xref: /petsc/src/snes/interface/snes.c (revision e5148a0bccdcd3ff01bf6eb239cc2c944c18e205)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h"  I*/
207475bc1SBarry Smith #include <petscdmshell.h>
3d96771aaSLisandro Dalcin #include <petscdraw.h>
4a01aa210SMatthew G. Knepley #include <petscds.h>
534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
606fc46c8SMatthew G. Knepley #include <petscconvest.h>
79b94acceSBarry Smith 
8ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
90298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
108ba1e511SMatthew Knepley 
118ba1e511SMatthew Knepley /* Logging support */
1222c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16dc4c0fb0SBarry Smith   SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
17e113a28aSBarry Smith 
18c3339decSBarry Smith   Logically Collective
19e113a28aSBarry Smith 
20e113a28aSBarry Smith   Input Parameters:
21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
22f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` indicates you want the error generated
23e113a28aSBarry Smith 
2420f4b53cSBarry Smith   Options Database Key:
2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
26e113a28aSBarry Smith 
27e113a28aSBarry Smith   Level: intermediate
28e113a28aSBarry Smith 
29f6dfbefdSBarry Smith   Note:
30f6dfbefdSBarry Smith   Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
31f6dfbefdSBarry Smith   to determine if it has converged. Otherwise the solution may be inaccurate or wrong
32e113a28aSBarry Smith 
331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
34e113a28aSBarry Smith @*/
35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
36d71ae5a4SJacob Faibussowitsch {
37e113a28aSBarry Smith   PetscFunctionBegin;
38e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flg, 2);
40e113a28aSBarry Smith   snes->errorifnotconverged = flg;
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42e113a28aSBarry Smith }
43e113a28aSBarry Smith 
44e113a28aSBarry Smith /*@
45f6dfbefdSBarry Smith   SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
46e113a28aSBarry Smith 
47e113a28aSBarry Smith   Not Collective
48e113a28aSBarry Smith 
49e113a28aSBarry Smith   Input Parameter:
50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
51e113a28aSBarry Smith 
52e113a28aSBarry Smith   Output Parameter:
53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
54e113a28aSBarry Smith 
55e113a28aSBarry Smith   Level: intermediate
56e113a28aSBarry Smith 
571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
58e113a28aSBarry Smith @*/
59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
60d71ae5a4SJacob Faibussowitsch {
61e113a28aSBarry Smith   PetscFunctionBegin;
62e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
634f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
64e113a28aSBarry Smith   *flag = snes->errorifnotconverged;
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66e113a28aSBarry Smith }
67e113a28aSBarry Smith 
684fc747eaSLawrence Mitchell /*@
69dc4c0fb0SBarry Smith   SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution
704fc747eaSLawrence Mitchell 
71c3339decSBarry Smith   Logically Collective
724fc747eaSLawrence Mitchell 
734fc747eaSLawrence Mitchell   Input Parameters:
74f6dfbefdSBarry Smith + snes - the shell `SNES`
75f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` to always compute the residual
764fc747eaSLawrence Mitchell 
774fc747eaSLawrence Mitchell   Level: advanced
784fc747eaSLawrence Mitchell 
79f6dfbefdSBarry Smith   Note:
80f6dfbefdSBarry Smith   Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it
81f6dfbefdSBarry Smith   to save time.
82f6dfbefdSBarry Smith 
83420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()`
844fc747eaSLawrence Mitchell @*/
85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
86d71ae5a4SJacob Faibussowitsch {
874fc747eaSLawrence Mitchell   PetscFunctionBegin;
884fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
894fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = flg;
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914fc747eaSLawrence Mitchell }
924fc747eaSLawrence Mitchell 
934fc747eaSLawrence Mitchell /*@
94f6dfbefdSBarry Smith   SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution
954fc747eaSLawrence Mitchell 
96c3339decSBarry Smith   Logically Collective
974fc747eaSLawrence Mitchell 
984fc747eaSLawrence Mitchell   Input Parameter:
99f6dfbefdSBarry Smith . snes - the `SNES` context
1004fc747eaSLawrence Mitchell 
1014fc747eaSLawrence Mitchell   Output Parameter:
102f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed
1034fc747eaSLawrence Mitchell 
1044fc747eaSLawrence Mitchell   Level: advanced
1054fc747eaSLawrence Mitchell 
106420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1074fc747eaSLawrence Mitchell @*/
108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
109d71ae5a4SJacob Faibussowitsch {
1104fc747eaSLawrence Mitchell   PetscFunctionBegin;
1114fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1124fc747eaSLawrence Mitchell   *flg = snes->alwayscomputesfinalresidual;
1133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1144fc747eaSLawrence Mitchell }
1154fc747eaSLawrence Mitchell 
116e725d27bSBarry Smith /*@
117f6dfbefdSBarry Smith   SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
118f0b84518SBarry Smith   in the functions domain. For example, a step with negative pressure.
1194936397dSBarry Smith 
120c3339decSBarry Smith   Logically Collective
1214936397dSBarry Smith 
1222fe279fdSBarry Smith   Input Parameter:
123f6dfbefdSBarry Smith . snes - the `SNES` context
1244936397dSBarry Smith 
12528529972SSatish Balay   Level: advanced
1264936397dSBarry Smith 
127ced0f3aeSBarry Smith   Notes:
128ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
129ced0f3aeSBarry Smith 
130ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
131ced0f3aeSBarry Smith 
132f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
133f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
134f0b84518SBarry Smith 
1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
136ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
1374936397dSBarry Smith @*/
138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
139d71ae5a4SJacob Faibussowitsch {
1404936397dSBarry Smith   PetscFunctionBegin;
1410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1425f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain");
1434936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1454936397dSBarry Smith }
1464936397dSBarry Smith 
1476a388c36SPeter Brune /*@
148f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
14907b62357SFande Kong 
150c3339decSBarry Smith   Logically Collective
15107b62357SFande Kong 
1522fe279fdSBarry Smith   Input Parameter:
153f6dfbefdSBarry Smith . snes - the `SNES` context
15407b62357SFande Kong 
15507b62357SFande Kong   Level: advanced
15607b62357SFande Kong 
157ced0f3aeSBarry Smith   Notes:
158ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
159ced0f3aeSBarry Smith 
160ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
161ced0f3aeSBarry Smith 
162f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
163f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
164f0b84518SBarry Smith 
1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
166ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
16707b62357SFande Kong @*/
168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
169d71ae5a4SJacob Faibussowitsch {
17007b62357SFande Kong   PetscFunctionBegin;
17107b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1725f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
17307b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
1743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17507b62357SFande Kong }
17607b62357SFande Kong 
17707b62357SFande Kong /*@
178f6dfbefdSBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
179420bcc1bSBarry Smith   each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode.
180b351a90bSFande Kong 
181c3339decSBarry Smith   Logically Collective
182b351a90bSFande Kong 
183b351a90bSFande Kong   Input Parameters:
18420f4b53cSBarry Smith + snes - the `SNES` context
185f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
186b351a90bSFande Kong 
187b351a90bSFande Kong   Level: advanced
188b351a90bSFande Kong 
189f6dfbefdSBarry Smith   Note:
190f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
191f6dfbefdSBarry Smith 
1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
193b351a90bSFande Kong @*/
194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
195d71ae5a4SJacob Faibussowitsch {
196b351a90bSFande Kong   PetscFunctionBegin;
197b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
198b351a90bSFande Kong   snes->checkjacdomainerror = flg;
1993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
200b351a90bSFande Kong }
201b351a90bSFande Kong 
202b351a90bSFande Kong /*@
203420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2048383d7d7SFande Kong 
205c3339decSBarry Smith   Logically Collective
2068383d7d7SFande Kong 
2072fe279fdSBarry Smith   Input Parameter:
208f6dfbefdSBarry Smith . snes - the `SNES` context
2098383d7d7SFande Kong 
2102fe279fdSBarry Smith   Output Parameter:
211420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2128383d7d7SFande Kong 
2138383d7d7SFande Kong   Level: advanced
2148383d7d7SFande Kong 
2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2168383d7d7SFande Kong @*/
217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
218d71ae5a4SJacob Faibussowitsch {
2198383d7d7SFande Kong   PetscFunctionBegin;
2208383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2214f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2228383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2248383d7d7SFande Kong }
2258383d7d7SFande Kong 
2268383d7d7SFande Kong /*@
227420bcc1bSBarry Smith   SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`
2286a388c36SPeter Brune 
229f6dfbefdSBarry Smith   Logically Collective
2306a388c36SPeter Brune 
2312fe279fdSBarry Smith   Input Parameter:
232f6dfbefdSBarry Smith . snes - the `SNES` context
2336a388c36SPeter Brune 
2342fe279fdSBarry Smith   Output Parameter:
235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2366a388c36SPeter Brune 
237f6dfbefdSBarry Smith   Level: developer
2386a388c36SPeter Brune 
2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2406a388c36SPeter Brune @*/
241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
242d71ae5a4SJacob Faibussowitsch {
2436a388c36SPeter Brune   PetscFunctionBegin;
2446a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2454f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
2466a388c36SPeter Brune   *domainerror = snes->domainerror;
2473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2486a388c36SPeter Brune }
2496a388c36SPeter Brune 
25007b62357SFande Kong /*@
251420bcc1bSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`
25207b62357SFande Kong 
253c3339decSBarry Smith   Logically Collective
25407b62357SFande Kong 
2552fe279fdSBarry Smith   Input Parameter:
256f6dfbefdSBarry Smith . snes - the `SNES` context
25707b62357SFande Kong 
2582fe279fdSBarry Smith   Output Parameter:
259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
26007b62357SFande Kong 
26107b62357SFande Kong   Level: advanced
26207b62357SFande Kong 
2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
26407b62357SFande Kong @*/
265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
266d71ae5a4SJacob Faibussowitsch {
26707b62357SFande Kong   PetscFunctionBegin;
26807b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2694f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
27007b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27207b62357SFande Kong }
27307b62357SFande Kong 
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     }
41963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
4209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42148a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4239566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4249566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42548a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4269b94acceSBarry Smith     if (snes->ksp_ewconv) {
427fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4289b94acceSBarry Smith       if (kctx) {
42963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4329b94acceSBarry Smith       }
4339b94acceSBarry Smith     }
434eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
436eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
43763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
438eb1f6c34SBarry Smith     }
439eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
441eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
443eb1f6c34SBarry Smith     }
4449566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4459566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
446789d8953SBarry Smith     if (snes->mf_operator) {
4479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
448789d8953SBarry Smith       pre = "Preconditioning ";
449789d8953SBarry Smith     }
4508404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4528404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
454789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
455789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
456789d8953SBarry Smith       MatFDColoring fdcoloring;
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
458789d8953SBarry Smith       if (fdcoloring) {
4599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
460789d8953SBarry Smith       } else {
4619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
462789d8953SBarry Smith       }
463996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4658404b7f3SBarry Smith     }
4660f5bd95cSBarry Smith   } else if (isstring) {
467317d6ea6SBarry Smith     const char *type;
4689566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4699566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
470dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47155849f57SBarry Smith   } else if (isbinary) {
47255849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47355849f57SBarry Smith     MPI_Comm    comm;
47455849f57SBarry Smith     PetscMPIInt rank;
47555849f57SBarry Smith     char        type[256];
47655849f57SBarry Smith 
4779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
479dd400576SPatrick Sanan     if (rank == 0) {
4809566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4819566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48355849f57SBarry Smith     }
484dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48572a02f06SBarry Smith   } else if (isdraw) {
48672a02f06SBarry Smith     PetscDraw draw;
48772a02f06SBarry Smith     char      str[36];
48889fd9fafSBarry Smith     PetscReal x, y, bottom, h;
48972a02f06SBarry Smith 
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4919566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4949566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49589fd9fafSBarry Smith     bottom = y - h;
4969566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
497dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
499536b137fSBarry Smith   } else if (issaws) {
500d45a07a7SBarry Smith     PetscMPIInt rank;
5012657e9d9SBarry Smith     const char *name;
502d45a07a7SBarry Smith 
5039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
505dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
506d45a07a7SBarry Smith       char dir[1024];
507d45a07a7SBarry Smith 
5089566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5099566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
510792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51148a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
513792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
514f05ece33SBarry Smith     }
515bfb97211SBarry Smith #endif
51672a02f06SBarry Smith   }
51772a02f06SBarry Smith   if (snes->linesearch) {
5189566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5209566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52219bcc07fSBarry Smith   }
523efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5259566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5274a0c5b0cSMatthew G Knepley   }
5289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5309566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5319566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5322c155ee1SBarry Smith   if (snes->usesksp) {
5339566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5372c155ee1SBarry Smith   }
53872a02f06SBarry Smith   if (isdraw) {
53972a02f06SBarry Smith     PetscDraw draw;
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5419566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5427f1410a3SPeter Brune   }
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5449b94acceSBarry Smith }
5459b94acceSBarry Smith 
54676b2cf59SMatthew Knepley /*
54776b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
54876b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
54976b2cf59SMatthew Knepley */
55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55376b2cf59SMatthew Knepley 
554ac226902SBarry Smith /*@C
555f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
55676b2cf59SMatthew Knepley 
55776b2cf59SMatthew Knepley   Not Collective
55876b2cf59SMatthew Knepley 
55976b2cf59SMatthew Knepley   Input Parameter:
56076b2cf59SMatthew Knepley . snescheck - function that checks for options
56176b2cf59SMatthew Knepley 
562420bcc1bSBarry Smith   Calling sequence of `snescheck`:
563420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
564420bcc1bSBarry Smith 
56576b2cf59SMatthew Knepley   Level: developer
56676b2cf59SMatthew Knepley 
5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
56876b2cf59SMatthew Knepley @*/
569420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
570d71ae5a4SJacob Faibussowitsch {
57176b2cf59SMatthew Knepley   PetscFunctionBegin;
57263a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57376b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57576b2cf59SMatthew Knepley }
57676b2cf59SMatthew Knepley 
577d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
578d71ae5a4SJacob Faibussowitsch {
579aa3661deSLisandro Dalcin   Mat          J;
580895c21f2SBarry Smith   MatNullSpace nullsp;
581aa3661deSLisandro Dalcin 
582aa3661deSLisandro Dalcin   PetscFunctionBegin;
5830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
584aa3661deSLisandro Dalcin 
58598613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
58698613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5879566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
58898613b67SLisandro Dalcin   }
58998613b67SLisandro Dalcin 
5900fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
591aa3661deSLisandro Dalcin   if (version == 1) {
5929566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5939566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5949566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5951e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
5960fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
5975f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
598570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
599f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
600aa3661deSLisandro Dalcin #else
6012479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
602aa3661deSLisandro Dalcin #endif
6030fdf79fbSJacob Faibussowitsch   }
604aa3661deSLisandro Dalcin 
60501c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
606895c21f2SBarry Smith   if (snes->jacobian) {
6079566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6081baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
609895c21f2SBarry Smith   }
610895c21f2SBarry Smith 
61163a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
612d3462f78SMatthew Knepley   if (hasOperator) {
613aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
614aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6159566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
616aa3661deSLisandro Dalcin   } else {
617aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
61801c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
619b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6209566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
621172a4300SPeter Brune     } else {
622789d8953SBarry Smith       KSP       ksp;
623789d8953SBarry Smith       PC        pc;
624789d8953SBarry Smith       PetscBool match;
625789d8953SBarry Smith 
6269566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
627aa3661deSLisandro Dalcin       /* Force no preconditioner */
6289566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6299566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6302698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
631aa3661deSLisandro Dalcin       if (!match) {
6329566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6339566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
634aa3661deSLisandro Dalcin       }
635aa3661deSLisandro Dalcin     }
636789d8953SBarry Smith   }
6379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639aa3661deSLisandro Dalcin }
640aa3661deSLisandro Dalcin 
641d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
642d71ae5a4SJacob Faibussowitsch {
643dfe15315SJed Brown   SNES snes = (SNES)ctx;
6440298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
645dfe15315SJed Brown 
646dfe15315SJed Brown   PetscFunctionBegin;
64716ebb321SJed Brown   if (PetscLogPrintInfo) {
64816ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6499566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6509566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6519566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6529566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65363a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel));
65416ebb321SJed Brown   }
655dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
656dfe15315SJed Brown   else {
6579566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
658dfe15315SJed Brown     Xfine = Xfine_named;
659dfe15315SJed Brown   }
6609566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
661907f5c5aSLawrence Mitchell   if (Inject) {
6629566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
663907f5c5aSLawrence Mitchell   } else {
6649566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6659566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
666907f5c5aSLawrence Mitchell   }
6679566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6689566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
670dfe15315SJed Brown }
671dfe15315SJed Brown 
672d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
673d71ae5a4SJacob Faibussowitsch {
67416ebb321SJed Brown   PetscFunctionBegin;
6759566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67716ebb321SJed Brown }
67816ebb321SJed Brown 
679a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
680a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
681d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
682d71ae5a4SJacob Faibussowitsch {
683caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
68497d931d1SStefano Zampini   DMSNES          sdm;
6850298fd71SBarry Smith   Vec             X, Xnamed = NULL;
686dfe15315SJed Brown   DM              dmsave;
6874e269d77SPeter Brune   void           *ctxsave;
6888434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
689caa4e7f2SJed Brown 
690caa4e7f2SJed Brown   PetscFunctionBegin;
691dfe15315SJed Brown   dmsave = snes->dm;
6929566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
693dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
69497d931d1SStefano Zampini   else {
695309d62e6SStefano Zampini     PetscBool has;
696309d62e6SStefano Zampini 
69797d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
698309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
699309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70097d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
701dfe15315SJed Brown     X = Xnamed;
7029566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7034e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
70448a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7054e269d77SPeter Brune   }
7064e269d77SPeter Brune 
7072b93b426SMatthew G. Knepley   /* Compute the operators */
70897d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
70997d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
71097d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71197d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
71297d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
71397d931d1SStefano Zampini 
71497d931d1SStefano Zampini     snes->vec_rhs = NULL;
71597d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
71697d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
71797d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
71897d931d1SStefano Zampini     snes->vec_rhs = saverhs;
71997d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
72097d931d1SStefano Zampini   }
72197d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
72297d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7239566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
72497d931d1SStefano Zampini 
7252b93b426SMatthew G. Knepley   /* Put the previous context back */
72648a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7274e269d77SPeter Brune 
7289566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
729dfe15315SJed Brown   snes->dm = dmsave;
7303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
731caa4e7f2SJed Brown }
732caa4e7f2SJed Brown 
7336cab3a1bSJed Brown /*@
734dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7356cab3a1bSJed Brown 
7366cab3a1bSJed Brown   Collective
7376cab3a1bSJed Brown 
7384165533cSJose E. Roman   Input Parameter:
73920f4b53cSBarry Smith . snes - `SNES` object to configure
7406cab3a1bSJed Brown 
7416cab3a1bSJed Brown   Level: developer
7426cab3a1bSJed Brown 
743dc4c0fb0SBarry Smith   Note:
744dc4c0fb0SBarry 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`
745dc4c0fb0SBarry Smith 
74673a84a35SBarry Smith   Developer Note:
74773a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
74873a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
74973a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
75073a84a35SBarry Smith 
7511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7526cab3a1bSJed Brown @*/
753d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
754d71ae5a4SJacob Faibussowitsch {
7556cab3a1bSJed Brown   DM     dm;
756942e3340SBarry Smith   DMSNES sdm;
7576cab3a1bSJed Brown 
7586cab3a1bSJed Brown   PetscFunctionBegin;
7599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7609566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
76173a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7626cab3a1bSJed Brown     Mat   J;
7636cab3a1bSJed Brown     void *functx;
7649566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7659566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7669566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7679566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7689566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
770caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7716cab3a1bSJed Brown     Mat J, B;
7729566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7739566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7749566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7759566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
77606f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7779566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7799566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
780caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7811ba9b98eSMatthew G. Knepley     PetscDS   prob;
7826cab3a1bSJed Brown     Mat       J, B;
7831ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7841ba9b98eSMatthew G. Knepley 
7856cab3a1bSJed Brown     J = snes->jacobian;
7869566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7879566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7889566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7899566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7909566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7919566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7929566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7946cab3a1bSJed Brown   }
795caa4e7f2SJed Brown   {
796caa4e7f2SJed Brown     KSP ksp;
7979566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7989566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7999566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
800caa4e7f2SJed Brown   }
8013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8026cab3a1bSJed Brown }
8036cab3a1bSJed Brown 
804d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
805d71ae5a4SJacob Faibussowitsch {
8065e7c47f3SMatthew G. Knepley   PetscInt i;
8075e7c47f3SMatthew G. Knepley 
8085e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8093ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
8105e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
8115e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
8125e7c47f3SMatthew G. Knepley     PetscDraw             draw;
8135e7c47f3SMatthew G. Knepley     PetscReal             lpause;
8145e7c47f3SMatthew G. Knepley 
8155e7c47f3SMatthew G. Knepley     if (!vf) continue;
8165e7c47f3SMatthew G. Knepley     if (vf->lg) {
8175e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8185e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8199566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8209566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8219566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8229566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8239566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8245e7c47f3SMatthew G. Knepley     } else {
8255e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8265e7c47f3SMatthew G. Knepley 
8275e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8285e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8299566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8305e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8319566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8329566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8339566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8349566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8359566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8365e7c47f3SMatthew G. Knepley     }
8375e7c47f3SMatthew G. Knepley   }
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8395e7c47f3SMatthew G. Knepley }
8405e7c47f3SMatthew G. Knepley 
841fde5950dSBarry Smith /*@C
842fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
843fde5950dSBarry Smith 
844c3339decSBarry Smith   Collective
845fde5950dSBarry Smith 
846fde5950dSBarry Smith   Input Parameters:
847dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
848fde5950dSBarry Smith . name         - the monitor type one is seeking
849fde5950dSBarry Smith . help         - message indicating what monitoring is done
850fde5950dSBarry Smith . manual       - manual page for the monitor
851fde5950dSBarry Smith . monitor      - the monitor function
852f6dfbefdSBarry 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
853fde5950dSBarry Smith 
854420bcc1bSBarry Smith   Calling sequence of `monitor`:
855420bcc1bSBarry Smith + snes - the nonlinear solver context
856420bcc1bSBarry Smith . it   - the current iteration
857420bcc1bSBarry Smith . r    - the current function norm
858420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
859420bcc1bSBarry Smith 
860420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
861420bcc1bSBarry Smith + snes - the nonlinear solver context
862420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
863420bcc1bSBarry Smith 
864f6dfbefdSBarry Smith   Options Database Key:
865f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
866f6dfbefdSBarry Smith 
867f6dfbefdSBarry Smith   Level: advanced
868fde5950dSBarry Smith 
869648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
870db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
871e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
872db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
873c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
874db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
875db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
876fde5950dSBarry Smith @*/
877420bcc1bSBarry 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))
878d71ae5a4SJacob Faibussowitsch {
879fde5950dSBarry Smith   PetscViewer       viewer;
880fde5950dSBarry Smith   PetscViewerFormat format;
881fde5950dSBarry Smith   PetscBool         flg;
882fde5950dSBarry Smith 
883fde5950dSBarry Smith   PetscFunctionBegin;
884648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
885fde5950dSBarry Smith   if (flg) {
886d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8879566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
888648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8891baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8909566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
891fde5950dSBarry Smith   }
8923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
893fde5950dSBarry Smith }
894fde5950dSBarry Smith 
895a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
896d71ae5a4SJacob Faibussowitsch {
897a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
898a4598233SStefano Zampini 
8990f0abf79SStefano Zampini   PetscFunctionBegin;
9000f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
901a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
902a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
903a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
904a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
905a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
906a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9070f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
908a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9090f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9100f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9110f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9120f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9130f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9140f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9150f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9160f0abf79SStefano Zampini   PetscOptionsEnd();
9173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9180f0abf79SStefano Zampini }
9190f0abf79SStefano Zampini 
9209b94acceSBarry Smith /*@
921f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9229b94acceSBarry Smith 
923c3339decSBarry Smith   Collective
924c7afd0dbSLois Curfman McInnes 
9259b94acceSBarry Smith   Input Parameter:
926f6dfbefdSBarry Smith . snes - the `SNES` context
9279b94acceSBarry Smith 
92836851e7fSLois Curfman McInnes   Options Database Keys:
929f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
930ceaaa498SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
93170441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
932b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
933e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
934ceaaa498SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
935b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
936b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9374839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
938ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
939a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9403d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
941e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9423d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9434a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
944ceaaa498SBarry 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.
945fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
946fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
947fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
948fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9494619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
950459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9515e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
952e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
953e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
954ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
955b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
956ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
957e62ac41dSBarry 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.
958e62ac41dSBarry 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.
95982738288SBarry Smith 
960f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
961fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9624b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
96336851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
96436851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
96536851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
96636851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
96736851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
96836851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
96982738288SBarry Smith 
970dc4c0fb0SBarry Smith   Level: beginner
971dc4c0fb0SBarry Smith 
97211ca99fdSLois Curfman McInnes   Notes:
973ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
974ec5066bdSBarry Smith 
975420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
976420bcc1bSBarry Smith   and computing explicitly with
977f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
97883e2fdc7SBarry Smith 
979420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9809b94acceSBarry Smith @*/
981d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
982d71ae5a4SJacob Faibussowitsch {
9838afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
984d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
98504d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
986649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
98785385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9880f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
989c40d0f55SPeter Brune   PCSide      pcside;
990a64e098fSPeter Brune   const char *optionsprefix;
9919b94acceSBarry Smith 
9923a40ed3dSBarry Smith   PetscFunctionBegin;
9930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9949566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
995d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
996639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
998d64ed03dSBarry Smith   if (flg) {
9999566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
10007adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
10019566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
1002d64ed03dSBarry Smith   }
10039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
1005186905e3SBarry Smith 
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
10079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
10099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
10109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
10119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
10129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
101585385478SLisandro Dalcin 
10169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1017a8054027SBarry Smith   if (flg) {
10185f80ce2aSJacob 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");
10199566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1020a8054027SBarry Smith   }
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10221baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1024e35cf81dSBarry Smith   if (flg) {
10255f80ce2aSJacob 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");
10269566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1027e35cf81dSBarry Smith   }
10289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10291baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
103037ec4e1aSPeter Brune 
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10321baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1033a8054027SBarry Smith 
1034400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
103585385478SLisandro Dalcin   if (flg) {
103685385478SLisandro Dalcin     switch (indx) {
1037d71ae5a4SJacob Faibussowitsch     case 0:
1038d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1039d71ae5a4SJacob Faibussowitsch       break;
1040d71ae5a4SJacob Faibussowitsch     case 1:
1041d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1042d71ae5a4SJacob Faibussowitsch       break;
1043d71ae5a4SJacob Faibussowitsch     case 2:
1044d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1045d71ae5a4SJacob Faibussowitsch       break;
104685385478SLisandro Dalcin     }
104785385478SLisandro Dalcin   }
104885385478SLisandro Dalcin 
10499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10509566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1051fdacfa88SPeter Brune 
10529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10539566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1054186905e3SBarry Smith 
105585385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
105685385478SLisandro Dalcin 
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1058186905e3SBarry Smith 
10590f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10600f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1061a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1062186905e3SBarry Smith 
106390d69ab7SBarry Smith   flg = PETSC_FALSE;
10649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10659566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1066eabae89aSBarry Smith 
10679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10689566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10699566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1070eabae89aSBarry Smith 
10719566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10729566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10739566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10749566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10759566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10769566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10779566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10792db13446SMatthew G. Knepley 
10809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10819566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10825180491cSLisandro Dalcin 
108390d69ab7SBarry Smith   flg = PETSC_FALSE;
10849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1085459f5d12SBarry Smith   if (flg) {
1086459f5d12SBarry Smith     PetscViewer ctx;
1087e24b481bSBarry Smith 
10889566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10899566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1090459f5d12SBarry Smith   }
10912e7541e6SPeter Brune 
1092648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1093648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
109490d69ab7SBarry Smith   flg = PETSC_FALSE;
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10969566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1097c4421ceaSFande Kong 
1098c4421ceaSFande Kong   flg = PETSC_FALSE;
10999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11004b27c08aSLois Curfman McInnes   if (flg) {
11016cab3a1bSJed Brown     void *functx;
1102b1f624c7SBarry Smith     DM    dm;
11039566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1104800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11059566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11069566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11079566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11089b94acceSBarry Smith   }
1109639f9d9dSBarry Smith 
111044848bc4SPeter Brune   flg = PETSC_FALSE;
11119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11121baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
111397584545SPeter Brune 
111497584545SPeter Brune   flg = PETSC_FALSE;
11159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
111644848bc4SPeter Brune   if (flg) {
1117c52e227fSPeter Brune     DM dm;
11189566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1119800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11209566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11219566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
112244848bc4SPeter Brune   }
112344848bc4SPeter Brune 
1124aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1126d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1127a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1128d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1129a8248277SBarry Smith   }
1130aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1132d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1134d28543b3SPeter Brune 
1135c40d0f55SPeter Brune   flg = PETSC_FALSE;
11369566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11389566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1139c40d0f55SPeter Brune 
1140e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11418a70d858SHong Zhang   /*
11428a70d858SHong Zhang     Publish convergence information using SAWs
11438a70d858SHong Zhang   */
11448a70d858SHong Zhang   flg = PETSC_FALSE;
11459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11468a70d858SHong Zhang   if (flg) {
11478a70d858SHong Zhang     void *ctx;
11489566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11499566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11508a70d858SHong Zhang   }
11518a70d858SHong Zhang #endif
11528a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1153b90c6cbeSBarry Smith   {
1154b90c6cbeSBarry Smith     PetscBool set;
1155b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11569566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11571baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1158b90c6cbeSBarry Smith   }
1159b90c6cbeSBarry Smith #endif
1160b90c6cbeSBarry Smith 
116148a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
116276b2cf59SMatthew Knepley 
1163dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11645d973c19SBarry Smith 
11655d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1166dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1167d0609cedSBarry Smith   PetscOptionsEnd();
11684bbc92c1SBarry Smith 
1169d8d34be6SBarry Smith   if (snes->linesearch) {
11709566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11719566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1172d8d34be6SBarry Smith   }
11739e764e56SPeter Brune 
11746aa5e7e9SBarry Smith   if (snes->usesksp) {
11759566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11769566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11779566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11786aa5e7e9SBarry Smith   }
11796991f827SBarry Smith 
1180b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11819566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
118348a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11841baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1185b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1187b3cd9a81SMatthew G. Knepley }
1188b3cd9a81SMatthew G. Knepley 
1189b3cd9a81SMatthew G. Knepley /*@
1190420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1191b3cd9a81SMatthew G. Knepley 
1192c3339decSBarry Smith   Collective
1193b3cd9a81SMatthew G. Knepley 
1194b3cd9a81SMatthew G. Knepley   Input Parameter:
1195f6dfbefdSBarry Smith . snes - the `SNES` context
1196b3cd9a81SMatthew G. Knepley 
1197420bcc1bSBarry Smith   Level: advanced
1198b3cd9a81SMatthew G. Knepley 
11991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1200b3cd9a81SMatthew G. Knepley @*/
1201d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1202d71ae5a4SJacob Faibussowitsch {
1203b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12049566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12069b94acceSBarry Smith }
12079b94acceSBarry Smith 
1208bb9467b5SJed Brown /*@C
1209d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1210d25893d9SBarry Smith   the nonlinear solvers.
1211d25893d9SBarry Smith 
1212dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1213d25893d9SBarry Smith 
1214d25893d9SBarry Smith   Input Parameters:
1215f6dfbefdSBarry Smith + snes    - the `SNES` context
1216d25893d9SBarry Smith . compute - function to compute the context
1217d25893d9SBarry Smith - destroy - function to destroy the context
1218d25893d9SBarry Smith 
1219420bcc1bSBarry Smith   Calling sequence of `compute`:
1220420bcc1bSBarry Smith + snes - the `SNES` context
1221420bcc1bSBarry Smith - ctx  - context to be computed
1222420bcc1bSBarry Smith 
1223420bcc1bSBarry Smith   Calling sequence of `destroy`:
1224420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1225420bcc1bSBarry Smith 
1226d25893d9SBarry Smith   Level: intermediate
1227d25893d9SBarry Smith 
1228f6dfbefdSBarry Smith   Note:
1229f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1230f6dfbefdSBarry Smith 
1231f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1232f6dfbefdSBarry Smith 
123342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1234d25893d9SBarry Smith @*/
1235420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1236d71ae5a4SJacob Faibussowitsch {
1237d25893d9SBarry Smith   PetscFunctionBegin;
1238d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1239d25893d9SBarry Smith   snes->ops->usercompute = compute;
1240d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1242d25893d9SBarry Smith }
1243a847f771SSatish Balay 
1244b07ff414SBarry Smith /*@
1245f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12469b94acceSBarry Smith 
1247c3339decSBarry Smith   Logically Collective
1248fee21e36SBarry Smith 
1249c7afd0dbSLois Curfman McInnes   Input Parameters:
1250f6dfbefdSBarry Smith + snes - the `SNES` context
1251c7afd0dbSLois Curfman McInnes - usrP - optional user context
1252c7afd0dbSLois Curfman McInnes 
125336851e7fSLois Curfman McInnes   Level: intermediate
125436851e7fSLois Curfman McInnes 
1255f6dfbefdSBarry Smith   Notes:
1256f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1257f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1258f6dfbefdSBarry Smith 
1259f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1260f6dfbefdSBarry Smith 
1261420bcc1bSBarry Smith   Fortran Note:
1262dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1263420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1264daf670e6SBarry Smith 
12651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12669b94acceSBarry Smith @*/
1267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1268d71ae5a4SJacob Faibussowitsch {
1269b07ff414SBarry Smith   KSP ksp;
12701b2093e4SBarry Smith 
12713a40ed3dSBarry Smith   PetscFunctionBegin;
12720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12739566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12749566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12759b94acceSBarry Smith   snes->user = usrP;
12763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12779b94acceSBarry Smith }
127874679c65SBarry Smith 
1279b07ff414SBarry Smith /*@
12809b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1281420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12829b94acceSBarry Smith 
1283c7afd0dbSLois Curfman McInnes   Not Collective
1284c7afd0dbSLois Curfman McInnes 
12859b94acceSBarry Smith   Input Parameter:
1286f6dfbefdSBarry Smith . snes - `SNES` context
12879b94acceSBarry Smith 
12889b94acceSBarry Smith   Output Parameter:
12899b94acceSBarry Smith . usrP - user context
12909b94acceSBarry Smith 
129136851e7fSLois Curfman McInnes   Level: intermediate
129236851e7fSLois Curfman McInnes 
1293420bcc1bSBarry Smith   Fortran Note:
1294dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1295420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1296dc4c0fb0SBarry Smith 
1297420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
12989b94acceSBarry Smith @*/
1299d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1300d71ae5a4SJacob Faibussowitsch {
13013a40ed3dSBarry Smith   PetscFunctionBegin;
13020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1303e71120c6SJed Brown   *(void **)usrP = snes->user;
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13059b94acceSBarry Smith }
130674679c65SBarry Smith 
13079b94acceSBarry Smith /*@
1308420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13093565c898SBarry Smith 
1310dc4c0fb0SBarry Smith   Logically Collective
13113565c898SBarry Smith 
13123565c898SBarry Smith   Input Parameters:
1313f6dfbefdSBarry Smith + snes        - `SNES` context
1314f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1315f6dfbefdSBarry 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
1316420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13173565c898SBarry Smith 
1318f6dfbefdSBarry Smith   Options Database Keys:
131901c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1320f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1321ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1322ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13233565c898SBarry Smith 
13243565c898SBarry Smith   Level: intermediate
13253565c898SBarry Smith 
1326f6dfbefdSBarry Smith   Note:
1327420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1328420bcc1bSBarry Smith   and computing explicitly with
1329f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1330ec5066bdSBarry Smith 
1331420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13323565c898SBarry Smith @*/
1333d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1334d71ae5a4SJacob Faibussowitsch {
13353565c898SBarry Smith   PetscFunctionBegin;
13363565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
133788b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
133888b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13394ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13403565c898SBarry Smith   snes->mf_operator = mf_operator;
13413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13423565c898SBarry Smith }
13433565c898SBarry Smith 
13443565c898SBarry Smith /*@
1345dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13463565c898SBarry Smith 
1347420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13483565c898SBarry Smith 
13493565c898SBarry Smith   Input Parameter:
1350f6dfbefdSBarry Smith . snes - `SNES` context
13513565c898SBarry Smith 
13523565c898SBarry Smith   Output Parameters:
1353f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1354f6dfbefdSBarry 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
13553565c898SBarry Smith 
13563565c898SBarry Smith   Level: intermediate
13573565c898SBarry Smith 
13581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13593565c898SBarry Smith @*/
1360d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1361d71ae5a4SJacob Faibussowitsch {
13623565c898SBarry Smith   PetscFunctionBegin;
13633565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13643565c898SBarry Smith   if (mf) *mf = snes->mf;
13653565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13673565c898SBarry Smith }
13683565c898SBarry Smith 
13693565c898SBarry Smith /*@
1370420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13719b94acceSBarry Smith 
1372c7afd0dbSLois Curfman McInnes   Not Collective
1373c7afd0dbSLois Curfman McInnes 
13749b94acceSBarry Smith   Input Parameter:
1375f6dfbefdSBarry Smith . snes - `SNES` context
13769b94acceSBarry Smith 
13779b94acceSBarry Smith   Output Parameter:
13789b94acceSBarry Smith . iter - iteration number
13799b94acceSBarry Smith 
1380dc4c0fb0SBarry Smith   Level: intermediate
1381dc4c0fb0SBarry Smith 
1382c8228a4eSBarry Smith   Notes:
1383c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1384c8228a4eSBarry Smith 
1385c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1386f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
138708405cd6SLois Curfman McInnes .vb
138808405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
138908405cd6SLois Curfman McInnes       if (!(it % 2)) {
139008405cd6SLois Curfman McInnes         [compute Jacobian here]
139108405cd6SLois Curfman McInnes       }
139208405cd6SLois Curfman McInnes .ve
1393f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1394f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1395c8228a4eSBarry Smith 
1396f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1397c04deec6SBarry Smith 
1398420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
13999b94acceSBarry Smith @*/
1400d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1401d71ae5a4SJacob Faibussowitsch {
14023a40ed3dSBarry Smith   PetscFunctionBegin;
14030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14044f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14059b94acceSBarry Smith   *iter = snes->iter;
14063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14079b94acceSBarry Smith }
140874679c65SBarry Smith 
1409360c497dSPeter Brune /*@
1410360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1411360c497dSPeter Brune 
1412360c497dSPeter Brune   Not Collective
1413360c497dSPeter Brune 
1414d8d19677SJose E. Roman   Input Parameters:
1415f6dfbefdSBarry Smith + snes - `SNES` context
1416a2b725a8SWilliam Gropp - iter - iteration number
1417360c497dSPeter Brune 
1418360c497dSPeter Brune   Level: developer
1419360c497dSPeter Brune 
1420420bcc1bSBarry Smith   Note:
1421420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1422420bcc1bSBarry Smith 
14231cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1424360c497dSPeter Brune @*/
1425d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1426d71ae5a4SJacob Faibussowitsch {
1427360c497dSPeter Brune   PetscFunctionBegin;
1428360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14299566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1430360c497dSPeter Brune   snes->iter = iter;
14319566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1433360c497dSPeter Brune }
1434360c497dSPeter Brune 
14359b94acceSBarry Smith /*@
1436b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1437420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14389b94acceSBarry Smith 
1439c7afd0dbSLois Curfman McInnes   Not Collective
1440c7afd0dbSLois Curfman McInnes 
14419b94acceSBarry Smith   Input Parameter:
1442f6dfbefdSBarry Smith . snes - `SNES` context
14439b94acceSBarry Smith 
14449b94acceSBarry Smith   Output Parameter:
14459b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14469b94acceSBarry Smith 
1447dc4c0fb0SBarry Smith   Level: intermediate
1448dc4c0fb0SBarry Smith 
1449f6dfbefdSBarry Smith   Note:
1450f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1451c96a6f78SLois Curfman McInnes 
14521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1453db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14549b94acceSBarry Smith @*/
1455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1456d71ae5a4SJacob Faibussowitsch {
14573a40ed3dSBarry Smith   PetscFunctionBegin;
14580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14594f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
146050ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146250ffb88aSMatthew Knepley }
146350ffb88aSMatthew Knepley 
146450ffb88aSMatthew Knepley /*@
1465b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1466420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
146750ffb88aSMatthew Knepley 
146850ffb88aSMatthew Knepley   Not Collective
146950ffb88aSMatthew Knepley 
147050ffb88aSMatthew Knepley   Input Parameters:
1471f6dfbefdSBarry Smith + snes     - `SNES` context
147250ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
147350ffb88aSMatthew Knepley 
1474420bcc1bSBarry Smith   Options Database Key:
1475420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1476420bcc1bSBarry Smith 
147750ffb88aSMatthew Knepley   Level: intermediate
147850ffb88aSMatthew Knepley 
1479420bcc1bSBarry Smith   Developer Note:
1480420bcc1bSBarry Smith   The options database key is wrong for this function name
1481420bcc1bSBarry Smith 
14821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1483db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
148450ffb88aSMatthew Knepley @*/
1485d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1486d71ae5a4SJacob Faibussowitsch {
148750ffb88aSMatthew Knepley   PetscFunctionBegin;
14880700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
148950ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149150ffb88aSMatthew Knepley }
149250ffb88aSMatthew Knepley 
149350ffb88aSMatthew Knepley /*@
1494b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1495420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
149650ffb88aSMatthew Knepley 
149750ffb88aSMatthew Knepley   Not Collective
149850ffb88aSMatthew Knepley 
149950ffb88aSMatthew Knepley   Input Parameter:
150020f4b53cSBarry Smith . snes - `SNES` context
150150ffb88aSMatthew Knepley 
150250ffb88aSMatthew Knepley   Output Parameter:
150350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
150450ffb88aSMatthew Knepley 
150550ffb88aSMatthew Knepley   Level: intermediate
150650ffb88aSMatthew Knepley 
15071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1508db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150950ffb88aSMatthew Knepley @*/
1510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1511d71ae5a4SJacob Faibussowitsch {
151250ffb88aSMatthew Knepley   PetscFunctionBegin;
15130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15144f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
151550ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15179b94acceSBarry Smith }
1518a847f771SSatish Balay 
15192541af92SBarry Smith /*@
15202541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1521420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15222541af92SBarry Smith 
15232541af92SBarry Smith   Not Collective
15242541af92SBarry Smith 
15252541af92SBarry Smith   Input Parameter:
1526f6dfbefdSBarry Smith . snes - `SNES` context
15272541af92SBarry Smith 
15282541af92SBarry Smith   Output Parameter:
15292541af92SBarry Smith . nfuncs - number of evaluations
15302541af92SBarry Smith 
15312541af92SBarry Smith   Level: intermediate
15322541af92SBarry Smith 
1533f6dfbefdSBarry Smith   Note:
1534f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1535971e163fSPeter Brune 
15361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15372541af92SBarry Smith @*/
1538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1539d71ae5a4SJacob Faibussowitsch {
15402541af92SBarry Smith   PetscFunctionBegin;
15410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15424f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15432541af92SBarry Smith   *nfuncs = snes->nfuncs;
15443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15452541af92SBarry Smith }
15462541af92SBarry Smith 
15473d4c4710SBarry Smith /*@
15483d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1549420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15503d4c4710SBarry Smith 
15513d4c4710SBarry Smith   Not Collective
15523d4c4710SBarry Smith 
15533d4c4710SBarry Smith   Input Parameter:
1554f6dfbefdSBarry Smith . snes - `SNES` context
15553d4c4710SBarry Smith 
15563d4c4710SBarry Smith   Output Parameter:
15573d4c4710SBarry Smith . nfails - number of failed solves
15583d4c4710SBarry Smith 
1559f6dfbefdSBarry Smith   Options Database Key:
15609d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15619d85da0cSMatthew G. Knepley 
1562f6dfbefdSBarry Smith   Level: intermediate
1563f6dfbefdSBarry Smith 
1564f6dfbefdSBarry Smith   Note:
1565f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15663d4c4710SBarry Smith 
15671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15683d4c4710SBarry Smith @*/
1569d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1570d71ae5a4SJacob Faibussowitsch {
15713d4c4710SBarry Smith   PetscFunctionBegin;
15720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15734f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15743d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15763d4c4710SBarry Smith }
15773d4c4710SBarry Smith 
15783d4c4710SBarry Smith /*@
15793d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1580f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15813d4c4710SBarry Smith 
1582c3339decSBarry Smith   Logically Collective
15833d4c4710SBarry Smith 
15843d4c4710SBarry Smith   Input Parameters:
1585f6dfbefdSBarry Smith + snes     - `SNES` context
15863d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15873d4c4710SBarry Smith 
1588f6dfbefdSBarry Smith   Options Database Key:
15899d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15909d85da0cSMatthew G. Knepley 
1591dc4c0fb0SBarry Smith   Level: intermediate
1592dc4c0fb0SBarry Smith 
1593f6dfbefdSBarry Smith   Note:
1594f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15953d4c4710SBarry Smith 
1596420bcc1bSBarry Smith   Developer Note:
1597420bcc1bSBarry Smith   The options database key is wrong for this function name
1598420bcc1bSBarry Smith 
15991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16003d4c4710SBarry Smith @*/
1601d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1602d71ae5a4SJacob Faibussowitsch {
16033d4c4710SBarry Smith   PetscFunctionBegin;
16040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1605c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
16063d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
16073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16083d4c4710SBarry Smith }
16093d4c4710SBarry Smith 
16103d4c4710SBarry Smith /*@
16113d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1612f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16133d4c4710SBarry Smith 
16143d4c4710SBarry Smith   Not Collective
16153d4c4710SBarry Smith 
16163d4c4710SBarry Smith   Input Parameter:
1617f6dfbefdSBarry Smith . snes - `SNES` context
16183d4c4710SBarry Smith 
16193d4c4710SBarry Smith   Output Parameter:
16203d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16213d4c4710SBarry Smith 
16223d4c4710SBarry Smith   Level: intermediate
16233d4c4710SBarry Smith 
1624f6dfbefdSBarry Smith   Note:
1625f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16263d4c4710SBarry Smith 
16271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16283d4c4710SBarry Smith @*/
1629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1630d71ae5a4SJacob Faibussowitsch {
16313d4c4710SBarry Smith   PetscFunctionBegin;
16320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16334f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16343d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16363d4c4710SBarry Smith }
16373d4c4710SBarry Smith 
1638c96a6f78SLois Curfman McInnes /*@
1639b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1640420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1641c96a6f78SLois Curfman McInnes 
1642c7afd0dbSLois Curfman McInnes   Not Collective
1643c7afd0dbSLois Curfman McInnes 
1644c96a6f78SLois Curfman McInnes   Input Parameter:
1645f6dfbefdSBarry Smith . snes - `SNES` context
1646c96a6f78SLois Curfman McInnes 
1647c96a6f78SLois Curfman McInnes   Output Parameter:
1648c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1649c96a6f78SLois Curfman McInnes 
1650dc4c0fb0SBarry Smith   Level: intermediate
1651dc4c0fb0SBarry Smith 
1652c96a6f78SLois Curfman McInnes   Notes:
1653f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1654c96a6f78SLois Curfman McInnes 
1655f6dfbefdSBarry 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
1656f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1657010be392SBarry Smith 
16581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1659c96a6f78SLois Curfman McInnes @*/
1660d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1661d71ae5a4SJacob Faibussowitsch {
16623a40ed3dSBarry Smith   PetscFunctionBegin;
16630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16644f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1665c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1667c96a6f78SLois Curfman McInnes }
1668c96a6f78SLois Curfman McInnes 
1669971e163fSPeter Brune /*@
1670971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1671f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1672971e163fSPeter Brune 
1673c3339decSBarry Smith   Logically Collective
1674971e163fSPeter Brune 
1675d8d19677SJose E. Roman   Input Parameters:
1676f6dfbefdSBarry Smith + snes  - `SNES` context
1677f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1678971e163fSPeter Brune 
1679971e163fSPeter Brune   Level: developer
1680971e163fSPeter Brune 
16811cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1682971e163fSPeter Brune @*/
1683d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1684d71ae5a4SJacob Faibussowitsch {
1685971e163fSPeter Brune   PetscFunctionBegin;
1686971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1687971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1688971e163fSPeter Brune   snes->counters_reset = reset;
16893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1690971e163fSPeter Brune }
1691971e163fSPeter Brune 
16922999313aSBarry Smith /*@
1693f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16942999313aSBarry Smith 
1695420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
16962999313aSBarry Smith 
16972999313aSBarry Smith   Input Parameters:
1698f6dfbefdSBarry Smith + snes - the `SNES` context
1699f6dfbefdSBarry Smith - ksp  - the `KSP` context
17002999313aSBarry Smith 
1701dc4c0fb0SBarry Smith   Level: developer
1702dc4c0fb0SBarry Smith 
17032999313aSBarry Smith   Notes:
1704f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17052999313aSBarry Smith   so this routine is rarely needed.
17062999313aSBarry Smith 
1707f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1708420bcc1bSBarry Smith   decreased by one when this is called.
17092999313aSBarry Smith 
171042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17112999313aSBarry Smith @*/
1712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1713d71ae5a4SJacob Faibussowitsch {
17142999313aSBarry Smith   PetscFunctionBegin;
17150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17160700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17172999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17199566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17202999313aSBarry Smith   snes->ksp = ksp;
17213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17222999313aSBarry Smith }
17232999313aSBarry Smith 
172452baeb72SSatish Balay /*@
1725dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17269b94acceSBarry Smith 
1727d083f849SBarry Smith   Collective
1728c7afd0dbSLois Curfman McInnes 
1729f6dfbefdSBarry Smith   Input Parameter:
1730906ed7ccSBarry Smith . comm - MPI communicator
17319b94acceSBarry Smith 
17329b94acceSBarry Smith   Output Parameter:
173320f4b53cSBarry Smith . outsnes - the new `SNES` context
17349b94acceSBarry Smith 
1735c7afd0dbSLois Curfman McInnes   Options Database Keys:
1736dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1737dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1738dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1739dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1740c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1741c1f60f51SBarry Smith 
174236851e7fSLois Curfman McInnes   Level: beginner
174336851e7fSLois Curfman McInnes 
174495452b02SPatrick Sanan   Developer Notes:
1745f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1746efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1747f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1748f6dfbefdSBarry Smith   in `SNESView()`.
1749efd4aadfSBarry Smith 
1750f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1751f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1752f6dfbefdSBarry Smith 
1753dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1754efd4aadfSBarry Smith 
1755e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17569b94acceSBarry Smith @*/
1757d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1758d71ae5a4SJacob Faibussowitsch {
17599b94acceSBarry Smith   SNES       snes;
1760fa9f3622SBarry Smith   SNESKSPEW *kctx;
176137fcc0dbSBarry Smith 
17623a40ed3dSBarry Smith   PetscFunctionBegin;
17634f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
17649566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17658ba1e511SMatthew Knepley 
17669566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17678d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17682c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
176988976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17709b94acceSBarry Smith   snes->max_its              = 50;
17719750a799SBarry Smith   snes->max_funcs            = 10000;
17729b94acceSBarry Smith   snes->norm                 = 0.0;
1773c1e67a49SFande Kong   snes->xnorm                = 0.0;
1774c1e67a49SFande Kong   snes->ynorm                = 0.0;
1775365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17766c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17778ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1778b4874afaSBarry Smith   snes->ttol                 = 0.0;
17798ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17808ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17818ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1782e37c518bSBarry Smith   snes->divtol               = 1.e4;
1783e37c518bSBarry Smith   snes->rnorm0               = 0;
17849b94acceSBarry Smith   snes->nfuncs               = 0;
178550ffb88aSMatthew Knepley   snes->numFailures          = 0;
178650ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17877a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1788e35cf81dSBarry Smith   snes->lagjacobian          = 1;
178937ec4e1aSPeter Brune   snes->jac_iter             = 0;
179037ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1791a8054027SBarry Smith   snes->lagpreconditioner    = 1;
179237ec4e1aSPeter Brune   snes->pre_iter             = 0;
179337ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1794639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1795c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17969e5d0892SLisandro Dalcin   snes->data                 = NULL;
17974dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1798186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17996f24a144SLois Curfman McInnes   snes->nwork                = 0;
18009e5d0892SLisandro Dalcin   snes->work                 = NULL;
180158c9b817SLisandro Dalcin   snes->nvwork               = 0;
18029e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1803758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1804758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18050298fd71SBarry Smith   snes->conv_hist            = NULL;
18060298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1807758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1808971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1809e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1810184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1811efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1812b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1813c40d0f55SPeter Brune 
1814d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1815d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1816d8f46077SPeter Brune   snes->mf_version  = 1;
1817d8f46077SPeter Brune 
18183d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18193d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18203d4c4710SBarry Smith 
1821349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
182276bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1823349187a7SBarry Smith 
18244fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18254fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18264fc747eaSLawrence Mitchell 
18279b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18284dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1829f5af7f23SKarl Rupp 
18309b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18319b94acceSBarry Smith   kctx->version     = 2;
18320f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18339b94acceSBarry Smith                              this was too large for some test cases */
183475567043SBarry Smith   kctx->rtol_last   = 0.0;
18350f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18369b94acceSBarry Smith   kctx->gamma       = 1.0;
18370f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
183871f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18390f0abf79SStefano Zampini   kctx->threshold   = 0.1;
184075567043SBarry Smith   kctx->lresid_last = 0.0;
184175567043SBarry Smith   kctx->norm_last   = 0.0;
18429b94acceSBarry Smith 
18430f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18440f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18450f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18460f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18470f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18480f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18490f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18500f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18510f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18520f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18530f0abf79SStefano Zampini 
18549b94acceSBarry Smith   *outsnes = snes;
18553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18569b94acceSBarry Smith }
18579b94acceSBarry Smith 
18589b94acceSBarry Smith /*@C
18599b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1860f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18619b94acceSBarry Smith   equations.
18629b94acceSBarry Smith 
1863c3339decSBarry Smith   Logically Collective
1864fee21e36SBarry Smith 
1865c7afd0dbSLois Curfman McInnes   Input Parameters:
1866f6dfbefdSBarry Smith + snes - the `SNES` context
1867dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
18688434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1869c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1870dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18719b94acceSBarry Smith 
187236851e7fSLois Curfman McInnes   Level: beginner
187336851e7fSLois Curfman McInnes 
18748434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
18759b94acceSBarry Smith @*/
18768434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1877d71ae5a4SJacob Faibussowitsch {
18786cab3a1bSJed Brown   DM dm;
18796cab3a1bSJed Brown 
18803a40ed3dSBarry Smith   PetscFunctionBegin;
18810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1882d2a683ecSLisandro Dalcin   if (r) {
1883d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1884d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18859566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18869566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
188785385478SLisandro Dalcin     snes->vec_func = r;
1888d2a683ecSLisandro Dalcin   }
18899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18909566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
189148a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18939b94acceSBarry Smith }
18949b94acceSBarry Smith 
1895e4ed7901SPeter Brune /*@C
18960b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1897e4ed7901SPeter Brune 
1898c3339decSBarry Smith   Logically Collective
1899e4ed7901SPeter Brune 
1900e4ed7901SPeter Brune   Input Parameters:
1901f6dfbefdSBarry Smith + snes - the `SNES` context
1902e4ed7901SPeter Brune - f    - vector to store function value
1903e4ed7901SPeter Brune 
1904dc4c0fb0SBarry Smith   Level: developer
1905dc4c0fb0SBarry Smith 
1906e4ed7901SPeter Brune   Notes:
1907e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1908e4ed7901SPeter Brune 
1909f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1910e4ed7901SPeter Brune 
19111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1912e4ed7901SPeter Brune @*/
1913d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1914d71ae5a4SJacob Faibussowitsch {
1915e4ed7901SPeter Brune   Vec vec_func;
1916e4ed7901SPeter Brune 
1917e4ed7901SPeter Brune   PetscFunctionBegin;
1918e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1919e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1920e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1921efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1922902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19233ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1924902f982fSPeter Brune   }
19259566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19269566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1927f5af7f23SKarl Rupp 
1928217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1930e4ed7901SPeter Brune }
1931e4ed7901SPeter Brune 
1932534ebe21SPeter Brune /*@
1933f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1934f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1935534ebe21SPeter Brune 
1936c3339decSBarry Smith   Logically Collective
1937534ebe21SPeter Brune 
1938534ebe21SPeter Brune   Input Parameters:
1939f6dfbefdSBarry Smith + snes         - the `SNES` context
1940365a6726SPeter Brune - normschedule - the frequency of norm computation
1941534ebe21SPeter Brune 
1942517f1916SMatthew G. Knepley   Options Database Key:
194367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1944517f1916SMatthew G. Knepley 
1945dc4c0fb0SBarry Smith   Level: advanced
1946dc4c0fb0SBarry Smith 
1947534ebe21SPeter Brune   Notes:
1948f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1949534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1950534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1951f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1952534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1953534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1954534ebe21SPeter Brune   their solution.
1955534ebe21SPeter Brune 
1956e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1957534ebe21SPeter Brune @*/
1958d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1959d71ae5a4SJacob Faibussowitsch {
1960534ebe21SPeter Brune   PetscFunctionBegin;
1961534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1962365a6726SPeter Brune   snes->normschedule = normschedule;
19633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1964534ebe21SPeter Brune }
1965534ebe21SPeter Brune 
1966534ebe21SPeter Brune /*@
1967f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1968f6dfbefdSBarry Smith   of the `SNES` method.
1969534ebe21SPeter Brune 
1970c3339decSBarry Smith   Logically Collective
1971534ebe21SPeter Brune 
1972534ebe21SPeter Brune   Input Parameters:
1973f6dfbefdSBarry Smith + snes         - the `SNES` context
1974365a6726SPeter Brune - normschedule - the type of the norm used
1975534ebe21SPeter Brune 
1976534ebe21SPeter Brune   Level: advanced
1977534ebe21SPeter Brune 
19781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1979534ebe21SPeter Brune @*/
1980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1981d71ae5a4SJacob Faibussowitsch {
1982534ebe21SPeter Brune   PetscFunctionBegin;
1983534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1984365a6726SPeter Brune   *normschedule = snes->normschedule;
19853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1986534ebe21SPeter Brune }
1987534ebe21SPeter Brune 
1988c5ce4427SMatthew G. Knepley /*@
1989c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1990c5ce4427SMatthew G. Knepley 
1991c3339decSBarry Smith   Logically Collective
1992c5ce4427SMatthew G. Knepley 
1993c5ce4427SMatthew G. Knepley   Input Parameters:
1994f6dfbefdSBarry Smith + snes - the `SNES` context
1995f6dfbefdSBarry Smith - norm - the value of the norm
1996c5ce4427SMatthew G. Knepley 
1997c5ce4427SMatthew G. Knepley   Level: developer
1998c5ce4427SMatthew G. Knepley 
19991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2000c5ce4427SMatthew G. Knepley @*/
2001d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2002d71ae5a4SJacob Faibussowitsch {
2003c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2004c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2005c5ce4427SMatthew G. Knepley   snes->norm = norm;
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2007c5ce4427SMatthew G. Knepley }
2008c5ce4427SMatthew G. Knepley 
2009c5ce4427SMatthew G. Knepley /*@
2010c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2011c5ce4427SMatthew G. Knepley 
2012c5ce4427SMatthew G. Knepley   Not Collective
2013c5ce4427SMatthew G. Knepley 
2014c5ce4427SMatthew G. Knepley   Input Parameter:
2015f6dfbefdSBarry Smith . snes - the `SNES` context
2016c5ce4427SMatthew G. Knepley 
2017c5ce4427SMatthew G. Knepley   Output Parameter:
2018c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2019c5ce4427SMatthew G. Knepley 
2020c5ce4427SMatthew G. Knepley   Level: developer
2021c5ce4427SMatthew G. Knepley 
20221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2023c5ce4427SMatthew G. Knepley @*/
2024d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2025d71ae5a4SJacob Faibussowitsch {
2026c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2027c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20284f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2029c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2031c5ce4427SMatthew G. Knepley }
2032c5ce4427SMatthew G. Knepley 
2033c1e67a49SFande Kong /*@
2034f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2035c1e67a49SFande Kong 
2036c1e67a49SFande Kong   Not Collective
2037c1e67a49SFande Kong 
2038c1e67a49SFande Kong   Input Parameter:
2039f6dfbefdSBarry Smith . snes - the `SNES` context
2040c1e67a49SFande Kong 
2041c1e67a49SFande Kong   Output Parameter:
2042c1e67a49SFande Kong . ynorm - the last computed update norm
2043c1e67a49SFande Kong 
2044c1e67a49SFande Kong   Level: developer
2045c1e67a49SFande Kong 
2046f6dfbefdSBarry Smith   Note:
2047f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2048f6dfbefdSBarry Smith 
20491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2050c1e67a49SFande Kong @*/
2051d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2052d71ae5a4SJacob Faibussowitsch {
2053c1e67a49SFande Kong   PetscFunctionBegin;
2054c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20554f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2056c1e67a49SFande Kong   *ynorm = snes->ynorm;
20573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2058c1e67a49SFande Kong }
2059c1e67a49SFande Kong 
2060c1e67a49SFande Kong /*@
20614591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2062c1e67a49SFande Kong 
2063c1e67a49SFande Kong   Not Collective
2064c1e67a49SFande Kong 
2065c1e67a49SFande Kong   Input Parameter:
2066f6dfbefdSBarry Smith . snes - the `SNES` context
2067c1e67a49SFande Kong 
2068c1e67a49SFande Kong   Output Parameter:
2069c1e67a49SFande Kong . xnorm - the last computed solution norm
2070c1e67a49SFande Kong 
2071c1e67a49SFande Kong   Level: developer
2072c1e67a49SFande Kong 
20731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2074c1e67a49SFande Kong @*/
2075d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2076d71ae5a4SJacob Faibussowitsch {
2077c1e67a49SFande Kong   PetscFunctionBegin;
2078c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20794f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2080c1e67a49SFande Kong   *xnorm = snes->xnorm;
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2082c1e67a49SFande Kong }
2083c1e67a49SFande Kong 
2084cc4c1da9SBarry Smith /*@
2085f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2086f6dfbefdSBarry Smith   of the `SNES` method.
208747073ea2SPeter Brune 
2088c3339decSBarry Smith   Logically Collective
208947073ea2SPeter Brune 
209047073ea2SPeter Brune   Input Parameters:
2091f6dfbefdSBarry Smith + snes - the `SNES` context
2092f6dfbefdSBarry Smith - type - the function type
209347073ea2SPeter Brune 
209447073ea2SPeter Brune   Level: developer
209547073ea2SPeter Brune 
2096420bcc1bSBarry Smith   Values of the function type\:
2097f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2098f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2099f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2100f6dfbefdSBarry Smith 
2101420bcc1bSBarry Smith   Note:
2102f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2103f6dfbefdSBarry Smith 
21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
210547073ea2SPeter Brune @*/
2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2107d71ae5a4SJacob Faibussowitsch {
210847073ea2SPeter Brune   PetscFunctionBegin;
210947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
211047073ea2SPeter Brune   snes->functype = type;
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211247073ea2SPeter Brune }
211347073ea2SPeter Brune 
2114cc4c1da9SBarry Smith /*@
2115f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
211647073ea2SPeter Brune   of the SNES method.
211747073ea2SPeter Brune 
2118c3339decSBarry Smith   Logically Collective
211947073ea2SPeter Brune 
212047073ea2SPeter Brune   Input Parameters:
2121f6dfbefdSBarry Smith + snes - the `SNES` context
2122f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
212347073ea2SPeter Brune 
212447073ea2SPeter Brune   Level: advanced
212547073ea2SPeter Brune 
21261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
212747073ea2SPeter Brune @*/
2128d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2129d71ae5a4SJacob Faibussowitsch {
213047073ea2SPeter Brune   PetscFunctionBegin;
213147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
213247073ea2SPeter Brune   *type = snes->functype;
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2134534ebe21SPeter Brune }
2135534ebe21SPeter Brune 
2136c79ef259SPeter Brune /*@C
2137be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2138c79ef259SPeter Brune   use with composed nonlinear solvers.
2139c79ef259SPeter Brune 
2140c79ef259SPeter Brune   Input Parameters:
21419bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
21428434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
2143c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2144dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2145c79ef259SPeter Brune 
2146dc4c0fb0SBarry Smith   Level: intermediate
2147dc4c0fb0SBarry Smith 
2148f6dfbefdSBarry Smith   Note:
2149f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2150f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2151c79ef259SPeter Brune 
21528434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2153c79ef259SPeter Brune @*/
21548434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2155d71ae5a4SJacob Faibussowitsch {
21566cab3a1bSJed Brown   DM dm;
21576cab3a1bSJed Brown 
2158646217ecSPeter Brune   PetscFunctionBegin;
21596cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21609566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2163646217ecSPeter Brune }
2164646217ecSPeter Brune 
2165bbc1464cSBarry Smith /*
2166bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2167bbc1464cSBarry Smith    changed during the KSPSolve()
2168bbc1464cSBarry Smith */
2169d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2170d71ae5a4SJacob Faibussowitsch {
2171bbc1464cSBarry Smith   DM     dm;
2172bbc1464cSBarry Smith   DMSNES sdm;
2173bbc1464cSBarry Smith 
2174bbc1464cSBarry Smith   PetscFunctionBegin;
21759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2177bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2178bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2179792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21809566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21810df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2182ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2183792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21849566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2185bbc1464cSBarry Smith   } else {
2186792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21879566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2188bbc1464cSBarry Smith   }
21893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2190bbc1464cSBarry Smith }
2191bbc1464cSBarry Smith 
2192d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2193d71ae5a4SJacob Faibussowitsch {
2194e03ab78fSPeter Brune   DM     dm;
2195942e3340SBarry Smith   DMSNES sdm;
21966cab3a1bSJed Brown 
21978b0a5094SBarry Smith   PetscFunctionBegin;
21989566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21999566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22008b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2201bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2202792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22039566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2204792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22059566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2206bbc1464cSBarry Smith   } else {
2207792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22089566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2209bbc1464cSBarry Smith   }
22103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22118b0a5094SBarry Smith }
22128b0a5094SBarry Smith 
2213d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2214d71ae5a4SJacob Faibussowitsch {
22158b0a5094SBarry Smith   PetscFunctionBegin;
2216e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2217bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22189566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22199566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22218b0a5094SBarry Smith }
22228b0a5094SBarry Smith 
22238b0a5094SBarry Smith /*@C
22241d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22258b0a5094SBarry Smith 
2226c3339decSBarry Smith   Logically Collective
22278b0a5094SBarry Smith 
22288b0a5094SBarry Smith   Input Parameters:
2229f6dfbefdSBarry Smith + snes - the `SNES` context
2230dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22318434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
22326b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2233dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22348434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2235dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2236dc4c0fb0SBarry Smith 
2237dc4c0fb0SBarry Smith   Level: intermediate
22388b0a5094SBarry Smith 
22398b0a5094SBarry Smith   Notes:
22406b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2241f450aa47SBarry 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.
2242f450aa47SBarry Smith 
2243f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22448b0a5094SBarry Smith 
22451d27aa22SBarry 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}$.
22461d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
22478b0a5094SBarry Smith 
2248dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22498b0a5094SBarry Smith 
22500d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22511d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
22528b0a5094SBarry Smith 
22538b0a5094SBarry 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
22541d27aa22SBarry 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
22551d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
22568b0a5094SBarry Smith 
22571d27aa22SBarry 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
2258f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22596b7fb656SBarry Smith 
226015229ffcSPierre 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.
22616b7fb656SBarry Smith 
2262dc4c0fb0SBarry 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
22636b7fb656SBarry 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
2264f6dfbefdSBarry 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`.
2265aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2266bbc1464cSBarry Smith 
22679bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
22688434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
22698b0a5094SBarry Smith @*/
22708434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2271d71ae5a4SJacob Faibussowitsch {
2272e03ab78fSPeter Brune   DM dm;
2273e03ab78fSPeter Brune 
22748b0a5094SBarry Smith   PetscFunctionBegin;
22758b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22769566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22779566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22789566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22799566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22809566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22828b0a5094SBarry Smith }
22838b0a5094SBarry Smith 
22847971a8bfSPeter Brune /*@C
22857971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22867971a8bfSPeter Brune 
2287f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22887971a8bfSPeter Brune 
22897971a8bfSPeter Brune   Input Parameter:
2290f6dfbefdSBarry Smith . snes - the `SNES` context
22917971a8bfSPeter Brune 
2292d8d19677SJose E. Roman   Output Parameters:
2293dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
22948434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2295dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2296dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
22978434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2298dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
22997971a8bfSPeter Brune 
23007971a8bfSPeter Brune   Level: advanced
23017971a8bfSPeter Brune 
23028434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23037971a8bfSPeter Brune @*/
23048434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2305d71ae5a4SJacob Faibussowitsch {
23067971a8bfSPeter Brune   DM dm;
23077971a8bfSPeter Brune 
23087971a8bfSPeter Brune   PetscFunctionBegin;
23097971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23109566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23119566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23129566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23139566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23157971a8bfSPeter Brune }
23167971a8bfSPeter Brune 
2317d25893d9SBarry Smith /*@C
2318dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2319d25893d9SBarry Smith 
2320c3339decSBarry Smith   Logically Collective
2321d25893d9SBarry Smith 
2322d25893d9SBarry Smith   Input Parameters:
2323f6dfbefdSBarry Smith + snes - the `SNES` context
23248434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2325d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2326dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2327d25893d9SBarry Smith 
2328d25893d9SBarry Smith   Level: intermediate
2329d25893d9SBarry Smith 
23308434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2331d25893d9SBarry Smith @*/
23328434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2333d71ae5a4SJacob Faibussowitsch {
2334d25893d9SBarry Smith   PetscFunctionBegin;
2335d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2336d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2337d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2339d25893d9SBarry Smith }
2340d25893d9SBarry Smith 
23411096aae1SMatthew Knepley /*@C
2342dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2343dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
23441096aae1SMatthew Knepley 
2345c3339decSBarry Smith   Logically Collective
23461096aae1SMatthew Knepley 
23471096aae1SMatthew Knepley   Input Parameter:
2348f6dfbefdSBarry Smith . snes - the `SNES` context
23491096aae1SMatthew Knepley 
23501096aae1SMatthew Knepley   Output Parameter:
2351dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
23521096aae1SMatthew Knepley 
23531096aae1SMatthew Knepley   Level: intermediate
23541096aae1SMatthew Knepley 
23551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23561096aae1SMatthew Knepley @*/
2357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2358d71ae5a4SJacob Faibussowitsch {
23591096aae1SMatthew Knepley   PetscFunctionBegin;
23600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23614f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
236285385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23641096aae1SMatthew Knepley }
23651096aae1SMatthew Knepley 
23669b94acceSBarry Smith /*@
2367f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23689b94acceSBarry Smith 
2369c3339decSBarry Smith   Collective
2370c7afd0dbSLois Curfman McInnes 
23719b94acceSBarry Smith   Input Parameters:
2372f6dfbefdSBarry Smith + snes - the `SNES` context
2373c7afd0dbSLois Curfman McInnes - x    - input vector
23749b94acceSBarry Smith 
23759b94acceSBarry Smith   Output Parameter:
2376f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23779b94acceSBarry Smith 
2378dc4c0fb0SBarry Smith   Level: developer
2379dc4c0fb0SBarry Smith 
238000677de2SStefano Zampini   Notes:
2381f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2382bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
238336851e7fSLois Curfman McInnes 
238400677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
238500677de2SStefano Zampini 
23861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23879b94acceSBarry Smith @*/
2388d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2389d71ae5a4SJacob Faibussowitsch {
23906cab3a1bSJed Brown   DM     dm;
2391942e3340SBarry Smith   DMSNES sdm;
23929b94acceSBarry Smith 
23933a40ed3dSBarry Smith   PetscFunctionBegin;
23940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23950700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23960700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2397c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2398c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2399e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2400184914b5SBarry Smith 
24019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24029566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24030fdf79fbSJacob 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().");
240432f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
240548a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24069566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24078ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24088ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2409800f99ffSJeremy L Thompson     {
2410800f99ffSJeremy L Thompson       void           *ctx;
24118434afd1SBarry Smith       SNESFunctionFn *computefunction;
2412800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2413800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2414800f99ffSJeremy L Thompson     }
24159566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
241648a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24170fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24189566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24190fdf79fbSJacob Faibussowitsch   }
24201baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2421ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2422422a814eSBarry Smith   /*
2423422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2424422a814eSBarry Smith      propagate the value to all processes
2425422a814eSBarry Smith   */
2426f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24289b94acceSBarry Smith }
24299b94acceSBarry Smith 
2430c79ef259SPeter Brune /*@
2431f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2432bbc1464cSBarry Smith 
2433c3339decSBarry Smith   Collective
2434bbc1464cSBarry Smith 
2435bbc1464cSBarry Smith   Input Parameters:
2436f6dfbefdSBarry Smith + snes - the `SNES` context
2437bbc1464cSBarry Smith - x    - input vector
2438bbc1464cSBarry Smith 
2439bbc1464cSBarry Smith   Output Parameter:
2440f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2441bbc1464cSBarry Smith 
2442dc4c0fb0SBarry Smith   Level: developer
2443dc4c0fb0SBarry Smith 
2444bbc1464cSBarry Smith   Notes:
2445420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2446bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2447bbc1464cSBarry Smith 
2448dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2449f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2450dd8e379bSPierre 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.
2451bbc1464cSBarry Smith 
24521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2453bbc1464cSBarry Smith @*/
2454d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2455d71ae5a4SJacob Faibussowitsch {
2456bbc1464cSBarry Smith   DM     dm;
2457bbc1464cSBarry Smith   DMSNES sdm;
2458bbc1464cSBarry Smith 
2459bbc1464cSBarry Smith   PetscFunctionBegin;
2460bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2461bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2462bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2463bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2464bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2465e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2466bbc1464cSBarry Smith 
24679566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24689566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24709566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2471bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2472bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2473792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24749566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2476bbc1464cSBarry Smith   snes->nfuncs++;
2477bbc1464cSBarry Smith   /*
2478bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2479bbc1464cSBarry Smith      propagate the value to all processes
2480bbc1464cSBarry Smith   */
2481f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2483bbc1464cSBarry Smith }
2484bbc1464cSBarry Smith 
2485bbc1464cSBarry Smith /*@
2486f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2487c79ef259SPeter Brune 
2488c3339decSBarry Smith   Collective
2489c79ef259SPeter Brune 
2490c79ef259SPeter Brune   Input Parameters:
2491f6dfbefdSBarry Smith + snes - the `SNES` context
2492c79ef259SPeter Brune . x    - input vector
2493c79ef259SPeter Brune - b    - rhs vector
2494c79ef259SPeter Brune 
2495c79ef259SPeter Brune   Output Parameter:
2496c79ef259SPeter Brune . x - new solution vector
2497c79ef259SPeter Brune 
2498dc4c0fb0SBarry Smith   Level: developer
2499dc4c0fb0SBarry Smith 
2500f6dfbefdSBarry Smith   Note:
2501f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2502c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2503c79ef259SPeter Brune   themselves.
2504c79ef259SPeter Brune 
25058434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2506c79ef259SPeter Brune @*/
2507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2508d71ae5a4SJacob Faibussowitsch {
25096cab3a1bSJed Brown   DM     dm;
2510942e3340SBarry Smith   DMSNES sdm;
2511646217ecSPeter Brune 
2512646217ecSPeter Brune   PetscFunctionBegin;
2513646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2514064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2515064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2516064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2517064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2518e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25209566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25219566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25220fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25239566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2524792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25259566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2528646217ecSPeter Brune }
2529646217ecSPeter Brune 
2530494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2531494a190aSStefano Zampini {
2532494a190aSStefano Zampini   Vec          X;
2533494a190aSStefano Zampini   PetscScalar *g;
2534494a190aSStefano Zampini   PetscReal    f, f2;
2535494a190aSStefano Zampini   PetscInt     low, high, N, i;
2536494a190aSStefano Zampini   PetscBool    flg;
2537494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2538494a190aSStefano Zampini 
2539494a190aSStefano Zampini   PetscFunctionBegin;
2540494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2541494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2542494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2543494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2544494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2545494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2546494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2547494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2548494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2549494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2550494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2551494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2552494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2553494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2554494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2555494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2556494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2557494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2558494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2559494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2560494a190aSStefano Zampini   }
2561494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2562494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2563494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2564494a190aSStefano Zampini }
2565494a190aSStefano Zampini 
2566494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2567494a190aSStefano Zampini {
2568494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2569494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2570494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2571494a190aSStefano Zampini   PetscScalar       dot;
2572494a190aSStefano Zampini   MPI_Comm          comm;
2573494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2574494a190aSStefano Zampini   PetscViewerFormat format;
2575494a190aSStefano Zampini   PetscInt          tabs;
2576494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
25778434afd1SBarry Smith   SNESObjectiveFn  *objective;
2578494a190aSStefano Zampini 
2579494a190aSStefano Zampini   PetscFunctionBegin;
2580494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2581494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2582494a190aSStefano Zampini 
2583494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2584494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2585494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2586494a190aSStefano Zampini   PetscOptionsEnd();
2587494a190aSStefano Zampini   if (!test) {
2588494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2589494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2590494a190aSStefano Zampini   }
2591494a190aSStefano Zampini 
2592494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2593494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2594494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2595494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2596494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2597494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2598494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2599494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2600494a190aSStefano Zampini   }
2601494a190aSStefano Zampini   if (!directionsprinted) {
2602494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2603494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2604494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2605494a190aSStefano Zampini   }
2606494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2607494a190aSStefano Zampini 
2608494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2609494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2610494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2611494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2612494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2613494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2614494a190aSStefano Zampini 
2615494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2616494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2617494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2618494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2619494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2620494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2621494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2622494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2623494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2624494a190aSStefano 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))));
2625494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2626494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2627494a190aSStefano Zampini 
2628494a190aSStefano Zampini   if (complete_print) {
2629494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2630494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2631494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2632494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2633494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2634494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2635494a190aSStefano Zampini   }
2636494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2637494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2638494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2639494a190aSStefano Zampini 
2640494a190aSStefano Zampini   if (complete_print) {
2641494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2642494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2643494a190aSStefano Zampini   }
2644494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2645494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2646494a190aSStefano Zampini }
2647494a190aSStefano Zampini 
2648d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2649d71ae5a4SJacob Faibussowitsch {
265012837594SBarry Smith   Mat               A, B, C, D, jacobian;
26514df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2652e885f1abSBarry Smith   PetscReal         nrm, gnorm;
265381e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
26540e276705SLisandro Dalcin   MatType           mattype;
2655e885f1abSBarry Smith   PetscInt          m, n, M, N;
2656e885f1abSBarry Smith   void             *functx;
26572cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
26583325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2659e885f1abSBarry Smith   MPI_Comm          comm;
2660e885f1abSBarry Smith   PetscInt          tabs;
266112837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
26623325ff46SBarry Smith   PetscViewerFormat format;
2663e885f1abSBarry Smith 
2664e885f1abSBarry Smith   PetscFunctionBegin;
2665d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
26669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
26679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
26689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
26694ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
26709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
26719566063dSJacob 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));
2672d0609cedSBarry Smith   PetscOptionsEnd();
26733ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2674e885f1abSBarry Smith 
26759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
26769566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
26779566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
26789566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
26799566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
268012837594SBarry Smith   if (!complete_print && !directionsprinted) {
26819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
26829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
268312837594SBarry Smith   }
268412837594SBarry Smith   if (!directionsprinted) {
26859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
26869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
268712837594SBarry Smith     directionsprinted = PETSC_TRUE;
2688e885f1abSBarry Smith   }
26891baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2690e885f1abSBarry Smith 
26919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
269212837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
269312837594SBarry Smith   else jacobian = snes->jacobian_pre;
269412837594SBarry Smith 
26954df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
26964df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
26979566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
26984df93895SStefano Zampini 
2699a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27009566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
270312837594SBarry Smith   while (jacobian) {
27042cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27052cd624f9SStefano Zampini 
27062cd624f9SStefano Zampini     if (istranspose) {
27079566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27082cd624f9SStefano Zampini       Jsave    = jacobian;
27092cd624f9SStefano Zampini       jacobian = JT;
27102cd624f9SStefano Zampini     }
27119566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
271212837594SBarry Smith     if (flg) {
271312837594SBarry Smith       A = jacobian;
27149566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
271512837594SBarry Smith     } else {
27169566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
271712837594SBarry Smith     }
2718e885f1abSBarry Smith 
27199566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27209566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27219566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27229566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27239566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27249566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27259566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27269566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
27279566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2728e885f1abSBarry Smith 
27299566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
27309566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
273112837594SBarry Smith 
27329566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
27339566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27349566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
27359566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
27369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
273712837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
27389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
273912837594SBarry Smith 
2740e885f1abSBarry Smith     if (complete_print) {
27419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
27429566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
27439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
27449566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2745e885f1abSBarry Smith     }
2746e885f1abSBarry Smith 
2747df10fb39SFande Kong     if (threshold_print || complete_print) {
2748e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2749e885f1abSBarry Smith       PetscScalar       *cvals;
2750e885f1abSBarry Smith       const PetscInt    *bcols;
2751e885f1abSBarry Smith       const PetscScalar *bvals;
2752e885f1abSBarry Smith 
27539566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
27549566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
27559566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
27569566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
27579566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
27589566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
27590e276705SLisandro Dalcin 
27609566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27619566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2762e885f1abSBarry Smith 
2763e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
27649566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
27659566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2766e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
276723a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2768e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2769e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2770e885f1abSBarry Smith             cncols += 1;
2771e885f1abSBarry Smith           }
2772e885f1abSBarry Smith         }
277348a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
27749566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
27759566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2776e885f1abSBarry Smith       }
27779566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
27789566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
27799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
27809566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
27819566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2782e885f1abSBarry Smith     }
27839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
27849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
27859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
27862cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
278712837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
278812837594SBarry Smith       jacobian = snes->jacobian_pre;
27899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
27909371c9d4SSatish Balay     } else jacobian = NULL;
279112837594SBarry Smith   }
27929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
27931baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2794648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
27959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
27963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2797e885f1abSBarry Smith }
2798e885f1abSBarry Smith 
279962fef451SLois Curfman McInnes /*@
2800f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
280162fef451SLois Curfman McInnes 
2802c3339decSBarry Smith   Collective
2803c7afd0dbSLois Curfman McInnes 
280462fef451SLois Curfman McInnes   Input Parameters:
2805f6dfbefdSBarry Smith + snes - the `SNES` context
2806e4094ef1SJacob Faibussowitsch - X    - input vector
280762fef451SLois Curfman McInnes 
280862fef451SLois Curfman McInnes   Output Parameters:
2809c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2810420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2811fee21e36SBarry Smith 
2812e35cf81dSBarry Smith   Options Database Keys:
281367b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
281467b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2815455a5933SJed 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.
2816455a5933SJed 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
2817693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2818693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2819693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28204c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
282194d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2822a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2823c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2824dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2825dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2826a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2827a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2828c01495d3SJed Brown 
2829dc4c0fb0SBarry Smith   Level: developer
2830dc4c0fb0SBarry Smith 
2831f6dfbefdSBarry Smith   Note:
283262fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
283362fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
283462fef451SLois Curfman McInnes 
2835420bcc1bSBarry Smith   Developer Note:
2836dc4c0fb0SBarry 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
2837420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2838e885f1abSBarry Smith 
28391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
284062fef451SLois Curfman McInnes @*/
2841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2842d71ae5a4SJacob Faibussowitsch {
2843ace3abfcSBarry Smith   PetscBool flag;
28446cab3a1bSJed Brown   DM        dm;
2845942e3340SBarry Smith   DMSNES    sdm;
2846e0e3a89bSBarry Smith   KSP       ksp;
28473a40ed3dSBarry Smith 
28483a40ed3dSBarry Smith   PetscFunctionBegin;
28490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
28500700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2851c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2852e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
28539566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
28549566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
28553232da50SPeter Brune 
285601c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2857fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2858fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2859f5af7f23SKarl Rupp 
28609566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2861fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
28629566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
28639566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2864ebd3b9afSBarry Smith     if (flag) {
28659566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28669566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2867ebd3b9afSBarry Smith     }
28683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
286937ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
287063a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
28719566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2872ebd3b9afSBarry Smith     if (flag) {
28739566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28749566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2875ebd3b9afSBarry Smith     }
28763ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2877e35cf81dSBarry Smith   }
2878efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
28799566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
28813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2882d728fb7dSPeter Brune   }
2883e35cf81dSBarry Smith 
28849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
28859566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2886800f99ffSJeremy L Thompson   {
2887800f99ffSJeremy L Thompson     void           *ctx;
28888434afd1SBarry Smith     SNESJacobianFn *J;
2889800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2890800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2891800f99ffSJeremy L Thompson   }
28929566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
28939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
289428d58a37SPierre Jolivet 
289528d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
28969566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2897a8054027SBarry Smith 
2898e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
28999566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29003b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29019566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29029566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29033b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29043b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29059566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29069566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
290737ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
290863a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29099566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2910d1e9a80fSBarry Smith   } else {
29119566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29129566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2913a8054027SBarry Smith   }
2914a8054027SBarry Smith 
29154df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29164df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29174df93895SStefano Zampini   {
29184df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29194df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29204df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29214df93895SStefano Zampini 
29224df93895SStefano Zampini     snes->vec_sol      = X;
29234df93895SStefano Zampini     snes->jacobian     = A;
29244df93895SStefano Zampini     snes->jacobian_pre = B;
2925494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29269566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
2927494a190aSStefano Zampini 
29284df93895SStefano Zampini     snes->vec_sol      = xsave;
29294df93895SStefano Zampini     snes->jacobian     = jacobiansave;
29304df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
29314df93895SStefano Zampini   }
29324df93895SStefano Zampini 
2933693365a8SJed Brown   {
2934693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
2935648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
2936648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
2937648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
2938648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2939693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
29400298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2941693365a8SJed Brown       PetscViewer vdraw, vstdout;
29426b3a5b13SJed Brown       PetscBool   flg;
2943693365a8SJed Brown       if (flag_operator) {
29449566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2945693365a8SJed Brown         Bexp = Bexp_mine;
2946693365a8SJed Brown       } else {
2947693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
29489566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
294994ab13aaSBarry Smith         if (flg) Bexp = B;
2950693365a8SJed Brown         else {
2951693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
29529566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2953693365a8SJed Brown           Bexp = Bexp_mine;
2954693365a8SJed Brown         }
2955693365a8SJed Brown       }
29569566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
29579566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
29589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2959693365a8SJed Brown       if (flag_draw || flag_contour) {
29609566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29619566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29620298fd71SBarry Smith       } else vdraw = NULL;
29639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
29649566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
29659566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
29669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
29679566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
29689566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
29699566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
29709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
29719566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2972693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
29739566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29749566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
29759566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2976693365a8SJed Brown       }
29779566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29789566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29799566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
29809566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2981693365a8SJed Brown     }
2982693365a8SJed Brown   }
29834c30e9fbSJed Brown   {
29846719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
29856719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
2986648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
2987648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
2988648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
2989648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
2990648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
299127b0f280SBarry Smith     if (flag_threshold) {
29929566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
29939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
299427b0f280SBarry Smith     }
29956719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
29964c30e9fbSJed Brown       Mat             Bfd;
29974c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
2998335efc43SPeter Brune       MatColoring     coloring;
29994c30e9fbSJed Brown       ISColoring      iscoloring;
30004c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30018434afd1SBarry Smith       SNESFunctionFn *func;
30024c30e9fbSJed Brown       void           *funcctx;
30036719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30044c30e9fbSJed Brown 
30059566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30069566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30079566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30089566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30099566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30109566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30119566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30129566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30139566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30149566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30154c30e9fbSJed Brown 
30164c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30179566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30189566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
30199566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30209566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30219566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30229566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30239566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30244c30e9fbSJed Brown 
30259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30264c30e9fbSJed Brown       if (flag_draw || flag_contour) {
30279566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30289566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30290298fd71SBarry Smith       } else vdraw = NULL;
30309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
30319566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
30329566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
30339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
30349566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30359566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
30369566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
30379566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
30389566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
30399566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
30409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
30419566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30424c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
30439566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30449566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
30459566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
30464c30e9fbSJed Brown       }
30479566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30486719d8e4SJed Brown 
30496719d8e4SJed Brown       if (flag_threshold) {
30506719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
30519566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
30529566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
30536719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
30546719d8e4SJed Brown           const PetscScalar *ba, *ca;
30556719d8e4SJed Brown           const PetscInt    *bj, *cj;
30566719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
30576719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
30589566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
30599566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
30605f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
30616719d8e4SJed Brown           for (j = 0; j < bn; j++) {
30626719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
30636719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
30646719d8e4SJed Brown               maxentrycol = bj[j];
30656719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
30666719d8e4SJed Brown             }
30676719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
30686719d8e4SJed Brown               maxdiffcol = bj[j];
30696719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
30706719d8e4SJed Brown             }
30716719d8e4SJed Brown             if (rdiff > maxrdiff) {
30726719d8e4SJed Brown               maxrdiffcol = bj[j];
30736719d8e4SJed Brown               maxrdiff    = rdiff;
30746719d8e4SJed Brown             }
30756719d8e4SJed Brown           }
30766719d8e4SJed Brown           if (maxrdiff > 1) {
307763a3b9bcSJacob 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));
30786719d8e4SJed Brown             for (j = 0; j < bn; j++) {
30796719d8e4SJed Brown               PetscReal rdiff;
30806719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
308148a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
30826719d8e4SJed Brown             }
308363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
30846719d8e4SJed Brown           }
30859566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
30869566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
30876719d8e4SJed Brown         }
30886719d8e4SJed Brown       }
30899566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30909566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
30914c30e9fbSJed Brown     }
30924c30e9fbSJed Brown   }
30933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30949b94acceSBarry Smith }
30959b94acceSBarry Smith 
30969b94acceSBarry Smith /*@C
30979b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3098044dda88SLois Curfman McInnes   location to store the matrix.
30999b94acceSBarry Smith 
3100c3339decSBarry Smith   Logically Collective
3101c7afd0dbSLois Curfman McInnes 
31029b94acceSBarry Smith   Input Parameters:
3103f6dfbefdSBarry Smith + snes - the `SNES` context
3104e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3105dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31068434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3107c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3108dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3109dc4c0fb0SBarry Smith 
3110dc4c0fb0SBarry Smith   Level: beginner
31119b94acceSBarry Smith 
31129b94acceSBarry Smith   Notes:
3113dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
311416913363SBarry Smith   each matrix.
311516913363SBarry Smith 
3116dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3117dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3118895c21f2SBarry Smith 
3119dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3120f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3121a8a26c1eSJed Brown 
3122c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3123f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3124c3cc8fd1SJed Brown 
31251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31268434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
31279b94acceSBarry Smith @*/
31288434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3129d71ae5a4SJacob Faibussowitsch {
31306cab3a1bSJed Brown   DM dm;
31313a7fca6bSBarry Smith 
31323a40ed3dSBarry Smith   PetscFunctionBegin;
31330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3134e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3135e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3136e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3137e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
31389566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31399566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3140e5d3d808SBarry Smith   if (Amat) {
31419566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
31429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3143f5af7f23SKarl Rupp 
3144e5d3d808SBarry Smith     snes->jacobian = Amat;
31453a7fca6bSBarry Smith   }
3146e5d3d808SBarry Smith   if (Pmat) {
31479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
31489566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3149f5af7f23SKarl Rupp 
3150e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
31513a7fca6bSBarry Smith   }
31523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31539b94acceSBarry Smith }
315462fef451SLois Curfman McInnes 
3155c2aafc4cSSatish Balay /*@C
3156b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3157b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3158b4fd4287SBarry Smith 
3159420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3160c7afd0dbSLois Curfman McInnes 
3161b4fd4287SBarry Smith   Input Parameter:
3162b4fd4287SBarry Smith . snes - the nonlinear solver context
3163b4fd4287SBarry Smith 
3164b4fd4287SBarry Smith   Output Parameters:
3165dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3166dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
31678434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3168dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3169fee21e36SBarry Smith 
317036851e7fSLois Curfman McInnes   Level: advanced
317136851e7fSLois Curfman McInnes 
31728434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3173b4fd4287SBarry Smith @*/
31748434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3175d71ae5a4SJacob Faibussowitsch {
31766cab3a1bSJed Brown   DM dm;
31776cab3a1bSJed Brown 
31783a40ed3dSBarry Smith   PetscFunctionBegin;
31790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3180e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3181e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
31829566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3183800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
31843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3185b4fd4287SBarry Smith }
3186b4fd4287SBarry Smith 
3187d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3188d71ae5a4SJacob Faibussowitsch {
318958b371f3SBarry Smith   DM     dm;
319058b371f3SBarry Smith   DMSNES sdm;
319158b371f3SBarry Smith 
319258b371f3SBarry Smith   PetscFunctionBegin;
31939566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31949566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
319558b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
319658b371f3SBarry Smith     DM        dm;
319758b371f3SBarry Smith     PetscBool isdense, ismf;
319858b371f3SBarry Smith 
31999566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32009566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32019566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
320258b371f3SBarry Smith     if (isdense) {
32039566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
320458b371f3SBarry Smith     } else if (!ismf) {
32059566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
320658b371f3SBarry Smith     }
320758b371f3SBarry Smith   }
32083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
320958b371f3SBarry Smith }
321058b371f3SBarry Smith 
32119b94acceSBarry Smith /*@
32129b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3213272ac6f2SLois Curfman McInnes   of a nonlinear solver.
32149b94acceSBarry Smith 
3215c3339decSBarry Smith   Collective
3216fee21e36SBarry Smith 
32172fe279fdSBarry Smith   Input Parameter:
3218f6dfbefdSBarry Smith . snes - the `SNES` context
3219c7afd0dbSLois Curfman McInnes 
3220dc4c0fb0SBarry Smith   Level: advanced
3221dc4c0fb0SBarry Smith 
3222f6dfbefdSBarry Smith   Note:
3223f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3224f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3225f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3226f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3227f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3228272ac6f2SLois Curfman McInnes 
32291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
32309b94acceSBarry Smith @*/
3231d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3232d71ae5a4SJacob Faibussowitsch {
32336cab3a1bSJed Brown   DM             dm;
3234942e3340SBarry Smith   DMSNES         sdm;
3235c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
32366e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
32379b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
32389b5c1c08SStefano Zampini   Vec            f, fpc;
32399b5c1c08SStefano Zampini   void          *funcctx;
32409b5c1c08SStefano Zampini   void          *jacctx, *appctx;
32419b5c1c08SStefano Zampini   Mat            j, jpre;
32426b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
32436b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
32448434afd1SBarry Smith   SNESFunctionFn *func;
32458434afd1SBarry Smith   SNESJacobianFn *jac;
32463a40ed3dSBarry Smith 
32473a40ed3dSBarry Smith   PetscFunctionBegin;
32480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
32493ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3250fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
32519b94acceSBarry Smith 
325248a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
325385385478SLisandro Dalcin 
32549566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
325558c9b817SLisandro Dalcin 
32569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32579566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
32589566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
325958b371f3SBarry Smith 
326048a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3261efd51863SBarry Smith 
326248a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3263b710008aSBarry Smith 
3264d8d34be6SBarry Smith   if (snes->linesearch) {
32659566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
32669566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3267d8d34be6SBarry Smith   }
32689e764e56SPeter Brune 
32699b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3270b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3271172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3272172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3273172a4300SPeter Brune   }
3274d8f46077SPeter Brune 
3275efd4aadfSBarry Smith   if (snes->npc) {
32766e2a1849SPeter Brune     /* copy the DM over */
32779566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32789566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
32796e2a1849SPeter Brune 
32809566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
32819566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
32829566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
32839566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
32849566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
32859566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
32869566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
32879b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
32889566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
32896e2a1849SPeter Brune 
32906e2a1849SPeter Brune     /* copy the function pointers over */
32919566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
32926e2a1849SPeter Brune 
32936e2a1849SPeter Brune     /* default to 1 iteration */
32949566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3295efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32969566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3297a9936a0cSPeter Brune     } else {
32989566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3299a9936a0cSPeter Brune     }
33009566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33016e2a1849SPeter Brune 
33026e2a1849SPeter Brune     /* copy the line search context over */
3303d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33049566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33059566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33069566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33079566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33089566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33099566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33109566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33116e2a1849SPeter Brune     }
3312d8d34be6SBarry Smith   }
33131baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
33149927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
33156e2a1849SPeter Brune 
331637ec4e1aSPeter Brune   snes->jac_iter = 0;
331737ec4e1aSPeter Brune   snes->pre_iter = 0;
331837ec4e1aSPeter Brune 
3319dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
332058c9b817SLisandro Dalcin 
33219566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
332258b371f3SBarry Smith 
3323b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33246c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3325d8d34be6SBarry Smith       if (snes->linesearch) {
33269566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
33279566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
33286c67d002SPeter Brune       }
33296c67d002SPeter Brune     }
3330d8d34be6SBarry Smith   }
3331fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
33327aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
33333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33349b94acceSBarry Smith }
33359b94acceSBarry Smith 
333637596af1SLisandro Dalcin /*@
3337f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
333837596af1SLisandro Dalcin 
3339c3339decSBarry Smith   Collective
334037596af1SLisandro Dalcin 
334137596af1SLisandro Dalcin   Input Parameter:
3342f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
334337596af1SLisandro Dalcin 
3344d25893d9SBarry Smith   Level: intermediate
3345d25893d9SBarry Smith 
334695452b02SPatrick Sanan   Notes:
3347f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
334837596af1SLisandro Dalcin 
3349f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3350f6dfbefdSBarry Smith 
33511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
335237596af1SLisandro Dalcin @*/
3353d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3354d71ae5a4SJacob Faibussowitsch {
335537596af1SLisandro Dalcin   PetscFunctionBegin;
335637596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3357d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
33589927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
33590298fd71SBarry Smith     snes->user = NULL;
3360d25893d9SBarry Smith   }
33611baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
33628a23116dSBarry Smith 
3363dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
33641baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
33659e764e56SPeter Brune 
33661baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
33679e764e56SPeter Brune 
33689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
33699566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
33709566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
33719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
33729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
33739566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
33749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
33759566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
33769566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3377f5af7f23SKarl Rupp 
337840fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
337940fdac6aSLawrence Mitchell 
338037596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
338137596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
33823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338337596af1SLisandro Dalcin }
338437596af1SLisandro Dalcin 
338552baeb72SSatish Balay /*@
338636d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
338736d43d94SBarry Smith   removes the default viewer.
3388c4421ceaSFande Kong 
3389c3339decSBarry Smith   Collective
3390c4421ceaSFande Kong 
3391c4421ceaSFande Kong   Input Parameter:
3392f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3393c4421ceaSFande Kong 
3394c4421ceaSFande Kong   Level: intermediate
3395c4421ceaSFande Kong 
3396420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3397c4421ceaSFande Kong @*/
3398d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3399d71ae5a4SJacob Faibussowitsch {
3400c4421ceaSFande Kong   PetscInt i;
3401c4421ceaSFande Kong 
3402c4421ceaSFande Kong   PetscFunctionBegin;
3403c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3404c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
340548a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3406c4421ceaSFande Kong   }
3407c4421ceaSFande Kong   snes->numberreasonviews = 0;
3408648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3410c4421ceaSFande Kong }
3411c4421ceaSFande Kong 
34120764c050SBarry Smith /*@
34139b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3414f6dfbefdSBarry Smith   with `SNESCreate()`.
34159b94acceSBarry Smith 
3416c3339decSBarry Smith   Collective
3417c7afd0dbSLois Curfman McInnes 
34189b94acceSBarry Smith   Input Parameter:
3419f6dfbefdSBarry Smith . snes - the `SNES` context
34209b94acceSBarry Smith 
342136851e7fSLois Curfman McInnes   Level: beginner
342236851e7fSLois Curfman McInnes 
34231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34249b94acceSBarry Smith @*/
3425d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3426d71ae5a4SJacob Faibussowitsch {
34273a40ed3dSBarry Smith   PetscFunctionBegin;
34283ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3429f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3430f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
34319371c9d4SSatish Balay     *snes = NULL;
34323ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
34339371c9d4SSatish Balay   }
3434d4bb536fSBarry Smith 
3435f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
34369566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
34376b8b9a38SLisandro Dalcin 
3438e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
34399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3440f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
34416d4c513bSLisandro Dalcin 
34429566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
34439566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
34449566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
34459566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
34466b8b9a38SLisandro Dalcin 
34479566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
344848a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
344948a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3450f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3451f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
34529566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
34533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34549b94acceSBarry Smith }
34559b94acceSBarry Smith 
34569b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
34579b94acceSBarry Smith 
3458a8054027SBarry Smith /*@
3459a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3460a8054027SBarry Smith 
3461c3339decSBarry Smith   Logically Collective
3462a8054027SBarry Smith 
3463a8054027SBarry Smith   Input Parameters:
3464f6dfbefdSBarry Smith + snes - the `SNES` context
3465d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
34663b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3467a8054027SBarry Smith 
3468a8054027SBarry Smith   Options Database Keys:
3469420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
34703d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3471420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
34723d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3473a8054027SBarry Smith 
3474dc4c0fb0SBarry Smith   Level: intermediate
3475dc4c0fb0SBarry Smith 
3476420bcc1bSBarry Smith   Notes:
3477a8054027SBarry Smith   The default is 1
3478420bcc1bSBarry Smith 
3479f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3480d8e291bfSBarry Smith 
3481f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3482a8054027SBarry Smith 
34831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3484f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3485a8054027SBarry Smith @*/
3486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3487d71ae5a4SJacob Faibussowitsch {
3488a8054027SBarry Smith   PetscFunctionBegin;
34890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34905f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34915f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3492c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3493a8054027SBarry Smith   snes->lagpreconditioner = lag;
34943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3495a8054027SBarry Smith }
3496a8054027SBarry Smith 
3497efd51863SBarry Smith /*@
3498f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3499efd51863SBarry Smith 
3500c3339decSBarry Smith   Logically Collective
3501efd51863SBarry Smith 
3502efd51863SBarry Smith   Input Parameters:
3503f6dfbefdSBarry Smith + snes  - the `SNES` context
3504efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3505efd51863SBarry Smith 
3506f6dfbefdSBarry Smith   Options Database Key:
350767b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3508efd51863SBarry Smith 
3509efd51863SBarry Smith   Level: intermediate
3510efd51863SBarry Smith 
3511f6dfbefdSBarry Smith   Note:
3512f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3513c0df2a02SJed Brown 
3514420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3515420bcc1bSBarry Smith           `SNESetDM()`
3516efd51863SBarry Smith @*/
3517d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3518d71ae5a4SJacob Faibussowitsch {
3519efd51863SBarry Smith   PetscFunctionBegin;
3520efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3521efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3522efd51863SBarry Smith   snes->gridsequence = steps;
35233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3524efd51863SBarry Smith }
3525efd51863SBarry Smith 
3526fa19ca70SBarry Smith /*@
3527f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3528fa19ca70SBarry Smith 
3529c3339decSBarry Smith   Logically Collective
3530fa19ca70SBarry Smith 
3531fa19ca70SBarry Smith   Input Parameter:
3532f6dfbefdSBarry Smith . snes - the `SNES` context
3533fa19ca70SBarry Smith 
3534fa19ca70SBarry Smith   Output Parameter:
3535fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3536fa19ca70SBarry Smith 
3537fa19ca70SBarry Smith   Level: intermediate
3538fa19ca70SBarry Smith 
35391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3540fa19ca70SBarry Smith @*/
3541d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3542d71ae5a4SJacob Faibussowitsch {
3543fa19ca70SBarry Smith   PetscFunctionBegin;
3544fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3545fa19ca70SBarry Smith   *steps = snes->gridsequence;
35463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3547fa19ca70SBarry Smith }
3548fa19ca70SBarry Smith 
3549a8054027SBarry Smith /*@
3550f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3551a8054027SBarry Smith 
35523f9fe445SBarry Smith   Not Collective
3553a8054027SBarry Smith 
3554a8054027SBarry Smith   Input Parameter:
3555f6dfbefdSBarry Smith . snes - the `SNES` context
3556a8054027SBarry Smith 
3557a8054027SBarry Smith   Output Parameter:
3558a8054027SBarry 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
35593b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3560a8054027SBarry Smith 
3561dc4c0fb0SBarry Smith   Level: intermediate
3562dc4c0fb0SBarry Smith 
3563a8054027SBarry Smith   Notes:
3564a8054027SBarry Smith   The default is 1
3565f6dfbefdSBarry Smith 
3566a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3567a8054027SBarry Smith 
35681cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3569a8054027SBarry Smith @*/
3570d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3571d71ae5a4SJacob Faibussowitsch {
3572a8054027SBarry Smith   PetscFunctionBegin;
35730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3574a8054027SBarry Smith   *lag = snes->lagpreconditioner;
35753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3576a8054027SBarry Smith }
3577a8054027SBarry Smith 
3578e35cf81dSBarry Smith /*@
3579f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3580e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3581e35cf81dSBarry Smith 
3582c3339decSBarry Smith   Logically Collective
3583e35cf81dSBarry Smith 
3584e35cf81dSBarry Smith   Input Parameters:
3585f6dfbefdSBarry Smith + snes - the `SNES` context
3586e35cf81dSBarry 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
3587fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3588e35cf81dSBarry Smith 
3589e35cf81dSBarry Smith   Options Database Keys:
359079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35913d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
359279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35933d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3594e35cf81dSBarry Smith 
3595dc4c0fb0SBarry Smith   Level: intermediate
3596dc4c0fb0SBarry Smith 
3597e35cf81dSBarry Smith   Notes:
3598e35cf81dSBarry Smith   The default is 1
3599f6dfbefdSBarry Smith 
3600e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3601f6dfbefdSBarry Smith 
3602fe3ffe1eSBarry 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
3603fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3604e35cf81dSBarry Smith 
36051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3606e35cf81dSBarry Smith @*/
3607d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3608d71ae5a4SJacob Faibussowitsch {
3609e35cf81dSBarry Smith   PetscFunctionBegin;
36100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36115f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36125f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3613c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3614e35cf81dSBarry Smith   snes->lagjacobian = lag;
36153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3616e35cf81dSBarry Smith }
3617e35cf81dSBarry Smith 
3618e35cf81dSBarry Smith /*@
3619f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3620e35cf81dSBarry Smith 
36213f9fe445SBarry Smith   Not Collective
3622e35cf81dSBarry Smith 
3623e35cf81dSBarry Smith   Input Parameter:
3624f6dfbefdSBarry Smith . snes - the `SNES` context
3625e35cf81dSBarry Smith 
3626e35cf81dSBarry Smith   Output Parameter:
3627e35cf81dSBarry 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
3628e35cf81dSBarry Smith          the Jacobian is built etc.
3629e35cf81dSBarry Smith 
3630dc4c0fb0SBarry Smith   Level: intermediate
3631dc4c0fb0SBarry Smith 
3632e35cf81dSBarry Smith   Notes:
3633e35cf81dSBarry Smith   The default is 1
3634f6dfbefdSBarry Smith 
3635f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3636e35cf81dSBarry Smith 
36371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3638e35cf81dSBarry Smith 
3639e35cf81dSBarry Smith @*/
3640d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3641d71ae5a4SJacob Faibussowitsch {
3642e35cf81dSBarry Smith   PetscFunctionBegin;
36430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3644e35cf81dSBarry Smith   *lag = snes->lagjacobian;
36453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3646e35cf81dSBarry Smith }
3647e35cf81dSBarry Smith 
364837ec4e1aSPeter Brune /*@
3649f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
365037ec4e1aSPeter Brune 
3651c3339decSBarry Smith   Logically collective
365237ec4e1aSPeter Brune 
3653d8d19677SJose E. Roman   Input Parameters:
3654f6dfbefdSBarry Smith + snes - the `SNES` context
36559d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
365637ec4e1aSPeter Brune 
365737ec4e1aSPeter Brune   Options Database Keys:
365879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36593d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
366079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36613d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
36623d5a8a6aSBarry Smith 
3663dc4c0fb0SBarry Smith   Level: advanced
3664dc4c0fb0SBarry Smith 
366595452b02SPatrick Sanan   Notes:
3666420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3667f6dfbefdSBarry Smith 
366895452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
366937ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
367037ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
367137ec4e1aSPeter Brune 
367242747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
367337ec4e1aSPeter Brune @*/
3674d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3675d71ae5a4SJacob Faibussowitsch {
367637ec4e1aSPeter Brune   PetscFunctionBegin;
367737ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
367837ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
367937ec4e1aSPeter Brune   snes->lagjac_persist = flg;
36803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368137ec4e1aSPeter Brune }
368237ec4e1aSPeter Brune 
368337ec4e1aSPeter Brune /*@
3684d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
368537ec4e1aSPeter Brune 
3686c3339decSBarry Smith   Logically Collective
368737ec4e1aSPeter Brune 
3688d8d19677SJose E. Roman   Input Parameters:
3689f6dfbefdSBarry Smith + snes - the `SNES` context
36909d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
369137ec4e1aSPeter Brune 
369237ec4e1aSPeter Brune   Options Database Keys:
369379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36943d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
369579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36963d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
369737ec4e1aSPeter Brune 
3698dc4c0fb0SBarry Smith   Level: developer
3699dc4c0fb0SBarry Smith 
370095452b02SPatrick Sanan   Notes:
3701420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3702f6dfbefdSBarry Smith 
370395452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
370437ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
370537ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
370637ec4e1aSPeter Brune 
37071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
370837ec4e1aSPeter Brune @*/
3709d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3710d71ae5a4SJacob Faibussowitsch {
371137ec4e1aSPeter Brune   PetscFunctionBegin;
371237ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
371337ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
371437ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
371637ec4e1aSPeter Brune }
371737ec4e1aSPeter Brune 
37189b94acceSBarry Smith /*@
3719f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3720be5caee7SBarry Smith 
3721c3339decSBarry Smith   Logically Collective
3722be5caee7SBarry Smith 
3723be5caee7SBarry Smith   Input Parameters:
3724f6dfbefdSBarry Smith + snes  - the `SNES` context
3725f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3726be5caee7SBarry Smith 
3727f6dfbefdSBarry Smith   Options Database Key:
3728be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3729be5caee7SBarry Smith 
3730dc4c0fb0SBarry Smith   Level: intermediate
3731dc4c0fb0SBarry Smith 
3732f6dfbefdSBarry Smith   Note:
3733f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3734be5caee7SBarry Smith 
37351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3736be5caee7SBarry Smith @*/
3737d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3738d71ae5a4SJacob Faibussowitsch {
3739be5caee7SBarry Smith   PetscFunctionBegin;
3740be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3741be5caee7SBarry Smith   snes->forceiteration = force;
37423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3743be5caee7SBarry Smith }
3744be5caee7SBarry Smith 
374585216dc7SFande Kong /*@
3746f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
374785216dc7SFande Kong 
3748c3339decSBarry Smith   Logically Collective
374985216dc7SFande Kong 
37502fe279fdSBarry Smith   Input Parameter:
3751f6dfbefdSBarry Smith . snes - the `SNES` context
375285216dc7SFande Kong 
375385216dc7SFande Kong   Output Parameter:
3754dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
375585216dc7SFande Kong 
375606dd6b0eSSatish Balay   Level: intermediate
375706dd6b0eSSatish Balay 
37581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
375985216dc7SFande Kong @*/
3760d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3761d71ae5a4SJacob Faibussowitsch {
376285216dc7SFande Kong   PetscFunctionBegin;
376385216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376485216dc7SFande Kong   *force = snes->forceiteration;
37653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376685216dc7SFande Kong }
3767be5caee7SBarry Smith 
3768be5caee7SBarry Smith /*@
3769f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
37709b94acceSBarry Smith 
3771c3339decSBarry Smith   Logically Collective
3772c7afd0dbSLois Curfman McInnes 
37739b94acceSBarry Smith   Input Parameters:
3774f6dfbefdSBarry Smith + snes   - the `SNES` context
377570441072SBarry Smith . abstol - absolute convergence tolerance
377633174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
37775358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3778f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3779f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3780fee21e36SBarry Smith 
378133174efeSLois Curfman McInnes   Options Database Keys:
378270441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3783c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3784c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3785c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3786c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
37879b94acceSBarry Smith 
378836851e7fSLois Curfman McInnes   Level: intermediate
378936851e7fSLois Curfman McInnes 
379000677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
37919b94acceSBarry Smith @*/
3792d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3793d71ae5a4SJacob Faibussowitsch {
37943a40ed3dSBarry Smith   PetscFunctionBegin;
37950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3796c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3797c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3798c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3799c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3800c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3801c5eb9154SBarry Smith 
380213bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
38035f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3804ab54825eSJed Brown     snes->abstol = abstol;
3805ab54825eSJed Brown   }
380613bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
38075f80ce2aSJacob 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);
3808ab54825eSJed Brown     snes->rtol = rtol;
3809ab54825eSJed Brown   }
381013bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
38115f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3812c60f73f4SPeter Brune     snes->stol = stol;
3813ab54825eSJed Brown   }
3814ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
381563a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3816ab54825eSJed Brown     snes->max_its = maxit;
3817ab54825eSJed Brown   }
3818ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
381963a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3820ab54825eSJed Brown     snes->max_funcs = maxf;
3821ab54825eSJed Brown   }
382288976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
38233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38249b94acceSBarry Smith }
38259b94acceSBarry Smith 
3826e4d06f11SPatrick Farrell /*@
3827f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3828e4d06f11SPatrick Farrell 
3829c3339decSBarry Smith   Logically Collective
3830e4d06f11SPatrick Farrell 
3831e4d06f11SPatrick Farrell   Input Parameters:
3832f6dfbefdSBarry Smith + snes   - the `SNES` context
3833e5cd489fSStefano Zampini - divtol - the divergence tolerance.
3834e4d06f11SPatrick Farrell 
3835f6dfbefdSBarry Smith   Options Database Key:
3836dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3837e4d06f11SPatrick Farrell 
3838e4d06f11SPatrick Farrell   Level: intermediate
3839e4d06f11SPatrick Farrell 
3840e5cd489fSStefano Zampini   Note:
3841e5cd489fSStefano Zampini   Non-positive values of `divtol` different from `PETSC_DEFAULT` will deactivate the test.
3842e5cd489fSStefano Zampini 
38431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3844e4d06f11SPatrick Farrell @*/
3845d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3846d71ae5a4SJacob Faibussowitsch {
3847e4d06f11SPatrick Farrell   PetscFunctionBegin;
3848e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3849e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3850e5cd489fSStefano Zampini   if (divtol != (PetscReal)PETSC_DEFAULT) snes->divtol = divtol;
38513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3852e4d06f11SPatrick Farrell }
3853e4d06f11SPatrick Farrell 
38549b94acceSBarry Smith /*@
385533174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
385633174efeSLois Curfman McInnes 
3857c7afd0dbSLois Curfman McInnes   Not Collective
3858c7afd0dbSLois Curfman McInnes 
385933174efeSLois Curfman McInnes   Input Parameters:
3860f6dfbefdSBarry Smith + snes  - the `SNES` context
386185385478SLisandro Dalcin . atol  - absolute convergence tolerance
386233174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
386333174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
386433174efeSLois Curfman McInnes           of the change in the solution between steps
386533174efeSLois Curfman McInnes . maxit - maximum number of iterations
3866c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3867fee21e36SBarry Smith 
386836851e7fSLois Curfman McInnes   Level: intermediate
386936851e7fSLois Curfman McInnes 
3870dc4c0fb0SBarry Smith   Note:
3871dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3872dc4c0fb0SBarry Smith 
38731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
387433174efeSLois Curfman McInnes @*/
3875d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3876d71ae5a4SJacob Faibussowitsch {
38773a40ed3dSBarry Smith   PetscFunctionBegin;
38780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
387985385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
388033174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3881c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
388233174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
388333174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
38843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388533174efeSLois Curfman McInnes }
388633174efeSLois Curfman McInnes 
3887e4d06f11SPatrick Farrell /*@
3888e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3889e4d06f11SPatrick Farrell 
3890e4d06f11SPatrick Farrell   Not Collective
3891e4d06f11SPatrick Farrell 
3892e4d06f11SPatrick Farrell   Input Parameters:
3893f6dfbefdSBarry Smith + snes   - the `SNES` context
3894e4d06f11SPatrick Farrell - divtol - divergence tolerance
3895e4d06f11SPatrick Farrell 
3896e4d06f11SPatrick Farrell   Level: intermediate
3897e4d06f11SPatrick Farrell 
38981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3899e4d06f11SPatrick Farrell @*/
3900d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3901d71ae5a4SJacob Faibussowitsch {
3902e4d06f11SPatrick Farrell   PetscFunctionBegin;
3903e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3904e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
39053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3906e4d06f11SPatrick Farrell }
3907e4d06f11SPatrick Farrell 
390833174efeSLois Curfman McInnes /*@
39099b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
39109b94acceSBarry Smith 
3911c3339decSBarry Smith   Logically Collective
3912fee21e36SBarry Smith 
3913c7afd0dbSLois Curfman McInnes   Input Parameters:
3914f6dfbefdSBarry Smith + snes - the `SNES` context
3915c7afd0dbSLois Curfman McInnes - tol  - tolerance
3916c7afd0dbSLois Curfman McInnes 
39179b94acceSBarry Smith   Options Database Key:
39184a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
39199b94acceSBarry Smith 
392036851e7fSLois Curfman McInnes   Level: intermediate
392136851e7fSLois Curfman McInnes 
39229bcc50f1SBarry Smith   Developer Note:
39239bcc50f1SBarry Smith   Should be SNESTrustRegionSetTolerance()
39249bcc50f1SBarry Smith 
39251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
39269b94acceSBarry Smith @*/
3927d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3928d71ae5a4SJacob Faibussowitsch {
39293a40ed3dSBarry Smith   PetscFunctionBegin;
39300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3931c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
39329b94acceSBarry Smith   snes->deltatol = tol;
39333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39349b94acceSBarry Smith }
39359b94acceSBarry Smith 
39366ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
39376ba87a44SLisandro Dalcin 
3938d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3939d71ae5a4SJacob Faibussowitsch {
3940b271bb04SBarry Smith   PetscDrawLG      lg;
3941b271bb04SBarry Smith   PetscReal        x, y, per;
3942b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3943b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3944b271bb04SBarry Smith   PetscDraw        draw;
3945b271bb04SBarry Smith 
3946459f5d12SBarry Smith   PetscFunctionBegin;
39474d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
39489566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
39499566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39509566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39519566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3952b271bb04SBarry Smith   x = (PetscReal)n;
395377b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
395494c9c6d3SKarl Rupp   else y = -15.0;
39559566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39566934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39579566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39589566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3959b271bb04SBarry Smith   }
3960b271bb04SBarry Smith 
39619566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
39629566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39639566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3964aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
39659566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3966b271bb04SBarry Smith   x = (PetscReal)n;
3967b271bb04SBarry Smith   y = 100.0 * per;
39689566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39696934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39709566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39719566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3972b271bb04SBarry Smith   }
3973b271bb04SBarry Smith 
39749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
39759371c9d4SSatish Balay   if (!n) {
39769371c9d4SSatish Balay     prev = rnorm;
39779371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
39789371c9d4SSatish Balay   }
39799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39809566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3981b271bb04SBarry Smith   x = (PetscReal)n;
3982b271bb04SBarry Smith   y = (prev - rnorm) / prev;
39839566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39846934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39859566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39869566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3987b271bb04SBarry Smith   }
3988b271bb04SBarry Smith 
39899566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
39909566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39919566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39929566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3993b271bb04SBarry Smith   x = (PetscReal)n;
3994b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3995b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3997b271bb04SBarry Smith   }
39986934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39999566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40009566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4001b271bb04SBarry Smith   }
4002b271bb04SBarry Smith   prev = rnorm;
40033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4004b271bb04SBarry Smith }
4005b271bb04SBarry Smith 
4006228d79bcSJed Brown /*@
40072d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
40082d157150SStefano Zampini 
40092d157150SStefano Zampini   Collective
40102d157150SStefano Zampini 
40112d157150SStefano Zampini   Input Parameters:
40122d157150SStefano Zampini + snes  - the `SNES` context
40132d157150SStefano Zampini . it    - current iteration
40142d157150SStefano Zampini . xnorm - 2-norm of current iterate
40152d157150SStefano Zampini . snorm - 2-norm of current step
40162d157150SStefano Zampini - fnorm - 2-norm of function
40172d157150SStefano Zampini 
40182d157150SStefano Zampini   Level: developer
40192d157150SStefano Zampini 
40202d157150SStefano Zampini   Note:
4021420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
40222d157150SStefano Zampini   It does not typically need to be called by the user.
40232d157150SStefano Zampini 
4024be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
40252d157150SStefano Zampini @*/
40262d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
40272d157150SStefano Zampini {
40282d157150SStefano Zampini   PetscFunctionBegin;
40292d157150SStefano Zampini   if (!snes->reason) {
40302d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
40312d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
40322d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
40332d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
40342d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
40352d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
40362d157150SStefano Zampini     }
40372d157150SStefano Zampini   }
40382d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
40392d157150SStefano Zampini }
40402d157150SStefano Zampini 
40412d157150SStefano Zampini /*@
4042228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4043228d79bcSJed Brown 
4044c3339decSBarry Smith   Collective
4045228d79bcSJed Brown 
4046228d79bcSJed Brown   Input Parameters:
4047f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4048228d79bcSJed Brown . iter  - iteration number
4049228d79bcSJed Brown - rnorm - relative norm of the residual
4050228d79bcSJed Brown 
4051dc4c0fb0SBarry Smith   Level: developer
4052dc4c0fb0SBarry Smith 
4053f6dfbefdSBarry Smith   Note:
4054420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4055228d79bcSJed Brown   It does not typically need to be called by the user.
4056228d79bcSJed Brown 
40571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4058228d79bcSJed Brown @*/
4059d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4060d71ae5a4SJacob Faibussowitsch {
40617a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
40627a03ce2fSLisandro Dalcin 
40637a03ce2fSLisandro Dalcin   PetscFunctionBegin;
40645f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
40659566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
406648a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
40679566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
40683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40697a03ce2fSLisandro Dalcin }
40707a03ce2fSLisandro Dalcin 
40719b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
40729b94acceSBarry Smith 
4073bf388a1fSBarry Smith /*MC
4074f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4075bf388a1fSBarry Smith 
4076bf388a1fSBarry Smith      Synopsis:
4077aaa7dc30SBarry Smith      #include <petscsnes.h>
407837fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4079bf388a1fSBarry Smith 
4080c3339decSBarry Smith      Collective
40811843f636SBarry Smith 
40821843f636SBarry Smith     Input Parameters:
4083f6dfbefdSBarry Smith +    snes - the `SNES` context
4084bf388a1fSBarry Smith .    its - iteration number
4085bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4086bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4087bf388a1fSBarry Smith 
4088878cb397SSatish Balay    Level: advanced
4089878cb397SSatish Balay 
40901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4091bf388a1fSBarry Smith M*/
4092bf388a1fSBarry Smith 
40939b94acceSBarry Smith /*@C
4094a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
40959b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
40969b94acceSBarry Smith   progress.
40979b94acceSBarry Smith 
4098c3339decSBarry Smith   Logically Collective
4099fee21e36SBarry Smith 
4100c7afd0dbSLois Curfman McInnes   Input Parameters:
4101f6dfbefdSBarry Smith + snes           - the `SNES` context
410220f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4103420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4104dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
41059b94acceSBarry Smith 
41069665c990SLois Curfman McInnes   Options Database Keys:
4107f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4108798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4109dc4c0fb0SBarry 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
4110c7afd0dbSLois Curfman McInnes                                 the options database.
41119665c990SLois Curfman McInnes 
4112dc4c0fb0SBarry Smith   Level: intermediate
4113dc4c0fb0SBarry Smith 
4114f6dfbefdSBarry Smith   Note:
41156bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4116f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
41176bc08f3fSLois Curfman McInnes   order in which they were set.
4118639f9d9dSBarry Smith 
4119420bcc1bSBarry Smith   Fortran Note:
4120f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4121025f1a04SBarry Smith 
41221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
41239b94acceSBarry Smith @*/
4124d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4125d71ae5a4SJacob Faibussowitsch {
4126b90d0a6eSBarry Smith   PetscInt  i;
412778064530SBarry Smith   PetscBool identical;
4128b90d0a6eSBarry Smith 
41293a40ed3dSBarry Smith   PetscFunctionBegin;
41300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4131b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
41329566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
41333ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4134649052a6SBarry Smith   }
41355f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
41366e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4137b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4138639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
41393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41409b94acceSBarry Smith }
41419b94acceSBarry Smith 
4142a278d85bSSatish Balay /*@
4143f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
41445cd90555SBarry Smith 
4145c3339decSBarry Smith   Logically Collective
4146c7afd0dbSLois Curfman McInnes 
41472fe279fdSBarry Smith   Input Parameter:
4148f6dfbefdSBarry Smith . snes - the `SNES` context
41495cd90555SBarry Smith 
41501a480d89SAdministrator   Options Database Key:
4151a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4152dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4153c7afd0dbSLois Curfman McInnes     set via the options database
41545cd90555SBarry Smith 
4155dc4c0fb0SBarry Smith   Level: intermediate
4156dc4c0fb0SBarry Smith 
4157f6dfbefdSBarry Smith   Note:
4158f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
41595cd90555SBarry Smith 
41601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
41615cd90555SBarry Smith @*/
4162d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4163d71ae5a4SJacob Faibussowitsch {
4164d952e501SBarry Smith   PetscInt i;
4165d952e501SBarry Smith 
41665cd90555SBarry Smith   PetscFunctionBegin;
41670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4168d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
416948a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4170d952e501SBarry Smith   }
41715cd90555SBarry Smith   snes->numbermonitors = 0;
41723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41735cd90555SBarry Smith }
41745cd90555SBarry Smith 
4175bf388a1fSBarry Smith /*MC
4176bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4177bf388a1fSBarry Smith 
4178bf388a1fSBarry Smith      Synopsis:
4179aaa7dc30SBarry Smith      #include <petscsnes.h>
418037fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4181bf388a1fSBarry Smith 
4182c3339decSBarry Smith      Collective
41831843f636SBarry Smith 
41841843f636SBarry Smith     Input Parameters:
4185f6dfbefdSBarry Smith +    snes - the `SNES` context
4186bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4187bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4188bf388a1fSBarry Smith .    gnorm - 2-norm of current step
41891843f636SBarry Smith .    f - 2-norm of function
41901843f636SBarry Smith -    cctx - [optional] convergence context
41911843f636SBarry Smith 
41921843f636SBarry Smith     Output Parameter:
41931843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4194bf388a1fSBarry Smith 
4195878cb397SSatish Balay    Level: intermediate
4196bf388a1fSBarry Smith 
41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4198bf388a1fSBarry Smith M*/
4199bf388a1fSBarry Smith 
42009b94acceSBarry Smith /*@C
42019b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
42029b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
42039b94acceSBarry Smith 
4204c3339decSBarry Smith   Logically Collective
4205fee21e36SBarry Smith 
4206c7afd0dbSLois Curfman McInnes   Input Parameters:
4207f6dfbefdSBarry Smith + snes                        - the `SNES` context
4208e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4209dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4210dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
42119b94acceSBarry Smith 
421236851e7fSLois Curfman McInnes   Level: advanced
421336851e7fSLois Curfman McInnes 
42141cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
42159b94acceSBarry Smith @*/
4216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4217d71ae5a4SJacob Faibussowitsch {
42183a40ed3dSBarry Smith   PetscFunctionBegin;
42190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4220e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
42211baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4222bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
42237f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
422485385478SLisandro Dalcin   snes->cnvP                  = cctx;
42253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42269b94acceSBarry Smith }
42279b94acceSBarry Smith 
422852baeb72SSatish Balay /*@
4229f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4230184914b5SBarry Smith 
4231184914b5SBarry Smith   Not Collective
4232184914b5SBarry Smith 
4233184914b5SBarry Smith   Input Parameter:
4234f6dfbefdSBarry Smith . snes - the `SNES` context
4235184914b5SBarry Smith 
4236184914b5SBarry Smith   Output Parameter:
4237f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4238184914b5SBarry Smith 
4239f6dfbefdSBarry Smith   Options Database Key:
42406a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
42416a4d7782SBarry Smith 
4242184914b5SBarry Smith   Level: intermediate
4243184914b5SBarry Smith 
4244f6dfbefdSBarry Smith   Note:
4245f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4246184914b5SBarry Smith 
42471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4248184914b5SBarry Smith @*/
4249d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4250d71ae5a4SJacob Faibussowitsch {
4251184914b5SBarry Smith   PetscFunctionBegin;
42520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42534f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4254184914b5SBarry Smith   *reason = snes->reason;
42553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4256184914b5SBarry Smith }
4257184914b5SBarry Smith 
4258c4421ceaSFande Kong /*@C
4259f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4260c4421ceaSFande Kong 
4261c4421ceaSFande Kong   Not Collective
4262c4421ceaSFande Kong 
4263c4421ceaSFande Kong   Input Parameter:
4264f6dfbefdSBarry Smith . snes - the `SNES` context
4265c4421ceaSFande Kong 
4266c4421ceaSFande Kong   Output Parameter:
4267dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4268c4421ceaSFande Kong 
426999c90e12SSatish Balay   Level: beginner
4270c4421ceaSFande Kong 
42711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4272c4421ceaSFande Kong @*/
4273d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4274d71ae5a4SJacob Faibussowitsch {
4275c4421ceaSFande Kong   PetscFunctionBegin;
4276c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42774f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4278c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
42793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4280c4421ceaSFande Kong }
4281c4421ceaSFande Kong 
428233866048SMatthew G. Knepley /*@
4283f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
428433866048SMatthew G. Knepley 
428533866048SMatthew G. Knepley   Not Collective
428633866048SMatthew G. Knepley 
428733866048SMatthew G. Knepley   Input Parameters:
4288f6dfbefdSBarry Smith + snes   - the `SNES` context
4289f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
429033866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
429133866048SMatthew G. Knepley 
4292f6dfbefdSBarry Smith   Level: developer
4293f6dfbefdSBarry Smith 
4294420bcc1bSBarry Smith   Developer Note:
4295f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
429633866048SMatthew G. Knepley 
42971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
429833866048SMatthew G. Knepley @*/
4299d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4300d71ae5a4SJacob Faibussowitsch {
430133866048SMatthew G. Knepley   PetscFunctionBegin;
430233866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43035f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
430433866048SMatthew G. Knepley   snes->reason = reason;
43053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
430633866048SMatthew G. Knepley }
430733866048SMatthew G. Knepley 
4308c9005455SLois Curfman McInnes /*@
4309420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4310c9005455SLois Curfman McInnes 
4311c3339decSBarry Smith   Logically Collective
4312fee21e36SBarry Smith 
4313c7afd0dbSLois Curfman McInnes   Input Parameters:
4314f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
43158c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4316cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4317420bcc1bSBarry Smith . na    - size of `a` and `its`
4318f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4319758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4320c7afd0dbSLois Curfman McInnes 
4321dc4c0fb0SBarry Smith   Level: intermediate
4322dc4c0fb0SBarry Smith 
4323308dcc3eSBarry Smith   Notes:
4324dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4325308dcc3eSBarry Smith   default array of length 10000 is allocated.
4326308dcc3eSBarry Smith 
4327c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4328c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4329c9005455SLois Curfman McInnes   during the section of code that is being timed.
4330c9005455SLois Curfman McInnes 
4331420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4332420bcc1bSBarry Smith 
43331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4334c9005455SLois Curfman McInnes @*/
4335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4336d71ae5a4SJacob Faibussowitsch {
43373a40ed3dSBarry Smith   PetscFunctionBegin;
43380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43394f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
43404f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
43417a1ec6d4SBarry Smith   if (!a) {
4342308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
43439566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4344071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4345308dcc3eSBarry Smith   }
4346c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4347758f92a0SBarry Smith   snes->conv_hist_its   = its;
4348115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4349a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4350758f92a0SBarry Smith   snes->conv_hist_reset = reset;
43513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4352758f92a0SBarry Smith }
4353758f92a0SBarry Smith 
4354d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4355c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4356c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
435799e0435eSBarry Smith 
4358d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4359d71ae5a4SJacob Faibussowitsch {
4360308dcc3eSBarry Smith   mxArray   *mat;
4361308dcc3eSBarry Smith   PetscInt   i;
4362308dcc3eSBarry Smith   PetscReal *ar;
4363308dcc3eSBarry Smith 
4364308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4365308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4366f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
436711cc89d2SBarry Smith   return mat;
4368308dcc3eSBarry Smith }
4369308dcc3eSBarry Smith #endif
4370308dcc3eSBarry Smith 
43710c4c9dddSBarry Smith /*@C
4372420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4373758f92a0SBarry Smith 
43743f9fe445SBarry Smith   Not Collective
4375758f92a0SBarry Smith 
4376758f92a0SBarry Smith   Input Parameter:
4377f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4378758f92a0SBarry Smith 
4379758f92a0SBarry Smith   Output Parameters:
4380f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4381758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4382758f92a0SBarry Smith          negative if not converged) for each solve.
438320f4b53cSBarry Smith - na  - size of `a` and `its`
4384758f92a0SBarry Smith 
4385dc4c0fb0SBarry Smith   Level: intermediate
4386dc4c0fb0SBarry Smith 
438720f4b53cSBarry Smith   Note:
438820f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
438920f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
439020f4b53cSBarry Smith   during the section of code that is being timed.
439120f4b53cSBarry Smith 
4392420bcc1bSBarry Smith   Fortran Note:
4393758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4394dc4c0fb0SBarry Smith .vb
4395dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4396dc4c0fb0SBarry Smith .ve
4397758f92a0SBarry Smith 
43981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4399758f92a0SBarry Smith @*/
4400d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4401d71ae5a4SJacob Faibussowitsch {
4402758f92a0SBarry Smith   PetscFunctionBegin;
44030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4404758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4405758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4406115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
44073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4408c9005455SLois Curfman McInnes }
4409c9005455SLois Curfman McInnes 
4410ac226902SBarry Smith /*@C
441176b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4412eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
441353e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
441453e5d35bSStefano Zampini   evaluation.
441576b2cf59SMatthew Knepley 
4416c3339decSBarry Smith   Logically Collective
441776b2cf59SMatthew Knepley 
441876b2cf59SMatthew Knepley   Input Parameters:
4419a2b725a8SWilliam Gropp + snes - The nonlinear solver context
442053e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
442176b2cf59SMatthew Knepley 
4422fe97e370SBarry Smith   Level: advanced
4423fe97e370SBarry Smith 
4424420bcc1bSBarry Smith   Notes:
4425f6dfbefdSBarry 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
4426f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
442753e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
442853e5d35bSStefano Zampini   right before the direction step is computed.
442953e5d35bSStefano Zampini   Users are free to modify the current residual vector,
443053e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
443153e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
443253e5d35bSStefano Zampini   vectors.
443376b2cf59SMatthew Knepley 
4434aaa8cc7dSPierre 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.
44356b7fb656SBarry Smith 
4436e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
443753e5d35bSStefano Zampini          `SNESMonitorSet()`
443876b2cf59SMatthew Knepley @*/
443953e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4440d71ae5a4SJacob Faibussowitsch {
444176b2cf59SMatthew Knepley   PetscFunctionBegin;
44420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4443e7788613SBarry Smith   snes->ops->update = func;
44443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
444576b2cf59SMatthew Knepley }
444676b2cf59SMatthew Knepley 
4447ffeef943SBarry Smith /*@
4448f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
44492a359c20SBarry Smith 
4450c3339decSBarry Smith   Collective
44512a359c20SBarry Smith 
4452e4094ef1SJacob Faibussowitsch   Input Parameters:
4453f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
44542a359c20SBarry Smith - viewer - the viewer to display the reason
44552a359c20SBarry Smith 
44562a359c20SBarry Smith   Options Database Keys:
4457ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4458ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4459eafd5ff0SAlex Lindsay 
4460420bcc1bSBarry Smith   Level: beginner
4461420bcc1bSBarry Smith 
4462f6dfbefdSBarry Smith   Note:
4463f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4464f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
44652a359c20SBarry Smith 
44661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4467f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4468f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4469db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
44702a359c20SBarry Smith @*/
4471d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4472d71ae5a4SJacob Faibussowitsch {
447375cca76cSMatthew G. Knepley   PetscViewerFormat format;
44742a359c20SBarry Smith   PetscBool         isAscii;
44752a359c20SBarry Smith 
44762a359c20SBarry Smith   PetscFunctionBegin;
447719a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
44789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
44792a359c20SBarry Smith   if (isAscii) {
44809566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
448165bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
448275cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
448375cca76cSMatthew G. Knepley       DM       dm;
448475cca76cSMatthew G. Knepley       Vec      u;
448575cca76cSMatthew G. Knepley       PetscDS  prob;
448675cca76cSMatthew G. Knepley       PetscInt Nf, f;
448795cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
448895cbbfd3SMatthew G. Knepley       void    **exactCtx;
448975cca76cSMatthew G. Knepley       PetscReal error;
449075cca76cSMatthew G. Knepley 
44919566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44929566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44939566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44949566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44959566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44969566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44979566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44989566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44999566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
450063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
450175cca76cSMatthew G. Knepley     }
4502eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
45032a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
450463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
45052a359c20SBarry Smith       } else {
450663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45072a359c20SBarry Smith       }
4508eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
45092a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
451063a3b9bcSJacob 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));
45112a359c20SBarry Smith       } else {
451263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45132a359c20SBarry Smith       }
45142a359c20SBarry Smith     }
451565bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
45162a359c20SBarry Smith   }
45173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45182a359c20SBarry Smith }
45192a359c20SBarry Smith 
4520c4421ceaSFande Kong /*@C
4521c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4522aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4523c4421ceaSFande Kong 
4524c3339decSBarry Smith   Logically Collective
4525c4421ceaSFande Kong 
4526c4421ceaSFande Kong   Input Parameters:
4527f6dfbefdSBarry Smith + snes              - the `SNES` context
4528420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4529420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4530420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4531420bcc1bSBarry Smith 
4532420bcc1bSBarry Smith   Calling sequence of `f`:
4533420bcc1bSBarry Smith + snes - the `SNES` context
4534420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4535420bcc1bSBarry Smith 
4536420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4537420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4538c4421ceaSFande Kong 
4539c4421ceaSFande Kong   Options Database Keys:
4540f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4541420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4542420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4543c4421ceaSFande Kong 
4544dc4c0fb0SBarry Smith   Level: intermediate
4545dc4c0fb0SBarry Smith 
4546f6dfbefdSBarry Smith   Note:
4547c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4548f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4549c4421ceaSFande Kong   order in which they were set.
4550c4421ceaSFande Kong 
45511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4552c4421ceaSFande Kong @*/
4553420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4554d71ae5a4SJacob Faibussowitsch {
4555c4421ceaSFande Kong   PetscInt  i;
4556c4421ceaSFande Kong   PetscBool identical;
4557c4421ceaSFande Kong 
4558c4421ceaSFande Kong   PetscFunctionBegin;
4559c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4560c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
45619566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
45623ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4563c4421ceaSFande Kong   }
45645f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4565c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4566c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4567c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
45683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4569c4421ceaSFande Kong }
4570c4421ceaSFande Kong 
457191f3e32bSBarry Smith /*@
4572420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4573c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
45742a359c20SBarry Smith 
4575c3339decSBarry Smith   Collective
45762a359c20SBarry Smith 
45772fe279fdSBarry Smith   Input Parameter:
4578f6dfbefdSBarry Smith . snes - the `SNES` object
45792a359c20SBarry Smith 
4580f6dfbefdSBarry Smith   Level: advanced
45812a359c20SBarry Smith 
45821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4583f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
45842a359c20SBarry Smith @*/
4585d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4586d71ae5a4SJacob Faibussowitsch {
45872a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
45882a359c20SBarry Smith 
45892a359c20SBarry Smith   PetscFunctionBegin;
45903ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
45912a359c20SBarry Smith   incall = PETSC_TRUE;
4592c4421ceaSFande Kong 
4593c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
459436d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4595c4421ceaSFande Kong 
4596c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
459736d43d94SBarry Smith   if (snes->convergedreasonviewer) {
459836d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
459936d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
460036d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
46012a359c20SBarry Smith   }
46022a359c20SBarry Smith   incall = PETSC_FALSE;
46033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46042a359c20SBarry Smith }
46052a359c20SBarry Smith 
4606487a658cSBarry Smith /*@
4607f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
46089b94acceSBarry Smith 
4609c3339decSBarry Smith   Collective
4610c7afd0dbSLois Curfman McInnes 
4611b2002411SLois Curfman McInnes   Input Parameters:
4612f6dfbefdSBarry Smith + snes - the `SNES` context
4613dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
461485385478SLisandro Dalcin - x    - the solution vector.
46159b94acceSBarry Smith 
4616dc4c0fb0SBarry Smith   Level: beginner
4617dc4c0fb0SBarry Smith 
4618f6dfbefdSBarry Smith   Note:
4619420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4620420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
46218ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4622f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
46238ddd3da0SLois Curfman McInnes 
46241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4625db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4626420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
46279b94acceSBarry Smith @*/
4628d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4629d71ae5a4SJacob Faibussowitsch {
4630ace3abfcSBarry Smith   PetscBool flg;
4631efd51863SBarry Smith   PetscInt  grid;
46320298fd71SBarry Smith   Vec       xcreated = NULL;
4633caa4e7f2SJed Brown   DM        dm;
4634052efed2SBarry Smith 
46353a40ed3dSBarry Smith   PetscFunctionBegin;
46360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4637a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4638a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
46390700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
464085385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
464185385478SLisandro Dalcin 
464234b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
464306fc46c8SMatthew G. Knepley   {
464406fc46c8SMatthew G. Knepley     PetscViewer       viewer;
464506fc46c8SMatthew G. Knepley     PetscViewerFormat format;
46467c88af5aSMatthew G. Knepley     PetscInt          num;
464706fc46c8SMatthew G. Knepley     PetscBool         flg;
464806fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
464906fc46c8SMatthew G. Knepley 
465006fc46c8SMatthew G. Knepley     if (!incall) {
465134b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4652648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
465306fc46c8SMatthew G. Knepley       if (flg) {
465406fc46c8SMatthew G. Knepley         PetscConvEst conv;
465546079b62SMatthew G. Knepley         DM           dm;
465646079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
465746079b62SMatthew G. Knepley         PetscInt     Nf;
465806fc46c8SMatthew G. Knepley 
465906fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
46609566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
46619566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
46629566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
46639566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
46649566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
46659566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
46669566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
46679566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
46689566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
46699566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
46709566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4671648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
46729566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
46739566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
467406fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
467506fc46c8SMatthew G. Knepley       }
467634b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4677b2588ea6SMatthew G. Knepley       num = 1;
46789566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
467934b4d3a8SMatthew G. Knepley       if (flg) {
468034b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
468134b4d3a8SMatthew G. Knepley 
468234b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
46839566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46849566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46859566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
469034b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
469134b4d3a8SMatthew G. Knepley       }
46927c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46937c88af5aSMatthew G. Knepley       num = 0;
46949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46957c88af5aSMatthew G. Knepley       if (num) {
46967c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46977c88af5aSMatthew G. Knepley 
46987c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46999566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47009566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47019566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4704*e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
47059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
47069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
47077c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
47087c88af5aSMatthew G. Knepley       }
470906fc46c8SMatthew G. Knepley     }
471006fc46c8SMatthew G. Knepley   }
4711ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4712caa4e7f2SJed Brown   if (!x) {
47139566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
47149566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4715a69afd8bSBarry Smith     x = xcreated;
4716a69afd8bSBarry Smith   }
47179566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4718f05ece33SBarry Smith 
47199566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4720efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
472185385478SLisandro Dalcin     /* set solution vector */
47229566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
47239566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
472485385478SLisandro Dalcin     snes->vec_sol = x;
47259566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4726caa4e7f2SJed Brown 
4727caa4e7f2SJed Brown     /* set affine vector if provided */
47289566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
47299566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
473085385478SLisandro Dalcin     snes->vec_rhs = b;
473185385478SLisandro Dalcin 
47325f80ce2aSJacob 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");
47335f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4734dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4735aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
47369566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
47379566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
47383f149594SLisandro Dalcin 
47397eee914bSBarry Smith     if (!grid) {
47409927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4741dd568438SSatish Balay     }
4742d25893d9SBarry Smith 
4743abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
47449371c9d4SSatish Balay     if (snes->counters_reset) {
47459371c9d4SSatish Balay       snes->nfuncs      = 0;
47469371c9d4SSatish Balay       snes->linear_its  = 0;
47479371c9d4SSatish Balay       snes->numFailures = 0;
47489371c9d4SSatish Balay     }
4749d5e45103SBarry Smith 
47502d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
47519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4752dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
47539566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
47542d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4755422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
47563f149594SLisandro Dalcin 
475737ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
475837ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
475937ec4e1aSPeter Brune 
4760648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
47619566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4762c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
47639566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
47645968eb51SBarry Smith 
47655f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
47669c8e83a9SBarry Smith     if (snes->reason < 0) break;
4767efd51863SBarry Smith     if (grid < snes->gridsequence) {
4768efd51863SBarry Smith       DM  fine;
4769efd51863SBarry Smith       Vec xnew;
4770efd51863SBarry Smith       Mat interp;
4771efd51863SBarry Smith 
47729566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
47735f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
47749566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
47759566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
47769566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
47779566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
47789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4779efd51863SBarry Smith       x = xnew;
4780efd51863SBarry Smith 
47819566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
47829566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
47839566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
47849566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
47859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4786efd51863SBarry Smith     }
4787efd51863SBarry Smith   }
47889566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47899566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47909566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47923f7e2da0SPeter Brune 
47939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47949566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47969b94acceSBarry Smith }
47979b94acceSBarry Smith 
47989b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47999b94acceSBarry Smith 
4800cc4c1da9SBarry Smith /*@
48014b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
48029b94acceSBarry Smith 
4803c3339decSBarry Smith   Collective
4804fee21e36SBarry Smith 
4805c7afd0dbSLois Curfman McInnes   Input Parameters:
4806f6dfbefdSBarry Smith + snes - the `SNES` context
4807454a90a3SBarry Smith - type - a known method
4808c7afd0dbSLois Curfman McInnes 
4809c7afd0dbSLois Curfman McInnes   Options Database Key:
4810454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
481104d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4812ae12b187SLois Curfman McInnes 
4813dc4c0fb0SBarry Smith   Level: intermediate
4814dc4c0fb0SBarry Smith 
48159b94acceSBarry Smith   Notes:
4816e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4817f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4818c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48194a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4820c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48219b94acceSBarry Smith 
4822f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4823f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4824ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4825ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4826f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4827ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4828ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4829ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4830ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4831b0a32e0cSBarry Smith   appropriate method.
483236851e7fSLois Curfman McInnes 
4833420bcc1bSBarry Smith   Developer Note:
4834f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4835f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
48368f6c3df8SBarry Smith 
48371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
48389b94acceSBarry Smith @*/
4839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4840d71ae5a4SJacob Faibussowitsch {
4841ace3abfcSBarry Smith   PetscBool match;
48425f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
48433a40ed3dSBarry Smith 
48443a40ed3dSBarry Smith   PetscFunctionBegin;
48450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48464f572ea9SToby Isaac   PetscAssertPointer(type, 2);
484782bf6240SBarry Smith 
48489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
48493ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
485092ff6ae8SBarry Smith 
48519566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
48526adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
485375396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4854dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
485575396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
48569e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
48579e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
48589e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
48599e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
48609e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
48617fe760d5SStefano Zampini 
48627fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
48639566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
48647fe760d5SStefano Zampini 
486575396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
486675396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4867f5af7f23SKarl Rupp 
48689566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
48699566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
48703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48719b94acceSBarry Smith }
48729b94acceSBarry Smith 
4873cc4c1da9SBarry Smith /*@
4874f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
48759b94acceSBarry Smith 
4876c7afd0dbSLois Curfman McInnes   Not Collective
4877c7afd0dbSLois Curfman McInnes 
48789b94acceSBarry Smith   Input Parameter:
48794b0e389bSBarry Smith . snes - nonlinear solver context
48809b94acceSBarry Smith 
48819b94acceSBarry Smith   Output Parameter:
4882f6dfbefdSBarry Smith . type - `SNES` method (a character string)
48839b94acceSBarry Smith 
488436851e7fSLois Curfman McInnes   Level: intermediate
488536851e7fSLois Curfman McInnes 
48861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48879b94acceSBarry Smith @*/
4888d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4889d71ae5a4SJacob Faibussowitsch {
48903a40ed3dSBarry Smith   PetscFunctionBegin;
48910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48924f572ea9SToby Isaac   PetscAssertPointer(type, 2);
48937adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48959b94acceSBarry Smith }
48969b94acceSBarry Smith 
48973cd8a7caSMatthew G. Knepley /*@
4898f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48993cd8a7caSMatthew G. Knepley 
4900c3339decSBarry Smith   Logically Collective
49013cd8a7caSMatthew G. Knepley 
49023cd8a7caSMatthew G. Knepley   Input Parameters:
4903f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
49043cd8a7caSMatthew G. Knepley - u    - the solution vector
49053cd8a7caSMatthew G. Knepley 
49063cd8a7caSMatthew G. Knepley   Level: beginner
49073cd8a7caSMatthew G. Knepley 
49081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
49093cd8a7caSMatthew G. Knepley @*/
4910d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4911d71ae5a4SJacob Faibussowitsch {
49123cd8a7caSMatthew G. Knepley   DM dm;
49133cd8a7caSMatthew G. Knepley 
49143cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
49153cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49163cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
49179566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
49189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
49193cd8a7caSMatthew G. Knepley 
49203cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
49213cd8a7caSMatthew G. Knepley 
49229566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49239566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
49243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49253cd8a7caSMatthew G. Knepley }
49263cd8a7caSMatthew G. Knepley 
492752baeb72SSatish Balay /*@
49289b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4929f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
49309b94acceSBarry Smith 
4931420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4932c7afd0dbSLois Curfman McInnes 
49339b94acceSBarry Smith   Input Parameter:
4934f6dfbefdSBarry Smith . snes - the `SNES` context
49359b94acceSBarry Smith 
49369b94acceSBarry Smith   Output Parameter:
49379b94acceSBarry Smith . x - the solution
49389b94acceSBarry Smith 
493970e92668SMatthew Knepley   Level: intermediate
494036851e7fSLois Curfman McInnes 
49411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
49429b94acceSBarry Smith @*/
4943d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4944d71ae5a4SJacob Faibussowitsch {
49453a40ed3dSBarry Smith   PetscFunctionBegin;
49460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49474f572ea9SToby Isaac   PetscAssertPointer(x, 2);
494885385478SLisandro Dalcin   *x = snes->vec_sol;
49493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
495070e92668SMatthew Knepley }
495170e92668SMatthew Knepley 
495252baeb72SSatish Balay /*@
49539b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
49549b94acceSBarry Smith   stored.
49559b94acceSBarry Smith 
4956420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4957c7afd0dbSLois Curfman McInnes 
49589b94acceSBarry Smith   Input Parameter:
4959f6dfbefdSBarry Smith . snes - the `SNES` context
49609b94acceSBarry Smith 
49619b94acceSBarry Smith   Output Parameter:
49629b94acceSBarry Smith . x - the solution update
49639b94acceSBarry Smith 
496436851e7fSLois Curfman McInnes   Level: advanced
496536851e7fSLois Curfman McInnes 
49661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
49679b94acceSBarry Smith @*/
4968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4969d71ae5a4SJacob Faibussowitsch {
49703a40ed3dSBarry Smith   PetscFunctionBegin;
49710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49724f572ea9SToby Isaac   PetscAssertPointer(x, 2);
497385385478SLisandro Dalcin   *x = snes->vec_sol_update;
49743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49759b94acceSBarry Smith }
49769b94acceSBarry Smith 
49779b94acceSBarry Smith /*@C
4978f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
49799b94acceSBarry Smith 
4980420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
4981c7afd0dbSLois Curfman McInnes 
49829b94acceSBarry Smith   Input Parameter:
4983f6dfbefdSBarry Smith . snes - the `SNES` context
49849b94acceSBarry Smith 
4985d8d19677SJose E. Roman   Output Parameters:
4986dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
49878434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
4988dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
49899b94acceSBarry Smith 
499036851e7fSLois Curfman McInnes   Level: advanced
499136851e7fSLois Curfman McInnes 
4992f6dfbefdSBarry Smith   Note:
4993dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
499404edfde5SBarry Smith 
49958434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
49969b94acceSBarry Smith @*/
49978434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
4998d71ae5a4SJacob Faibussowitsch {
49996cab3a1bSJed Brown   DM dm;
5000a63bb30eSJed Brown 
50013a40ed3dSBarry Smith   PetscFunctionBegin;
50020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5003a63bb30eSJed Brown   if (r) {
5004a63bb30eSJed Brown     if (!snes->vec_func) {
5005a63bb30eSJed Brown       if (snes->vec_rhs) {
50069566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5007a63bb30eSJed Brown       } else if (snes->vec_sol) {
50089566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5009a63bb30eSJed Brown       } else if (snes->dm) {
50109566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5011a63bb30eSJed Brown       }
5012a63bb30eSJed Brown     }
5013a63bb30eSJed Brown     *r = snes->vec_func;
5014a63bb30eSJed Brown   }
50159566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50169566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
50173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50189b94acceSBarry Smith }
50199b94acceSBarry Smith 
5020c79ef259SPeter Brune /*@C
502137fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5022c79ef259SPeter Brune 
5023c79ef259SPeter Brune   Input Parameter:
5024f6dfbefdSBarry Smith . snes - the `SNES` context
5025c79ef259SPeter Brune 
5026d8d19677SJose E. Roman   Output Parameters:
50278434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5028dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5029c79ef259SPeter Brune 
5030c79ef259SPeter Brune   Level: advanced
5031c79ef259SPeter Brune 
50328434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5033c79ef259SPeter Brune @*/
50348434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5035d71ae5a4SJacob Faibussowitsch {
50366cab3a1bSJed Brown   DM dm;
50376cab3a1bSJed Brown 
5038646217ecSPeter Brune   PetscFunctionBegin;
5039646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50409566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50419566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
50423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5043646217ecSPeter Brune }
5044646217ecSPeter Brune 
5045cc4c1da9SBarry Smith /*@
50463c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5047f6dfbefdSBarry Smith   `SNES` options in the database.
50483c7409f5SSatish Balay 
5049c3339decSBarry Smith   Logically Collective
5050fee21e36SBarry Smith 
5051d8d19677SJose E. Roman   Input Parameters:
5052f6dfbefdSBarry Smith + snes   - the `SNES` context
5053c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5054c7afd0dbSLois Curfman McInnes 
5055dc4c0fb0SBarry Smith   Level: advanced
5056dc4c0fb0SBarry Smith 
5057f6dfbefdSBarry Smith   Note:
5058a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5059c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5060d850072dSLois Curfman McInnes 
50611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
50623c7409f5SSatish Balay @*/
5063d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5064d71ae5a4SJacob Faibussowitsch {
50653a40ed3dSBarry Smith   PetscFunctionBegin;
50660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50679566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
50689566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
506935f5d045SPeter Brune   if (snes->linesearch) {
50709566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50719566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
507235f5d045SPeter Brune   }
50739566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
50743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50753c7409f5SSatish Balay }
50763c7409f5SSatish Balay 
5077cc4c1da9SBarry Smith /*@
5078f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5079f6dfbefdSBarry Smith   `SNES` options in the database.
50803c7409f5SSatish Balay 
5081c3339decSBarry Smith   Logically Collective
5082fee21e36SBarry Smith 
5083c7afd0dbSLois Curfman McInnes   Input Parameters:
5084f6dfbefdSBarry Smith + snes   - the `SNES` context
5085c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5086c7afd0dbSLois Curfman McInnes 
5087dc4c0fb0SBarry Smith   Level: advanced
5088dc4c0fb0SBarry Smith 
5089f6dfbefdSBarry Smith   Note:
5090a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5091c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5092d850072dSLois Curfman McInnes 
50931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50943c7409f5SSatish Balay @*/
5095d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5096d71ae5a4SJacob Faibussowitsch {
50973a40ed3dSBarry Smith   PetscFunctionBegin;
50980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50999566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
51009566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
510135f5d045SPeter Brune   if (snes->linesearch) {
51029566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51039566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
510435f5d045SPeter Brune   }
51059566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
51063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51073c7409f5SSatish Balay }
51083c7409f5SSatish Balay 
5109cc4c1da9SBarry Smith /*@
5110f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5111f6dfbefdSBarry Smith   `SNES` options in the database.
51123c7409f5SSatish Balay 
5113c7afd0dbSLois Curfman McInnes   Not Collective
5114c7afd0dbSLois Curfman McInnes 
51153c7409f5SSatish Balay   Input Parameter:
5116f6dfbefdSBarry Smith . snes - the `SNES` context
51173c7409f5SSatish Balay 
51183c7409f5SSatish Balay   Output Parameter:
51193c7409f5SSatish Balay . prefix - pointer to the prefix string used
51203c7409f5SSatish Balay 
512136851e7fSLois Curfman McInnes   Level: advanced
512236851e7fSLois Curfman McInnes 
5123420bcc1bSBarry Smith   Fortran Note:
5124dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5125dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5126dc4c0fb0SBarry Smith 
51271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
51283c7409f5SSatish Balay @*/
5129d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5130d71ae5a4SJacob Faibussowitsch {
51313a40ed3dSBarry Smith   PetscFunctionBegin;
51320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
51343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51353c7409f5SSatish Balay }
51363c7409f5SSatish Balay 
51373cea93caSBarry Smith /*@C
51381c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
51391c84c290SBarry Smith 
514020f4b53cSBarry Smith   Not Collective
51411c84c290SBarry Smith 
51421c84c290SBarry Smith   Input Parameters:
514320f4b53cSBarry Smith + sname    - name of a new user-defined solver
514420f4b53cSBarry Smith - function - routine to create method context
51451c84c290SBarry Smith 
5146dc4c0fb0SBarry Smith   Level: advanced
5147dc4c0fb0SBarry Smith 
5148f6dfbefdSBarry Smith   Note:
5149f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
51501c84c290SBarry Smith 
5151e4094ef1SJacob Faibussowitsch   Example Usage:
51521c84c290SBarry Smith .vb
5153bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
51541c84c290SBarry Smith .ve
51551c84c290SBarry Smith 
51561c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
51571c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
51581c84c290SBarry Smith   or at runtime via the option
51591c84c290SBarry Smith $     -snes_type my_solver
51601c84c290SBarry Smith 
51611cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
51623cea93caSBarry Smith @*/
5163d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5164d71ae5a4SJacob Faibussowitsch {
5165b2002411SLois Curfman McInnes   PetscFunctionBegin;
51669566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
51679566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
51683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5169b2002411SLois Curfman McInnes }
5170da9b6338SBarry Smith 
5171d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5172d71ae5a4SJacob Faibussowitsch {
517377431f27SBarry Smith   PetscInt    N, i, j;
5174da9b6338SBarry Smith   Vec         u, uh, fh;
5175da9b6338SBarry Smith   PetscScalar value;
5176da9b6338SBarry Smith   PetscReal   norm;
5177da9b6338SBarry Smith 
5178da9b6338SBarry Smith   PetscFunctionBegin;
51799566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
51809566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
51819566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5182da9b6338SBarry Smith 
5183da9b6338SBarry Smith   /* currently only works for sequential */
51849566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51859566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5186da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51879566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
518863a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5189da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51908b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51919566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51929566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51939566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
519463a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5195da9b6338SBarry Smith       value = -value;
51969566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5197da9b6338SBarry Smith     }
5198da9b6338SBarry Smith   }
51999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
52009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
52013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5202da9b6338SBarry Smith }
520371f87433Sdalcinl 
520471f87433Sdalcinl /*@
5205f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
520671f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
520771f87433Sdalcinl   Newton method.
520871f87433Sdalcinl 
5209c3339decSBarry Smith   Logically Collective
521071f87433Sdalcinl 
521171f87433Sdalcinl   Input Parameters:
5212f6dfbefdSBarry Smith + snes - `SNES` context
5213f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
521471f87433Sdalcinl 
5215f6dfbefdSBarry Smith   Options Database Keys:
521664ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
521764ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
521864ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
521964ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
522064ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
522164ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
522264ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
522364ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
522464ba62caSBarry Smith 
5225dc4c0fb0SBarry Smith   Level: advanced
5226dc4c0fb0SBarry Smith 
5227f6dfbefdSBarry Smith   Note:
5228f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
522971f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
52301d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
523171f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
523271f87433Sdalcinl   solver.
523371f87433Sdalcinl 
52341cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
523571f87433Sdalcinl @*/
5236d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5237d71ae5a4SJacob Faibussowitsch {
523871f87433Sdalcinl   PetscFunctionBegin;
52390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5240acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
524171f87433Sdalcinl   snes->ksp_ewconv = flag;
52423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
524371f87433Sdalcinl }
524471f87433Sdalcinl 
524571f87433Sdalcinl /*@
5246f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
524771f87433Sdalcinl   for computing relative tolerance for linear solvers within an
524871f87433Sdalcinl   inexact Newton method.
524971f87433Sdalcinl 
525071f87433Sdalcinl   Not Collective
525171f87433Sdalcinl 
525271f87433Sdalcinl   Input Parameter:
5253f6dfbefdSBarry Smith . snes - `SNES` context
525471f87433Sdalcinl 
525571f87433Sdalcinl   Output Parameter:
5256f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
525771f87433Sdalcinl 
525871f87433Sdalcinl   Level: advanced
525971f87433Sdalcinl 
52601cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
526171f87433Sdalcinl @*/
5262d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5263d71ae5a4SJacob Faibussowitsch {
526471f87433Sdalcinl   PetscFunctionBegin;
52650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52664f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
526771f87433Sdalcinl   *flag = snes->ksp_ewconv;
52683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
526971f87433Sdalcinl }
527071f87433Sdalcinl 
527171f87433Sdalcinl /*@
5272fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
527371f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
527471f87433Sdalcinl   Newton method.
527571f87433Sdalcinl 
5276c3339decSBarry Smith   Logically Collective
527771f87433Sdalcinl 
527871f87433Sdalcinl   Input Parameters:
5279f6dfbefdSBarry Smith + snes      - `SNES` context
52800f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
528171f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
528271f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
528371f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
528471f87433Sdalcinl              (0 <= gamma2 <= 1)
528571f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
528671f87433Sdalcinl . alpha2    - power for safeguard
528771f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
528871f87433Sdalcinl 
5289dc4c0fb0SBarry Smith   Level: advanced
5290dc4c0fb0SBarry Smith 
5291f6dfbefdSBarry Smith   Notes:
529271f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
529371f87433Sdalcinl 
5294f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
529571f87433Sdalcinl 
52961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
529771f87433Sdalcinl @*/
5298d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5299d71ae5a4SJacob Faibussowitsch {
5300fa9f3622SBarry Smith   SNESKSPEW *kctx;
53015fd66863SKarl Rupp 
530271f87433Sdalcinl   PetscFunctionBegin;
53030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5304fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53055f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5306c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5307c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5308c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5309c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5310c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5311c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5312c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
531371f87433Sdalcinl 
531471f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
531513bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
531613bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
531713bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
531813bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
531913bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
532013bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
532171f87433Sdalcinl 
53220f0abf79SStefano 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);
53230b121fc5SBarry 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);
53240b121fc5SBarry 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);
53250b121fc5SBarry 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);
53260b121fc5SBarry 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);
53270b121fc5SBarry 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);
53283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532971f87433Sdalcinl }
533071f87433Sdalcinl 
533171f87433Sdalcinl /*@
5332fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
533371f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
533471f87433Sdalcinl   Newton method.
533571f87433Sdalcinl 
533671f87433Sdalcinl   Not Collective
533771f87433Sdalcinl 
533897bb3fdcSJose E. Roman   Input Parameter:
5339f6dfbefdSBarry Smith . snes - `SNES` context
534071f87433Sdalcinl 
534171f87433Sdalcinl   Output Parameters:
53420f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
534371f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
534471f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5345bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
534671f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
534771f87433Sdalcinl . alpha2    - power for safeguard
534871f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
534971f87433Sdalcinl 
535071f87433Sdalcinl   Level: advanced
535171f87433Sdalcinl 
53521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
535371f87433Sdalcinl @*/
5354d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5355d71ae5a4SJacob Faibussowitsch {
5356fa9f3622SBarry Smith   SNESKSPEW *kctx;
53575fd66863SKarl Rupp 
535871f87433Sdalcinl   PetscFunctionBegin;
53590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5360fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53615f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
536271f87433Sdalcinl   if (version) *version = kctx->version;
536371f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
536471f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
536571f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
536671f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
536771f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
536871f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
53693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537071f87433Sdalcinl }
537171f87433Sdalcinl 
53725c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5373d71ae5a4SJacob Faibussowitsch {
53745c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5375fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
537671f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
537771f87433Sdalcinl 
537871f87433Sdalcinl   PetscFunctionBegin;
53793ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
538030058271SDmitry Karpeev   if (!snes->iter) {
538130058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
53829566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53830f0abf79SStefano Zampini   } else {
53840fdf79fbSJacob 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);
538571f87433Sdalcinl     if (kctx->version == 1) {
53860f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
538785ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
538871f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
538971f87433Sdalcinl     } else if (kctx->version == 2) {
539085ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
539185ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
539271f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
539371f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
539485ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
539571f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
539685ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
539771f87433Sdalcinl       stol = PetscMax(rtol, stol);
539871f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
539971f87433Sdalcinl       /* safeguard: avoid oversolving */
540030058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
540171f87433Sdalcinl       stol = PetscMax(rtol, stol);
540271f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
54030fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
54040fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
54050f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
54060f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
54070f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
54080f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
54090f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
54100f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
54110f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
54120f0abf79SStefano Zampini 
5413a4598233SStefano 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;
54140f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
54150f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
54160f0abf79SStefano Zampini       kctx->rk_last     = rk;
54170fdf79fbSJacob Faibussowitsch     }
54180f0abf79SStefano Zampini   }
54190f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
542071f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
54219566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
542263a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
54233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542471f87433Sdalcinl }
542571f87433Sdalcinl 
54265c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5427d71ae5a4SJacob Faibussowitsch {
54285c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5429fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
543071f87433Sdalcinl   PCSide     pcside;
543171f87433Sdalcinl   Vec        lres;
543271f87433Sdalcinl 
543371f87433Sdalcinl   PetscFunctionBegin;
54343ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
54359566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
543671dbe336SPeter Brune   kctx->norm_last = snes->norm;
54370f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
54384f00ce20SMatthew G. Knepley     PC        pc;
54390f0abf79SStefano Zampini     PetscBool getRes;
54404f00ce20SMatthew G. Knepley 
54419566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
54420f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
54430f0abf79SStefano Zampini     if (!getRes) {
54440f0abf79SStefano Zampini       KSPNormType normtype;
54450f0abf79SStefano Zampini 
54460f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
54470f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
54480f0abf79SStefano Zampini     }
54499566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
54500f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
54519566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
545271f87433Sdalcinl     } else {
545371f87433Sdalcinl       /* KSP residual is preconditioned residual */
545471f87433Sdalcinl       /* compute true linear residual norm */
54550f0abf79SStefano Zampini       Mat J;
54560f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
54579566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
54580f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
54599566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
54609566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
54619566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
546271f87433Sdalcinl     }
546371f87433Sdalcinl   }
54643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546571f87433Sdalcinl }
546671f87433Sdalcinl 
5467d4211eb9SBarry Smith /*@
5468f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5469d4211eb9SBarry Smith 
5470420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5471d4211eb9SBarry Smith 
5472d4211eb9SBarry Smith   Input Parameter:
5473f6dfbefdSBarry Smith . snes - the `SNES` context
5474d4211eb9SBarry Smith 
5475d4211eb9SBarry Smith   Output Parameter:
5476f6dfbefdSBarry Smith . ksp - the `KSP` context
5477d4211eb9SBarry Smith 
5478dc4c0fb0SBarry Smith   Level: beginner
5479dc4c0fb0SBarry Smith 
5480d4211eb9SBarry Smith   Notes:
5481f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5482d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5483f6dfbefdSBarry Smith   `PC` contexts as well.
5484f6dfbefdSBarry Smith 
5485f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5486d4211eb9SBarry Smith 
54871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5488d4211eb9SBarry Smith @*/
5489d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5490d71ae5a4SJacob Faibussowitsch {
549171f87433Sdalcinl   PetscFunctionBegin;
5492d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54934f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5494d4211eb9SBarry Smith 
5495d4211eb9SBarry Smith   if (!snes->ksp) {
54969566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54979566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5498d4211eb9SBarry Smith 
54995c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
55005c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5501a5c2985bSBarry Smith 
55029566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
55039566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5504d4211eb9SBarry Smith   }
5505d4211eb9SBarry Smith   *ksp = snes->ksp;
55063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550771f87433Sdalcinl }
55086c699258SBarry Smith 
5509af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
55106c699258SBarry Smith /*@
5511f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
55126c699258SBarry Smith 
5513c3339decSBarry Smith   Logically Collective
55146c699258SBarry Smith 
55156c699258SBarry Smith   Input Parameters:
55162a808120SBarry Smith + snes - the nonlinear solver context
5517420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5518dc4c0fb0SBarry Smith 
5519dc4c0fb0SBarry Smith   Level: intermediate
55206c699258SBarry Smith 
5521f6dfbefdSBarry Smith   Note:
5522f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5523f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5524e03a659cSJed Brown   problems using the same function space.
5525e03a659cSJed Brown 
5526420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
55276c699258SBarry Smith @*/
5528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5529d71ae5a4SJacob Faibussowitsch {
5530345fed2cSBarry Smith   KSP    ksp;
5531942e3340SBarry Smith   DMSNES sdm;
55326c699258SBarry Smith 
55336c699258SBarry Smith   PetscFunctionBegin;
55340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55352a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
55369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5537942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
553851f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
55399566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
55409566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5541f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
55426cab3a1bSJed Brown     }
55439566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
55449566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
55456cab3a1bSJed Brown   }
55466c699258SBarry Smith   snes->dm     = dm;
5547116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5548f5af7f23SKarl Rupp 
55499566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
55509566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
55519566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5552efd4aadfSBarry Smith   if (snes->npc) {
55539566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
55549566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
55552c155ee1SBarry Smith   }
55563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55576c699258SBarry Smith }
55586c699258SBarry Smith 
55596c699258SBarry Smith /*@
5560420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
55616c699258SBarry Smith 
5562f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
55636c699258SBarry Smith 
55646c699258SBarry Smith   Input Parameter:
5565420bcc1bSBarry Smith . snes - the `SNES` context
55666c699258SBarry Smith 
55676c699258SBarry Smith   Output Parameter:
5568420bcc1bSBarry Smith . dm - the `DM`
55696c699258SBarry Smith 
55706c699258SBarry Smith   Level: intermediate
55716c699258SBarry Smith 
5572420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
55736c699258SBarry Smith @*/
5574d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5575d71ae5a4SJacob Faibussowitsch {
55766c699258SBarry Smith   PetscFunctionBegin;
55770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55786cab3a1bSJed Brown   if (!snes->dm) {
55799566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5580116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
55816cab3a1bSJed Brown   }
55826c699258SBarry Smith   *dm = snes->dm;
55833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55846c699258SBarry Smith }
55850807856dSBarry Smith 
558631823bd8SMatthew G Knepley /*@
5587be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
558831823bd8SMatthew G Knepley 
5589c3339decSBarry Smith   Collective
559031823bd8SMatthew G Knepley 
559131823bd8SMatthew G Knepley   Input Parameters:
5592f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5593420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
559431823bd8SMatthew G Knepley 
5595dc4c0fb0SBarry Smith   Level: developer
5596dc4c0fb0SBarry Smith 
559731823bd8SMatthew G Knepley   Notes:
5598f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
559931823bd8SMatthew G Knepley   to configure it using the API).
560031823bd8SMatthew G Knepley 
5601f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5602f6dfbefdSBarry Smith 
5603420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
560431823bd8SMatthew G Knepley @*/
5605d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5606d71ae5a4SJacob Faibussowitsch {
560731823bd8SMatthew G Knepley   PetscFunctionBegin;
560831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5609f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5610f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5611f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
56129566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5613f6dfbefdSBarry Smith   snes->npc = npc;
56143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
561531823bd8SMatthew G Knepley }
561631823bd8SMatthew G Knepley 
561731823bd8SMatthew G Knepley /*@
5618f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
561931823bd8SMatthew G Knepley 
5620f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
562131823bd8SMatthew G Knepley 
562231823bd8SMatthew G Knepley   Input Parameter:
5623f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
562431823bd8SMatthew G Knepley 
562531823bd8SMatthew G Knepley   Output Parameter:
5626e4094ef1SJacob Faibussowitsch . pc - preconditioner context
562731823bd8SMatthew G Knepley 
5628f6dfbefdSBarry Smith   Options Database Key:
5629f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5630b5badacbSBarry Smith 
5631dc4c0fb0SBarry Smith   Level: developer
5632dc4c0fb0SBarry Smith 
563395452b02SPatrick Sanan   Notes:
5634f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5635be95d8f1SBarry Smith 
5636f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5637f6dfbefdSBarry Smith   `SNES`
5638951fe5abSBarry Smith 
56391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
564031823bd8SMatthew G Knepley @*/
5641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5642d71ae5a4SJacob Faibussowitsch {
5643a64e098fSPeter Brune   const char *optionsprefix;
564431823bd8SMatthew G Knepley 
564531823bd8SMatthew G Knepley   PetscFunctionBegin;
564631823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56474f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5648efd4aadfSBarry Smith   if (!snes->npc) {
5649ec785e5bSStefano Zampini     void *ctx;
5650ec785e5bSStefano Zampini 
56519566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
56529566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
56539566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
56549566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
56559566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5656fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5657fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5658fb87a551SStefano Zampini     } else {
5659ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5660ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5661fb87a551SStefano Zampini     }
56629566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
566331823bd8SMatthew G Knepley   }
5664efd4aadfSBarry Smith   *pc = snes->npc;
56653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566631823bd8SMatthew G Knepley }
566731823bd8SMatthew G Knepley 
56683ad1a0b9SPatrick Farrell /*@
56693ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
56703ad1a0b9SPatrick Farrell 
56713ad1a0b9SPatrick Farrell   Not Collective
56723ad1a0b9SPatrick Farrell 
56733ad1a0b9SPatrick Farrell   Input Parameter:
5674f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56753ad1a0b9SPatrick Farrell 
56763ad1a0b9SPatrick Farrell   Output Parameter:
5677420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
56783ad1a0b9SPatrick Farrell 
56793ad1a0b9SPatrick Farrell   Level: developer
56803ad1a0b9SPatrick Farrell 
56811cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
56823ad1a0b9SPatrick Farrell @*/
5683d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5684d71ae5a4SJacob Faibussowitsch {
56853ad1a0b9SPatrick Farrell   PetscFunctionBegin;
56863ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5687efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56893ad1a0b9SPatrick Farrell }
56903ad1a0b9SPatrick Farrell 
5691c40d0f55SPeter Brune /*@
5692420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5693c40d0f55SPeter Brune 
5694c3339decSBarry Smith   Logically Collective
5695c40d0f55SPeter Brune 
5696c40d0f55SPeter Brune   Input Parameter:
5697f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5698c40d0f55SPeter Brune 
5699c40d0f55SPeter Brune   Output Parameter:
5700c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5701c40d0f55SPeter Brune .vb
57022d547940SBarry Smith       PC_LEFT - left preconditioning
57032d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5704c40d0f55SPeter Brune .ve
5705c40d0f55SPeter Brune 
5706f6dfbefdSBarry Smith   Options Database Key:
570767b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5708c40d0f55SPeter Brune 
5709dc4c0fb0SBarry Smith   Level: intermediate
5710dc4c0fb0SBarry Smith 
5711f6dfbefdSBarry Smith   Note:
5712f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
57132d547940SBarry Smith 
5714420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5715c40d0f55SPeter Brune @*/
5716d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5717d71ae5a4SJacob Faibussowitsch {
5718c40d0f55SPeter Brune   PetscFunctionBegin;
5719c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5720c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5721b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
572254c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5723efd4aadfSBarry Smith   snes->npcside = side;
57243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5725c40d0f55SPeter Brune }
5726c40d0f55SPeter Brune 
5727c40d0f55SPeter Brune /*@
5728be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5729c40d0f55SPeter Brune 
5730c40d0f55SPeter Brune   Not Collective
5731c40d0f55SPeter Brune 
5732c40d0f55SPeter Brune   Input Parameter:
5733f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5734c40d0f55SPeter Brune 
5735c40d0f55SPeter Brune   Output Parameter:
5736c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5737c40d0f55SPeter Brune .vb
5738f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5739f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5740c40d0f55SPeter Brune .ve
5741c40d0f55SPeter Brune 
5742c40d0f55SPeter Brune   Level: intermediate
5743c40d0f55SPeter Brune 
5744420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5745c40d0f55SPeter Brune @*/
5746d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5747d71ae5a4SJacob Faibussowitsch {
5748c40d0f55SPeter Brune   PetscFunctionBegin;
5749c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57504f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5751efd4aadfSBarry Smith   *side = snes->npcside;
57523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5753c40d0f55SPeter Brune }
5754c40d0f55SPeter Brune 
57559e764e56SPeter Brune /*@
5756420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
57579e764e56SPeter Brune 
5758c3339decSBarry Smith   Collective
57599e764e56SPeter Brune 
57609e764e56SPeter Brune   Input Parameters:
5761f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
57629e764e56SPeter Brune - linesearch - the linesearch object
57639e764e56SPeter Brune 
5764dc4c0fb0SBarry Smith   Level: developer
5765dc4c0fb0SBarry Smith 
5766f6dfbefdSBarry Smith   Note:
5767420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
57689e764e56SPeter Brune   to configure it using the API).
57699e764e56SPeter Brune 
5770420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
57719e764e56SPeter Brune @*/
5772d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5773d71ae5a4SJacob Faibussowitsch {
57749e764e56SPeter Brune   PetscFunctionBegin;
57759e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5776f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
57779e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
57789566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
57799566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5780f5af7f23SKarl Rupp 
57819e764e56SPeter Brune   snes->linesearch = linesearch;
57823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57839e764e56SPeter Brune }
57849e764e56SPeter Brune 
5785a34ceb2aSJed Brown /*@
5786420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5787f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57889e764e56SPeter Brune 
57899e764e56SPeter Brune   Not Collective
57909e764e56SPeter Brune 
57919e764e56SPeter Brune   Input Parameter:
5792f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57939e764e56SPeter Brune 
57949e764e56SPeter Brune   Output Parameter:
57959e764e56SPeter Brune . linesearch - linesearch context
57969e764e56SPeter Brune 
5797162e0bf5SPeter Brune   Level: beginner
57989e764e56SPeter Brune 
57991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
58009e764e56SPeter Brune @*/
5801d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5802d71ae5a4SJacob Faibussowitsch {
58039e764e56SPeter Brune   const char *optionsprefix;
58049e764e56SPeter Brune 
58059e764e56SPeter Brune   PetscFunctionBegin;
58069e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58074f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
58089e764e56SPeter Brune   if (!snes->linesearch) {
58099566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58109566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
58119566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
58129566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
58139566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
58149e764e56SPeter Brune   }
58159e764e56SPeter Brune   *linesearch = snes->linesearch;
58163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58179e764e56SPeter Brune }
5818