1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
276c63389SBarry Smith #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h" I*/
307475bc1SBarry Smith #include <petscdmshell.h>
4d96771aaSLisandro Dalcin #include <petscdraw.h>
5a01aa210SMatthew G. Knepley #include <petscds.h>
634b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
706fc46c8SMatthew G. Knepley #include <petscconvest.h>
89b94acceSBarry Smith
9ace3abfcSBarry Smith PetscBool SNESRegisterAllCalled = PETSC_FALSE;
100298fd71SBarry Smith PetscFunctionList SNESList = NULL;
118ba1e511SMatthew Knepley
128ba1e511SMatthew Knepley /* Logging support */
1322c6f798SBarry Smith PetscClassId SNES_CLASSID, DMSNES_CLASSID;
1497276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval;
15a09944afSBarry Smith
16e113a28aSBarry Smith /*@
17dc4c0fb0SBarry Smith SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
18e113a28aSBarry Smith
19c3339decSBarry Smith Logically Collective
20e113a28aSBarry Smith
21e113a28aSBarry Smith Input Parameters:
22f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
23f6dfbefdSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
24e113a28aSBarry Smith
2520f4b53cSBarry Smith Options Database Key:
2667b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
27e113a28aSBarry Smith
28e113a28aSBarry Smith Level: intermediate
29e113a28aSBarry Smith
30f6dfbefdSBarry Smith Note:
31f6dfbefdSBarry Smith Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
32f6dfbefdSBarry Smith to determine if it has converged. Otherwise the solution may be inaccurate or wrong
33e113a28aSBarry Smith
341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
35e113a28aSBarry Smith @*/
SNESSetErrorIfNotConverged(SNES snes,PetscBool flg)36d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
37d71ae5a4SJacob Faibussowitsch {
38e113a28aSBarry Smith PetscFunctionBegin;
39e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
40acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flg, 2);
41e113a28aSBarry Smith snes->errorifnotconverged = flg;
423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43e113a28aSBarry Smith }
44e113a28aSBarry Smith
45e113a28aSBarry Smith /*@
46f6dfbefdSBarry Smith SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
47e113a28aSBarry Smith
48e113a28aSBarry Smith Not Collective
49e113a28aSBarry Smith
50e113a28aSBarry Smith Input Parameter:
51f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
52e113a28aSBarry Smith
53e113a28aSBarry Smith Output Parameter:
54f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
55e113a28aSBarry Smith
56e113a28aSBarry Smith Level: intermediate
57e113a28aSBarry Smith
581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
59e113a28aSBarry Smith @*/
SNESGetErrorIfNotConverged(SNES snes,PetscBool * flag)60d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
61d71ae5a4SJacob Faibussowitsch {
62e113a28aSBarry Smith PetscFunctionBegin;
63e113a28aSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
644f572ea9SToby Isaac PetscAssertPointer(flag, 2);
65e113a28aSBarry Smith *flag = snes->errorifnotconverged;
663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
67e113a28aSBarry Smith }
68e113a28aSBarry Smith
694fc747eaSLawrence Mitchell /*@
70dc4c0fb0SBarry Smith SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution
714fc747eaSLawrence Mitchell
72c3339decSBarry Smith Logically Collective
734fc747eaSLawrence Mitchell
744fc747eaSLawrence Mitchell Input Parameters:
75f6dfbefdSBarry Smith + snes - the shell `SNES`
76f6dfbefdSBarry Smith - flg - `PETSC_TRUE` to always compute the residual
774fc747eaSLawrence Mitchell
784fc747eaSLawrence Mitchell Level: advanced
794fc747eaSLawrence Mitchell
80f6dfbefdSBarry Smith Note:
81f6dfbefdSBarry Smith Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it
82f6dfbefdSBarry Smith to save time.
83f6dfbefdSBarry Smith
84420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()`
854fc747eaSLawrence Mitchell @*/
SNESSetAlwaysComputesFinalResidual(SNES snes,PetscBool flg)86d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
87d71ae5a4SJacob Faibussowitsch {
884fc747eaSLawrence Mitchell PetscFunctionBegin;
894fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
904fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = flg;
913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
924fc747eaSLawrence Mitchell }
934fc747eaSLawrence Mitchell
944fc747eaSLawrence Mitchell /*@
95f6dfbefdSBarry Smith SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution
964fc747eaSLawrence Mitchell
97c3339decSBarry Smith Logically Collective
984fc747eaSLawrence Mitchell
994fc747eaSLawrence Mitchell Input Parameter:
100f6dfbefdSBarry Smith . snes - the `SNES` context
1014fc747eaSLawrence Mitchell
1024fc747eaSLawrence Mitchell Output Parameter:
103f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed
1044fc747eaSLawrence Mitchell
1054fc747eaSLawrence Mitchell Level: advanced
1064fc747eaSLawrence Mitchell
107420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1084fc747eaSLawrence Mitchell @*/
SNESGetAlwaysComputesFinalResidual(SNES snes,PetscBool * flg)109d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
110d71ae5a4SJacob Faibussowitsch {
1114fc747eaSLawrence Mitchell PetscFunctionBegin;
1124fc747eaSLawrence Mitchell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1134fc747eaSLawrence Mitchell *flg = snes->alwayscomputesfinalresidual;
1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1154fc747eaSLawrence Mitchell }
1164fc747eaSLawrence Mitchell
117e725d27bSBarry Smith /*@
118f6dfbefdSBarry Smith SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
11976c63389SBarry Smith in the function's domain. For example, a step with negative pressure.
1204936397dSBarry Smith
1216b1535e8SBarry Smith Not Collective
1224936397dSBarry Smith
1232fe279fdSBarry Smith Input Parameter:
124f6dfbefdSBarry Smith . snes - the `SNES` context
1254936397dSBarry Smith
12628529972SSatish Balay Level: advanced
1274936397dSBarry Smith
128ced0f3aeSBarry Smith Notes:
1296b1535e8SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator.
1306b1535e8SBarry Smith
13176c63389SBarry Smith A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and
13276c63389SBarry Smith returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
133ced0f3aeSBarry Smith
134f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
135f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
136f0b84518SBarry Smith
13776c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
13876c63389SBarry Smith
1396b1535e8SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
1406b1535e8SBarry Smith
1416b1535e8SBarry Smith Developer Note:
14276c63389SBarry Smith This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
1436b1535e8SBarry Smith
1448434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
1456b1535e8SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
14676c63389SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetObjectiveDomainError()`
1474936397dSBarry Smith @*/
SNESSetFunctionDomainError(SNES snes)148d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
149d71ae5a4SJacob Faibussowitsch {
1504936397dSBarry Smith PetscFunctionBegin;
1510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15276c63389SBarry Smith snes->functiondomainerror = PETSC_TRUE;
15376c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS);
15476c63389SBarry Smith }
15576c63389SBarry Smith
15676c63389SBarry Smith /*@
15776c63389SBarry Smith SNESSetObjectiveDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetObjective()` is not
15876c63389SBarry Smith in the function's domain. For example, a step with negative pressure.
15976c63389SBarry Smith
16076c63389SBarry Smith Not Collective
16176c63389SBarry Smith
16276c63389SBarry Smith Input Parameter:
16376c63389SBarry Smith . snes - the `SNES` context
16476c63389SBarry Smith
16576c63389SBarry Smith Level: advanced
16676c63389SBarry Smith
16776c63389SBarry Smith Notes:
16876c63389SBarry Smith This does not need to be called by all processes in the `SNES` MPI communicator.
16976c63389SBarry Smith
17076c63389SBarry Smith A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and
17176c63389SBarry Smith returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
17276c63389SBarry Smith
17376c63389SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
17476c63389SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
17576c63389SBarry Smith
17676c63389SBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
17776c63389SBarry Smith
17876c63389SBarry Smith You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
17976c63389SBarry Smith
18076c63389SBarry Smith Developer Note:
18176c63389SBarry Smith This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
18276c63389SBarry Smith
18376c63389SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
18476c63389SBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
18576c63389SBarry Smith `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetFunctionDomainError()`
18676c63389SBarry Smith @*/
SNESSetObjectiveDomainError(SNES snes)18776c63389SBarry Smith PetscErrorCode SNESSetObjectiveDomainError(SNES snes)
18876c63389SBarry Smith {
18976c63389SBarry Smith PetscFunctionBegin;
19076c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
19176c63389SBarry Smith snes->objectivedomainerror = PETSC_TRUE;
1923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1934936397dSBarry Smith }
1944936397dSBarry Smith
1956a388c36SPeter Brune /*@
196f6dfbefdSBarry Smith SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
19707b62357SFande Kong
198c3339decSBarry Smith Logically Collective
19907b62357SFande Kong
2002fe279fdSBarry Smith Input Parameter:
201f6dfbefdSBarry Smith . snes - the `SNES` context
20207b62357SFande Kong
20307b62357SFande Kong Level: advanced
20407b62357SFande Kong
205ced0f3aeSBarry Smith Notes:
206ced0f3aeSBarry Smith If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
207ced0f3aeSBarry Smith
208ced0f3aeSBarry Smith You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
209ced0f3aeSBarry Smith
210f0b84518SBarry Smith You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
211f0b84518SBarry Smith `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
212f0b84518SBarry Smith
2138434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
214ced0f3aeSBarry Smith `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
21507b62357SFande Kong @*/
SNESSetJacobianDomainError(SNES snes)216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
217d71ae5a4SJacob Faibussowitsch {
21807b62357SFande Kong PetscFunctionBegin;
21907b62357SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2205f80ce2aSJacob Faibussowitsch PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
22107b62357SFande Kong snes->jacobiandomainerror = PETSC_TRUE;
2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22307b62357SFande Kong }
22407b62357SFande Kong
22507b62357SFande Kong /*@
22676c63389SBarry Smith SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` to indicate a Jacobian domain error after
22776c63389SBarry Smith each Jacobian evaluation.
228b351a90bSFande Kong
229c3339decSBarry Smith Logically Collective
230b351a90bSFande Kong
231b351a90bSFande Kong Input Parameters:
23220f4b53cSBarry Smith + snes - the `SNES` context
233f6dfbefdSBarry Smith - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation
234b351a90bSFande Kong
235b351a90bSFande Kong Level: advanced
236b351a90bSFande Kong
23776c63389SBarry Smith Notes:
23876c63389SBarry Smith By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode.
23976c63389SBarry Smith
240f6dfbefdSBarry Smith Checks require one extra parallel synchronization for each Jacobian evaluation
241f6dfbefdSBarry Smith
2428434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
243b351a90bSFande Kong @*/
SNESSetCheckJacobianDomainError(SNES snes,PetscBool flg)244d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
245d71ae5a4SJacob Faibussowitsch {
246b351a90bSFande Kong PetscFunctionBegin;
247b351a90bSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
248b351a90bSFande Kong snes->checkjacdomainerror = flg;
2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
250b351a90bSFande Kong }
251b351a90bSFande Kong
252b351a90bSFande Kong /*@
253420bcc1bSBarry Smith SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2548383d7d7SFande Kong
255c3339decSBarry Smith Logically Collective
2568383d7d7SFande Kong
2572fe279fdSBarry Smith Input Parameter:
258f6dfbefdSBarry Smith . snes - the `SNES` context
2598383d7d7SFande Kong
2602fe279fdSBarry Smith Output Parameter:
261420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2628383d7d7SFande Kong
2638383d7d7SFande Kong Level: advanced
2648383d7d7SFande Kong
2658434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2668383d7d7SFande Kong @*/
SNESGetCheckJacobianDomainError(SNES snes,PetscBool * flg)267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
268d71ae5a4SJacob Faibussowitsch {
2698383d7d7SFande Kong PetscFunctionBegin;
2708383d7d7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2714f572ea9SToby Isaac PetscAssertPointer(flg, 2);
2728383d7d7SFande Kong *flg = snes->checkjacdomainerror;
2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2748383d7d7SFande Kong }
2758383d7d7SFande Kong
2768383d7d7SFande Kong /*@
277f6dfbefdSBarry Smith SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27855849f57SBarry Smith
279c3339decSBarry Smith Collective
28055849f57SBarry Smith
28155849f57SBarry Smith Input Parameters:
282e4094ef1SJacob Faibussowitsch + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
283f6dfbefdSBarry Smith some related function before a call to `SNESLoad()`.
284f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28555849f57SBarry Smith
28655849f57SBarry Smith Level: intermediate
28755849f57SBarry Smith
288f6dfbefdSBarry Smith Note:
289420bcc1bSBarry Smith The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
29055849f57SBarry Smith
2911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29255849f57SBarry Smith @*/
SNESLoad(SNES snes,PetscViewer viewer)293d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
294d71ae5a4SJacob Faibussowitsch {
29555849f57SBarry Smith PetscBool isbinary;
296060da220SMatthew G. Knepley PetscInt classid;
29755849f57SBarry Smith char type[256];
29855849f57SBarry Smith KSP ksp;
2992d53ad75SBarry Smith DM dm;
3002d53ad75SBarry Smith DMSNES dmsnes;
30155849f57SBarry Smith
30255849f57SBarry Smith PetscFunctionBegin;
3032d53ad75SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30455849f57SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3065f80ce2aSJacob Faibussowitsch PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30755849f57SBarry Smith
3089566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3095f80ce2aSJacob Faibussowitsch PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3109566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3119566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type));
312dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, load, viewer);
3139566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
3149566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &dmsnes));
3159566063dSJacob Faibussowitsch PetscCall(DMSNESLoad(dmsnes, viewer));
3169566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
3179566063dSJacob Faibussowitsch PetscCall(KSPLoad(ksp, viewer));
3183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
31955849f57SBarry Smith }
3206a388c36SPeter Brune
3219804daf3SBarry Smith #include <petscdraw.h>
322e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
323e04113cfSBarry Smith #include <petscviewersaws.h>
324bfb97211SBarry Smith #endif
3258404b7f3SBarry Smith
326ffeef943SBarry Smith /*@
327dc4c0fb0SBarry Smith SNESViewFromOptions - View a `SNES` based on values in the options database
328fe2efc57SMark
329c3339decSBarry Smith Collective
330fe2efc57SMark
331fe2efc57SMark Input Parameters:
332f6dfbefdSBarry Smith + A - the `SNES` context
333dc4c0fb0SBarry Smith . obj - Optional object that provides the options prefix for the checks
334736c3998SJose E. Roman - name - command line option
335fe2efc57SMark
336fe2efc57SMark Level: intermediate
337f6dfbefdSBarry Smith
3381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
339fe2efc57SMark @*/
SNESViewFromOptions(SNES A,PetscObject obj,const char name[])340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
341d71ae5a4SJacob Faibussowitsch {
342fe2efc57SMark PetscFunctionBegin;
343fe2efc57SMark PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3449566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
346fe2efc57SMark }
347fe2efc57SMark
348789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
349789d8953SBarry Smith
350ffeef943SBarry Smith /*@
351dc4c0fb0SBarry Smith SNESView - Prints or visualizes the `SNES` data structure.
3529b94acceSBarry Smith
353c3339decSBarry Smith Collective
354fee21e36SBarry Smith
355c7afd0dbSLois Curfman McInnes Input Parameters:
356f6dfbefdSBarry Smith + snes - the `SNES` context
357f6dfbefdSBarry Smith - viewer - the `PetscViewer`
358c7afd0dbSLois Curfman McInnes
3599b94acceSBarry Smith Options Database Key:
360f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3619b94acceSBarry Smith
362dc4c0fb0SBarry Smith Level: beginner
363dc4c0fb0SBarry Smith
3649b94acceSBarry Smith Notes:
3659b94acceSBarry Smith The available visualization contexts include
366f6dfbefdSBarry Smith + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
367f6dfbefdSBarry Smith - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
368c8a8ba5cSLois Curfman McInnes output where only the first processor opens
369c8a8ba5cSLois Curfman McInnes the file. All other processors send their
370c8a8ba5cSLois Curfman McInnes data to the first processor to print.
3719b94acceSBarry Smith
372052bf0daSPierre Jolivet The available formats include
373f6dfbefdSBarry Smith + `PETSC_VIEWER_DEFAULT` - standard output (default)
374f6dfbefdSBarry Smith - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
375052bf0daSPierre Jolivet
3763e081fefSLois Curfman McInnes The user can open an alternative visualization context with
377f6dfbefdSBarry Smith `PetscViewerASCIIOpen()` - output to a specified file.
3789b94acceSBarry Smith
379f6dfbefdSBarry Smith In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
380595c91d4SBarry Smith
3811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3829b94acceSBarry Smith @*/
SNESView(SNES snes,PetscViewer viewer)383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
384d71ae5a4SJacob Faibussowitsch {
385fa9f3622SBarry Smith SNESKSPEW *kctx;
38694b7f48cSBarry Smith KSP ksp;
3877f1410a3SPeter Brune SNESLineSearch linesearch;
3889f196a02SMartin Diehl PetscBool isascii, isstring, isbinary, isdraw;
3892d53ad75SBarry Smith DMSNES dmsnes;
390e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
391536b137fSBarry Smith PetscBool issaws;
392bfb97211SBarry Smith #endif
3939b94acceSBarry Smith
3943a40ed3dSBarry Smith PetscFunctionBegin;
3950700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39648a46eb9SPierre Jolivet if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3970700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
398c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, viewer, 2);
39974679c65SBarry Smith
4009f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
404e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
406bfb97211SBarry Smith #endif
4079f196a02SMartin Diehl if (isascii) {
408dc0571f2SMatthew G. Knepley SNESNormSchedule normschedule;
4098404b7f3SBarry Smith DM dm;
4108434afd1SBarry Smith SNESJacobianFn *cJ;
4118404b7f3SBarry Smith void *ctx;
412789d8953SBarry Smith const char *pre = "";
413dc0571f2SMatthew G. Knepley
4149566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41548a46eb9SPierre Jolivet if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n"));
416e7788613SBarry Smith if (snes->ops->view) {
4179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
418dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, view, viewer);
4199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
4200ef38995SBarry Smith }
42177e5a1f9SBarry Smith if (snes->max_funcs == PETSC_UNLIMITED) {
42277e5a1f9SBarry Smith PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
42377e5a1f9SBarry Smith } else {
42463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
42577e5a1f9SBarry Smith }
4269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42748a46eb9SPierre Jolivet if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4299566063dSJacob Faibussowitsch PetscCall(SNESGetNormSchedule(snes, &normschedule));
4309566063dSJacob Faibussowitsch if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule]));
43148a46eb9SPierre Jolivet if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4329b94acceSBarry Smith if (snes->ksp_ewconv) {
433fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx;
4349b94acceSBarry Smith if (kctx) {
43563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4389b94acceSBarry Smith }
4399b94acceSBarry Smith }
440eb1f6c34SBarry Smith if (snes->lagpreconditioner == -1) {
4419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n"));
442eb1f6c34SBarry Smith } else if (snes->lagpreconditioner > 1) {
44363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
444eb1f6c34SBarry Smith }
445eb1f6c34SBarry Smith if (snes->lagjacobian == -1) {
4469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n"));
447eb1f6c34SBarry Smith } else if (snes->lagjacobian > 1) {
44863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
449eb1f6c34SBarry Smith }
4509566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
4519566063dSJacob Faibussowitsch PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
452789d8953SBarry Smith if (snes->mf_operator) {
4539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n"));
454789d8953SBarry Smith pre = "Preconditioning ";
455789d8953SBarry Smith }
4568404b7f3SBarry Smith if (cJ == SNESComputeJacobianDefault) {
4579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre));
4588404b7f3SBarry Smith } else if (cJ == SNESComputeJacobianDefaultColor) {
4599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre));
460789d8953SBarry Smith /* it slightly breaks data encapsulation for access the DMDA information directly */
461789d8953SBarry Smith } else if (cJ == SNESComputeJacobian_DMDA) {
462789d8953SBarry Smith MatFDColoring fdcoloring;
4639566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
464789d8953SBarry Smith if (fdcoloring) {
4659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre));
466789d8953SBarry Smith } else {
4679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre));
468789d8953SBarry Smith }
469996e1cbcSBarry Smith } else if (snes->mf && !snes->mf_operator) {
4709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4718404b7f3SBarry Smith }
4720f5bd95cSBarry Smith } else if (isstring) {
473317d6ea6SBarry Smith const char *type;
4749566063dSJacob Faibussowitsch PetscCall(SNESGetType(snes, &type));
4759566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
476dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer);
47755849f57SBarry Smith } else if (isbinary) {
47855849f57SBarry Smith PetscInt classid = SNES_FILE_CLASSID;
47955849f57SBarry Smith MPI_Comm comm;
48055849f57SBarry Smith PetscMPIInt rank;
48155849f57SBarry Smith char type[256];
48255849f57SBarry Smith
4839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
485dd400576SPatrick Sanan if (rank == 0) {
4869566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4879566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4889566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48955849f57SBarry Smith }
490dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer);
49172a02f06SBarry Smith } else if (isdraw) {
49272a02f06SBarry Smith PetscDraw draw;
49372a02f06SBarry Smith char str[36];
49489fd9fafSBarry Smith PetscReal x, y, bottom, h;
49572a02f06SBarry Smith
4969566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4979566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4989566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4999566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
5009566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
50189fd9fafSBarry Smith bottom = y - h;
5029566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
503dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, view, viewer);
504e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
505536b137fSBarry Smith } else if (issaws) {
506d45a07a7SBarry Smith PetscMPIInt rank;
5072657e9d9SBarry Smith const char *name;
508d45a07a7SBarry Smith
5099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
511dd400576SPatrick Sanan if (!((PetscObject)snes)->amsmem && rank == 0) {
512d45a07a7SBarry Smith char dir[1024];
513d45a07a7SBarry Smith
5149566063dSJacob Faibussowitsch PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5159566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
516792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51748a46eb9SPierre Jolivet if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5189566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
519792fecdfSBarry Smith PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
520f05ece33SBarry Smith }
521bfb97211SBarry Smith #endif
52272a02f06SBarry Smith }
52372a02f06SBarry Smith if (snes->linesearch) {
5249566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch));
5259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
5269566063dSJacob Faibussowitsch PetscCall(SNESLineSearchView(linesearch, viewer));
5279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
52819bcc07fSBarry Smith }
529efd4aadfSBarry Smith if (snes->npc && snes->usesnpc) {
5309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
5319566063dSJacob Faibussowitsch PetscCall(SNESView(snes->npc, viewer));
5329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
5334a0c5b0cSMatthew G Knepley }
5349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5369566063dSJacob Faibussowitsch PetscCall(DMSNESView(dmsnes, viewer));
5379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
5382c155ee1SBarry Smith if (snes->usesksp) {
5399566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
5409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer));
5419566063dSJacob Faibussowitsch PetscCall(KSPView(ksp, viewer));
5429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer));
5432c155ee1SBarry Smith }
54472a02f06SBarry Smith if (isdraw) {
54572a02f06SBarry Smith PetscDraw draw;
5469566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5479566063dSJacob Faibussowitsch PetscCall(PetscDrawPopCurrentPoint(draw));
5487f1410a3SPeter Brune }
5493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5509b94acceSBarry Smith }
5519b94acceSBarry Smith
55276b2cf59SMatthew Knepley /*
55376b2cf59SMatthew Knepley We retain a list of functions that also take SNES command
55476b2cf59SMatthew Knepley line options. These are called at the end SNESSetFromOptions()
55576b2cf59SMatthew Knepley */
55676b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
557a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5586849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55976b2cf59SMatthew Knepley
560ac226902SBarry Smith /*@C
561f6dfbefdSBarry Smith SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
56276b2cf59SMatthew Knepley
56376b2cf59SMatthew Knepley Not Collective
56476b2cf59SMatthew Knepley
56576b2cf59SMatthew Knepley Input Parameter:
56676b2cf59SMatthew Knepley . snescheck - function that checks for options
56776b2cf59SMatthew Knepley
568420bcc1bSBarry Smith Calling sequence of `snescheck`:
569420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
570420bcc1bSBarry Smith
57176b2cf59SMatthew Knepley Level: developer
57276b2cf59SMatthew Knepley
5731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
57476b2cf59SMatthew Knepley @*/
SNESAddOptionsChecker(PetscErrorCode (* snescheck)(SNES snes))575420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
576d71ae5a4SJacob Faibussowitsch {
57776b2cf59SMatthew Knepley PetscFunctionBegin;
57863a3b9bcSJacob Faibussowitsch PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57976b2cf59SMatthew Knepley othersetfromoptions[numberofsetfromoptions++] = snescheck;
5803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
58176b2cf59SMatthew Knepley }
58276b2cf59SMatthew Knepley
SNESSetUpMatrixFree_Private(SNES snes,PetscBool hasOperator,PetscInt version)583d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
584d71ae5a4SJacob Faibussowitsch {
585aa3661deSLisandro Dalcin Mat J;
586895c21f2SBarry Smith MatNullSpace nullsp;
587aa3661deSLisandro Dalcin
588aa3661deSLisandro Dalcin PetscFunctionBegin;
5890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
590aa3661deSLisandro Dalcin
59198613b67SLisandro Dalcin if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
59298613b67SLisandro Dalcin Mat A = snes->jacobian, B = snes->jacobian_pre;
5939566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
59498613b67SLisandro Dalcin }
59598613b67SLisandro Dalcin
5960fdf79fbSJacob Faibussowitsch PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
597aa3661deSLisandro Dalcin if (version == 1) {
5989566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J));
5999566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
6009566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J));
6011e2ae407SBarry Smith /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6020fdf79fbSJacob Faibussowitsch } else /* if (version == 2) */ {
6035f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
604570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
605f6dfbefdSBarry Smith PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
606aa3661deSLisandro Dalcin #else
6072479783cSJose E. Roman SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
608aa3661deSLisandro Dalcin #endif
6090fdf79fbSJacob Faibussowitsch }
610aa3661deSLisandro Dalcin
61101c1178eSBarry Smith /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
612895c21f2SBarry Smith if (snes->jacobian) {
6139566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6141baa6e33SBarry Smith if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
615895c21f2SBarry Smith }
616895c21f2SBarry Smith
61763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
618d3462f78SMatthew Knepley if (hasOperator) {
619aa3661deSLisandro Dalcin /* This version replaces the user provided Jacobian matrix with a
6207addb90fSBarry Smith matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */
6219566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
622aa3661deSLisandro Dalcin } else {
623aa3661deSLisandro Dalcin /* This version replaces both the user-provided Jacobian and the user-
62401c1178eSBarry Smith provided preconditioner Jacobian with the default matrix-free version. */
625b552625fSStefano Zampini if (snes->npcside == PC_LEFT && snes->npc) {
6269566063dSJacob Faibussowitsch if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
627172a4300SPeter Brune } else {
628789d8953SBarry Smith KSP ksp;
629789d8953SBarry Smith PC pc;
630789d8953SBarry Smith PetscBool match;
631789d8953SBarry Smith
6329566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
633aa3661deSLisandro Dalcin /* Force no preconditioner */
6349566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
6359566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc));
6362698c518SLisandro Dalcin PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
637aa3661deSLisandro Dalcin if (!match) {
6389566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6399566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCNONE));
640aa3661deSLisandro Dalcin }
641aa3661deSLisandro Dalcin }
642789d8953SBarry Smith }
6439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
6443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
645aa3661deSLisandro Dalcin }
646aa3661deSLisandro Dalcin
DMRestrictHook_SNESVecSol(DM dmfine,Mat Restrict,Vec Rscale,Mat Inject,DM dmcoarse,PetscCtx ctx)6472a8381b2SBarry Smith static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, PetscCtx ctx)
648d71ae5a4SJacob Faibussowitsch {
649dfe15315SJed Brown SNES snes = (SNES)ctx;
6500298fd71SBarry Smith Vec Xfine, Xfine_named = NULL, Xcoarse;
651dfe15315SJed Brown
652dfe15315SJed Brown PetscFunctionBegin;
65316ebb321SJed Brown if (PetscLogPrintInfo) {
65416ebb321SJed Brown PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6559566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6569566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6579566063dSJacob Faibussowitsch PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6589566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65963a3b9bcSJacob 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));
66016ebb321SJed Brown }
661dfe15315SJed Brown if (dmfine == snes->dm) Xfine = snes->vec_sol;
662dfe15315SJed Brown else {
6639566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
664dfe15315SJed Brown Xfine = Xfine_named;
665dfe15315SJed Brown }
6669566063dSJacob Faibussowitsch PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
667907f5c5aSLawrence Mitchell if (Inject) {
6689566063dSJacob Faibussowitsch PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
669907f5c5aSLawrence Mitchell } else {
6709566063dSJacob Faibussowitsch PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6719566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
672907f5c5aSLawrence Mitchell }
6739566063dSJacob Faibussowitsch PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6749566063dSJacob Faibussowitsch if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
676dfe15315SJed Brown }
677dfe15315SJed Brown
DMCoarsenHook_SNESVecSol(DM dm,DM dmc,PetscCtx ctx)6782a8381b2SBarry Smith static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, PetscCtx ctx)
679d71ae5a4SJacob Faibussowitsch {
68016ebb321SJed Brown PetscFunctionBegin;
6819566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
68316ebb321SJed Brown }
68416ebb321SJed Brown
685a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
686a6950cb2SJed Brown * safely call SNESGetDM() in their residual evaluation routine. */
KSPComputeOperators_SNES(KSP ksp,Mat A,Mat B,PetscCtx ctx)6872a8381b2SBarry Smith static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, PetscCtx ctx)
688d71ae5a4SJacob Faibussowitsch {
689caa4e7f2SJed Brown SNES snes = (SNES)ctx;
69097d931d1SStefano Zampini DMSNES sdm;
6910298fd71SBarry Smith Vec X, Xnamed = NULL;
692dfe15315SJed Brown DM dmsave;
6934e269d77SPeter Brune void *ctxsave;
6948434afd1SBarry Smith SNESJacobianFn *jac = NULL;
695caa4e7f2SJed Brown
696caa4e7f2SJed Brown PetscFunctionBegin;
697dfe15315SJed Brown dmsave = snes->dm;
6989566063dSJacob Faibussowitsch PetscCall(KSPGetDM(ksp, &snes->dm));
699dfe15315SJed Brown if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
70097d931d1SStefano Zampini else {
701309d62e6SStefano Zampini PetscBool has;
702309d62e6SStefano Zampini
70397d931d1SStefano Zampini /* We are on a coarser level, this vec was initialized using a DM restrict hook */
704309d62e6SStefano Zampini PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
705309d62e6SStefano Zampini PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70697d931d1SStefano Zampini PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
707dfe15315SJed Brown X = Xnamed;
7089566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7094e269d77SPeter Brune /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
71048a46eb9SPierre Jolivet if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7114e269d77SPeter Brune }
7124e269d77SPeter Brune
7132b93b426SMatthew G. Knepley /* Compute the operators */
71497d931d1SStefano Zampini PetscCall(DMGetDMSNES(snes->dm, &sdm));
71597d931d1SStefano Zampini if (Xnamed && sdm->ops->computefunction) {
71697d931d1SStefano Zampini /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71797d931d1SStefano Zampini We make sure of this here. Disable affine shift since it is for the finest level */
71897d931d1SStefano Zampini Vec F, saverhs = snes->vec_rhs;
71997d931d1SStefano Zampini
72097d931d1SStefano Zampini snes->vec_rhs = NULL;
72197d931d1SStefano Zampini PetscCall(DMGetGlobalVector(snes->dm, &F));
72297d931d1SStefano Zampini PetscCall(SNESComputeFunction(snes, X, F));
72397d931d1SStefano Zampini PetscCall(DMRestoreGlobalVector(snes->dm, &F));
72497d931d1SStefano Zampini snes->vec_rhs = saverhs;
72597d931d1SStefano Zampini snes->nfuncs--; /* Do not log coarser level evaluations */
72697d931d1SStefano Zampini }
72797d931d1SStefano Zampini /* Make sure KSP DM has the Jacobian computation routine */
72897d931d1SStefano Zampini if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
72976c63389SBarry Smith PetscCall(SNESComputeJacobian(snes, X, A, B)); /* cannot handle previous SNESSetJacobianDomainError() calls */
73097d931d1SStefano Zampini
7312b93b426SMatthew G. Knepley /* Put the previous context back */
73248a46eb9SPierre Jolivet if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7334e269d77SPeter Brune
7349566063dSJacob Faibussowitsch if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
735dfe15315SJed Brown snes->dm = dmsave;
7363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
737caa4e7f2SJed Brown }
738caa4e7f2SJed Brown
7396cab3a1bSJed Brown /*@
740dc4c0fb0SBarry Smith SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7416cab3a1bSJed Brown
7426cab3a1bSJed Brown Collective
7436cab3a1bSJed Brown
7444165533cSJose E. Roman Input Parameter:
74520f4b53cSBarry Smith . snes - `SNES` object to configure
7466cab3a1bSJed Brown
7476cab3a1bSJed Brown Level: developer
7486cab3a1bSJed Brown
749dc4c0fb0SBarry Smith Note:
750dc4c0fb0SBarry 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`
751dc4c0fb0SBarry Smith
75273a84a35SBarry Smith Developer Note:
75373a84a35SBarry Smith The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
75473a84a35SBarry Smith `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
75573a84a35SBarry Smith logic that handles the matrix-free case is desirable.
75673a84a35SBarry Smith
7571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7586cab3a1bSJed Brown @*/
SNESSetUpMatrices(SNES snes)759d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
760d71ae5a4SJacob Faibussowitsch {
7616cab3a1bSJed Brown DM dm;
762942e3340SBarry Smith DMSNES sdm;
7636cab3a1bSJed Brown
7646cab3a1bSJed Brown PetscFunctionBegin;
7659566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
7669566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
76773a84a35SBarry Smith if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7686cab3a1bSJed Brown Mat J;
7696cab3a1bSJed Brown void *functx;
7709566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J));
7719566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7729566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J));
7739566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7749566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
776caa4e7f2SJed Brown } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7776cab3a1bSJed Brown Mat J, B;
7789566063dSJacob Faibussowitsch PetscCall(MatCreateSNESMF(snes, &J));
7799566063dSJacob Faibussowitsch PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7809566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(J));
7819566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B));
78206f20277SJed Brown /* sdm->computejacobian was already set to reach here */
7839566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
7859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
786caa4e7f2SJed Brown } else if (!snes->jacobian_pre) {
7871ba9b98eSMatthew G. Knepley PetscDS prob;
7886cab3a1bSJed Brown Mat J, B;
7891ba9b98eSMatthew G. Knepley PetscBool hasPrec = PETSC_FALSE;
7901ba9b98eSMatthew G. Knepley
7916cab3a1bSJed Brown J = snes->jacobian;
7929566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
7939566063dSJacob Faibussowitsch if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7949566063dSJacob Faibussowitsch if (J) PetscCall(PetscObjectReference((PetscObject)J));
7959566063dSJacob Faibussowitsch else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7969566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(snes->dm, &B));
7979566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&J));
7999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
8006cab3a1bSJed Brown }
801caa4e7f2SJed Brown {
802caa4e7f2SJed Brown KSP ksp;
8039566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
8049566063dSJacob Faibussowitsch PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8059566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
806caa4e7f2SJed Brown }
8073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8086cab3a1bSJed Brown }
8096cab3a1bSJed Brown
810d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *);
811ce78bad3SBarry Smith
SNESMonitorPauseFinal_Internal(SNES snes)812d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
813d71ae5a4SJacob Faibussowitsch {
8145e7c47f3SMatthew G. Knepley PetscFunctionBegin;
8153ba16761SJacob Faibussowitsch if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
816ce78bad3SBarry Smith PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext));
8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8185e7c47f3SMatthew G. Knepley }
8195e7c47f3SMatthew G. Knepley
820fde5950dSBarry Smith /*@C
821fde5950dSBarry Smith SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
822fde5950dSBarry Smith
823c3339decSBarry Smith Collective
824fde5950dSBarry Smith
825fde5950dSBarry Smith Input Parameters:
826dc4c0fb0SBarry Smith + snes - `SNES` object you wish to monitor
827fde5950dSBarry Smith . name - the monitor type one is seeking
828fde5950dSBarry Smith . help - message indicating what monitoring is done
829fde5950dSBarry Smith . manual - manual page for the monitor
83049abdd8aSBarry Smith . monitor - the monitor function, this must use a `PetscViewerFormat` as its context
831f6dfbefdSBarry 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
832fde5950dSBarry Smith
833420bcc1bSBarry Smith Calling sequence of `monitor`:
834420bcc1bSBarry Smith + snes - the nonlinear solver context
835420bcc1bSBarry Smith . it - the current iteration
836420bcc1bSBarry Smith . r - the current function norm
837420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
838420bcc1bSBarry Smith
839420bcc1bSBarry Smith Calling sequence of `monitorsetup`:
840420bcc1bSBarry Smith + snes - the nonlinear solver context
841420bcc1bSBarry Smith - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
842420bcc1bSBarry Smith
843f6dfbefdSBarry Smith Options Database Key:
844f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
845f6dfbefdSBarry Smith
846f6dfbefdSBarry Smith Level: advanced
847fde5950dSBarry Smith
848648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
849db781477SPatrick Sanan `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
850e4094ef1SJacob Faibussowitsch `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
851db781477SPatrick Sanan `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
852c2e3fba1SPatrick Sanan `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
853db781477SPatrick Sanan `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
854db781477SPatrick Sanan `PetscOptionsFList()`, `PetscOptionsEList()`
855fde5950dSBarry Smith @*/
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))856420bcc1bSBarry 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))
857d71ae5a4SJacob Faibussowitsch {
858fde5950dSBarry Smith PetscViewer viewer;
859fde5950dSBarry Smith PetscViewerFormat format;
860fde5950dSBarry Smith PetscBool flg;
861fde5950dSBarry Smith
862fde5950dSBarry Smith PetscFunctionBegin;
863648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
864fde5950dSBarry Smith if (flg) {
865d43b4f6eSBarry Smith PetscViewerAndFormat *vf;
8669566063dSJacob Faibussowitsch PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
867648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer));
8681baa6e33SBarry Smith if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8692a8381b2SBarry Smith PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
870fde5950dSBarry Smith }
8713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
872fde5950dSBarry Smith }
873fde5950dSBarry Smith
SNESEWSetFromOptions_Private(SNESKSPEW * kctx,PetscBool print_api,MPI_Comm comm,const char * prefix)874a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
875d71ae5a4SJacob Faibussowitsch {
876a4598233SStefano Zampini const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
877a4598233SStefano Zampini
8780f0abf79SStefano Zampini PetscFunctionBegin;
8790f0abf79SStefano Zampini PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
880a4598233SStefano Zampini PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
881a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
882a4598233SStefano Zampini kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
883a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
884a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
885a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8860f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
887a4598233SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8880f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8890f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8900f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8910f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8920f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8930f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8940f0abf79SStefano Zampini PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8950f0abf79SStefano Zampini PetscOptionsEnd();
8963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8970f0abf79SStefano Zampini }
8980f0abf79SStefano Zampini
8999b94acceSBarry Smith /*@
900f6dfbefdSBarry Smith SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9019b94acceSBarry Smith
902c3339decSBarry Smith Collective
903c7afd0dbSLois Curfman McInnes
9049b94acceSBarry Smith Input Parameter:
905f6dfbefdSBarry Smith . snes - the `SNES` context
9069b94acceSBarry Smith
90736851e7fSLois Curfman McInnes Options Database Keys:
908f6dfbefdSBarry Smith + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
909b39c3a46SLois Curfman McInnes . -snes_rtol <rtol> - relative decrease in tolerance norm from initial
91077e5a1f9SBarry Smith . -snes_atol <abstol> - absolute tolerance of residual norm
91177e5a1f9SBarry Smith . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps
912e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
913b39c3a46SLois Curfman McInnes . -snes_max_it <max_it> - maximum number of iterations
914b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs> - maximum number of function evaluations
91577e5a1f9SBarry Smith . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration
9164839bfe8SBarry Smith . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
917ddf469c8SBarry Smith . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
918a8054027SBarry Smith . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
9193d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve()
920e35cf81dSBarry Smith . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
9213d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve()
922ceaaa498SBarry Smith . -snes_convergence_test <default,skip,correct_pressure> - convergence test in nonlinear solver. default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense of convergence test. correct_pressure `SNESConvergedCorrectPressure()` has special handling of a pressure null space.
923fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
924fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
925fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
926fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9274619e776SBarry Smith . -snes_monitor_lg_residualnorm - plots residual norm at each iteration
928459f5d12SBarry Smith . -snes_monitor_lg_range - plots residual norm at each iteration
9295e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends
930e24b481bSBarry Smith . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
931e2e60de9SPeter Brune . -snes_fd_color - use finite differences with coloring to compute Jacobian
932ceaaa498SBarry Smith . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration
933b5badacbSBarry Smith . -snes_converged_reason - print the reason for convergence/divergence after each solve
934ceaaa498SBarry Smith . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner
935e62ac41dSBarry Smith . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one computed via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold.
936e62ac41dSBarry Smith - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian.
93782738288SBarry Smith
938f6dfbefdSBarry Smith Options Database Keys for Eisenstat-Walker method:
939fa9f3622SBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
9404b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
94136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
94236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
94336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma> - Sets gamma
94436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha> - Sets alpha
94536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
94636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
94782738288SBarry Smith
948dc4c0fb0SBarry Smith Level: beginner
949dc4c0fb0SBarry Smith
95011ca99fdSLois Curfman McInnes Notes:
951ec5066bdSBarry Smith To see all options, run your program with the -help option or consult the users manual
952ec5066bdSBarry Smith
953420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
954420bcc1bSBarry Smith and computing explicitly with
955f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
95683e2fdc7SBarry Smith
957420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9589b94acceSBarry Smith @*/
SNESSetFromOptions(SNES snes)959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
960d71ae5a4SJacob Faibussowitsch {
9618afaa268SBarry Smith PetscBool flg, pcset, persist, set;
96277e5a1f9SBarry Smith PetscInt i, indx, lag, grids, max_its, max_funcs;
96304d7464bSBarry Smith const char *deft = SNESNEWTONLS;
964649ef022SMatthew Knepley const char *convtests[] = {"default", "skip", "correct_pressure"};
96585385478SLisandro Dalcin SNESKSPEW *kctx = NULL;
9660f0abf79SStefano Zampini char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
967c40d0f55SPeter Brune PCSide pcside;
968a64e098fSPeter Brune const char *optionsprefix;
96977e5a1f9SBarry Smith PetscReal rtol, abstol, stol;
9709b94acceSBarry Smith
9713a40ed3dSBarry Smith PetscFunctionBegin;
9720700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9739566063dSJacob Faibussowitsch PetscCall(SNESRegisterAll());
974d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes);
975639ff905SBarry Smith if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9769566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
977d64ed03dSBarry Smith if (flg) {
9789566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, type));
9797adad957SLisandro Dalcin } else if (!((PetscObject)snes)->type_name) {
9809566063dSJacob Faibussowitsch PetscCall(SNESSetType(snes, deft));
981d64ed03dSBarry Smith }
982186905e3SBarry Smith
98377e5a1f9SBarry Smith abstol = snes->abstol;
98477e5a1f9SBarry Smith rtol = snes->rtol;
98577e5a1f9SBarry Smith stol = snes->stol;
98677e5a1f9SBarry Smith max_its = snes->max_its;
98777e5a1f9SBarry Smith max_funcs = snes->max_funcs;
98877e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
98977e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
99077e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
99177e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
99277e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
99377e5a1f9SBarry Smith PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
99477e5a1f9SBarry Smith
99577e5a1f9SBarry Smith PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
99677e5a1f9SBarry Smith if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
99777e5a1f9SBarry Smith
99877e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
99977e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
100077e5a1f9SBarry Smith
100177e5a1f9SBarry Smith PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
100277e5a1f9SBarry Smith if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
100377e5a1f9SBarry Smith
10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
100785385478SLisandro Dalcin
10089566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1009a8054027SBarry Smith if (flg) {
10105f80ce2aSJacob 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");
10119566063dSJacob Faibussowitsch PetscCall(SNESSetLagPreconditioner(snes, lag));
1012a8054027SBarry Smith }
10139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10141baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10159566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1016e35cf81dSBarry Smith if (flg) {
10175f80ce2aSJacob 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");
10189566063dSJacob Faibussowitsch PetscCall(SNESSetLagJacobian(snes, lag));
1019e35cf81dSBarry Smith }
10209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10211baa6e33SBarry Smith if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
102237ec4e1aSPeter Brune
10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10241baa6e33SBarry Smith if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1025a8054027SBarry Smith
1026400f6f02SBarry Smith PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
102785385478SLisandro Dalcin if (flg) {
102885385478SLisandro Dalcin switch (indx) {
1029d71ae5a4SJacob Faibussowitsch case 0:
1030d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1031d71ae5a4SJacob Faibussowitsch break;
1032d71ae5a4SJacob Faibussowitsch case 1:
1033d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1034d71ae5a4SJacob Faibussowitsch break;
1035d71ae5a4SJacob Faibussowitsch case 2:
1036d71ae5a4SJacob Faibussowitsch PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1037d71ae5a4SJacob Faibussowitsch break;
103885385478SLisandro Dalcin }
103985385478SLisandro Dalcin }
104085385478SLisandro Dalcin
10419566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10429566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1043fdacfa88SPeter Brune
10449566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10459566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1046186905e3SBarry Smith
104785385478SLisandro Dalcin kctx = (SNESKSPEW *)snes->kspconvctx;
104885385478SLisandro Dalcin
10499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1050186905e3SBarry Smith
10510f0abf79SStefano Zampini PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10520f0abf79SStefano Zampini PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1053a4598233SStefano Zampini PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1054186905e3SBarry Smith
105590d69ab7SBarry Smith flg = PETSC_FALSE;
10569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10579566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESMonitorCancel(snes));
1058eabae89aSBarry Smith
10599566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10609566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10619566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1062eabae89aSBarry Smith
10639566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10649566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10659566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10669566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10679566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10689566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10699566063dSJacob Faibussowitsch PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10712db13446SMatthew G. Knepley
10729566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10739566063dSJacob Faibussowitsch if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10745180491cSLisandro Dalcin
107590d69ab7SBarry Smith flg = PETSC_FALSE;
10769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1077459f5d12SBarry Smith if (flg) {
1078459f5d12SBarry Smith PetscViewer ctx;
1079e24b481bSBarry Smith
10809566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
108149abdd8aSBarry Smith PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1082459f5d12SBarry Smith }
10832e7541e6SPeter Brune
1084648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1085648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
108690d69ab7SBarry Smith flg = PETSC_FALSE;
10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10889566063dSJacob Faibussowitsch if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1089c4421ceaSFande Kong
1090c4421ceaSFande Kong flg = PETSC_FALSE;
10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10924b27c08aSLois Curfman McInnes if (flg) {
10936cab3a1bSJed Brown void *functx;
1094b1f624c7SBarry Smith DM dm;
10959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
1096800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10979566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10989566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10999566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11009b94acceSBarry Smith }
1101639f9d9dSBarry Smith
110244848bc4SPeter Brune flg = PETSC_FALSE;
11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11041baa6e33SBarry Smith if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
110597584545SPeter Brune
110697584545SPeter Brune flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
110844848bc4SPeter Brune if (flg) {
1109c52e227fSPeter Brune DM dm;
11109566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
1111800f99ffSJeremy L Thompson PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11129566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11139566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
111444848bc4SPeter Brune }
111544848bc4SPeter Brune
1116aa3661deSLisandro Dalcin flg = PETSC_FALSE;
11177addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1118d8f46077SPeter Brune if (flg && snes->mf_operator) {
1119a8248277SBarry Smith snes->mf_operator = PETSC_TRUE;
1120d8f46077SPeter Brune snes->mf = PETSC_TRUE;
1121a8248277SBarry Smith }
1122aa3661deSLisandro Dalcin flg = PETSC_FALSE;
11237addb90fSBarry Smith PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1124d8f46077SPeter Brune if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1126d28543b3SPeter Brune
11271dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc));
11281dfd7622SMatthew Knepley PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac));
11291dfd7622SMatthew Knepley
1130c40d0f55SPeter Brune flg = PETSC_FALSE;
11319566063dSJacob Faibussowitsch PetscCall(SNESGetNPCSide(snes, &pcside));
11329566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11339566063dSJacob Faibussowitsch if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1134c40d0f55SPeter Brune
1135e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11368a70d858SHong Zhang /*
11378a70d858SHong Zhang Publish convergence information using SAWs
11388a70d858SHong Zhang */
11398a70d858SHong Zhang flg = PETSC_FALSE;
11409566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11418a70d858SHong Zhang if (flg) {
11422a8381b2SBarry Smith PetscCtx ctx;
11439566063dSJacob Faibussowitsch PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11449566063dSJacob Faibussowitsch PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11458a70d858SHong Zhang }
11468a70d858SHong Zhang #endif
11478a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1148b90c6cbeSBarry Smith {
1149b90c6cbeSBarry Smith PetscBool set;
1150b90c6cbeSBarry Smith flg = PETSC_FALSE;
11519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11521baa6e33SBarry Smith if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1153b90c6cbeSBarry Smith }
1154b90c6cbeSBarry Smith #endif
1155b90c6cbeSBarry Smith
115648a46eb9SPierre Jolivet for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
115776b2cf59SMatthew Knepley
1158dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11595d973c19SBarry Smith
11605d973c19SBarry Smith /* process any options handlers added with PetscObjectAddOptionsHandler() */
1161dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1162d0609cedSBarry Smith PetscOptionsEnd();
11634bbc92c1SBarry Smith
1164d8d34be6SBarry Smith if (snes->linesearch) {
11659566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11669566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1167d8d34be6SBarry Smith }
11689e764e56SPeter Brune
11696aa5e7e9SBarry Smith if (snes->usesksp) {
11709566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11719566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11729566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(snes->ksp));
11736aa5e7e9SBarry Smith }
11746991f827SBarry Smith
1175b5badacbSBarry Smith /* if user has set the SNES NPC type via options database, create it. */
11769566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11779566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
117848a46eb9SPierre Jolivet if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11791baa6e33SBarry Smith if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1180b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled++;
11813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1182b3cd9a81SMatthew G. Knepley }
1183b3cd9a81SMatthew G. Knepley
1184b3cd9a81SMatthew G. Knepley /*@
1185420bcc1bSBarry Smith SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1186b3cd9a81SMatthew G. Knepley
1187c3339decSBarry Smith Collective
1188b3cd9a81SMatthew G. Knepley
1189b3cd9a81SMatthew G. Knepley Input Parameter:
1190f6dfbefdSBarry Smith . snes - the `SNES` context
1191b3cd9a81SMatthew G. Knepley
1192420bcc1bSBarry Smith Level: advanced
1193b3cd9a81SMatthew G. Knepley
11941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1195b3cd9a81SMatthew G. Knepley @*/
SNESResetFromOptions(SNES snes)1196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1197d71ae5a4SJacob Faibussowitsch {
1198b3cd9a81SMatthew G. Knepley PetscFunctionBegin;
11999566063dSJacob Faibussowitsch if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12019b94acceSBarry Smith }
12029b94acceSBarry Smith
1203bb9467b5SJed Brown /*@C
1204d25893d9SBarry Smith SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1205d25893d9SBarry Smith the nonlinear solvers.
1206d25893d9SBarry Smith
1207dc4c0fb0SBarry Smith Logically Collective; No Fortran Support
1208d25893d9SBarry Smith
1209d25893d9SBarry Smith Input Parameters:
1210f6dfbefdSBarry Smith + snes - the `SNES` context
1211d25893d9SBarry Smith . compute - function to compute the context
121249abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1213d25893d9SBarry Smith
1214420bcc1bSBarry Smith Calling sequence of `compute`:
1215420bcc1bSBarry Smith + snes - the `SNES` context
1216420bcc1bSBarry Smith - ctx - context to be computed
1217420bcc1bSBarry Smith
1218d25893d9SBarry Smith Level: intermediate
1219d25893d9SBarry Smith
1220f6dfbefdSBarry Smith Note:
1221f6dfbefdSBarry Smith This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1222f6dfbefdSBarry Smith
1223f6dfbefdSBarry Smith Use `SNESSetApplicationContext()` to see the context immediately
1224f6dfbefdSBarry Smith
122549abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1226d25893d9SBarry Smith @*/
SNESSetComputeApplicationContext(SNES snes,PetscErrorCode (* compute)(SNES snes,PetscCtxRt ctx),PetscCtxDestroyFn * destroy)12272a8381b2SBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, PetscCtxRt ctx), PetscCtxDestroyFn *destroy)
1228d71ae5a4SJacob Faibussowitsch {
1229d25893d9SBarry Smith PetscFunctionBegin;
1230d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12312a8381b2SBarry Smith snes->ops->ctxcompute = compute;
123249abdd8aSBarry Smith snes->ops->ctxdestroy = destroy;
12333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1234d25893d9SBarry Smith }
1235a847f771SSatish Balay
1236b07ff414SBarry Smith /*@
1237f6dfbefdSBarry Smith SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12389b94acceSBarry Smith
1239c3339decSBarry Smith Logically Collective
1240fee21e36SBarry Smith
1241c7afd0dbSLois Curfman McInnes Input Parameters:
1242f6dfbefdSBarry Smith + snes - the `SNES` context
1243ce78bad3SBarry Smith - ctx - the user context
1244c7afd0dbSLois Curfman McInnes
124536851e7fSLois Curfman McInnes Level: intermediate
124636851e7fSLois Curfman McInnes
1247f6dfbefdSBarry Smith Notes:
1248ce78bad3SBarry Smith Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1249f6dfbefdSBarry Smith with `SNESGetApplicationContext()`
1250f6dfbefdSBarry Smith
1251f6dfbefdSBarry Smith To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1252f6dfbefdSBarry Smith
1253420bcc1bSBarry Smith Fortran Note:
1254ce78bad3SBarry Smith This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
1255ce78bad3SBarry Smith function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1256ce78bad3SBarry Smith an example.
1257daf670e6SBarry Smith
12581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12599b94acceSBarry Smith @*/
SNESSetApplicationContext(SNES snes,PetscCtx ctx)12602a8381b2SBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, PetscCtx ctx)
1261d71ae5a4SJacob Faibussowitsch {
1262b07ff414SBarry Smith KSP ksp;
12631b2093e4SBarry Smith
12643a40ed3dSBarry Smith PetscFunctionBegin;
12650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12669566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
126749abdd8aSBarry Smith PetscCall(KSPSetApplicationContext(ksp, ctx));
126849abdd8aSBarry Smith snes->ctx = ctx;
12693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12709b94acceSBarry Smith }
127174679c65SBarry Smith
1272b07ff414SBarry Smith /*@
12739b94acceSBarry Smith SNESGetApplicationContext - Gets the user-defined context for the
1274420bcc1bSBarry Smith nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12759b94acceSBarry Smith
1276c7afd0dbSLois Curfman McInnes Not Collective
1277c7afd0dbSLois Curfman McInnes
12789b94acceSBarry Smith Input Parameter:
1279f6dfbefdSBarry Smith . snes - `SNES` context
12809b94acceSBarry Smith
12819b94acceSBarry Smith Output Parameter:
12822a8381b2SBarry Smith . ctx - the application context
12839b94acceSBarry Smith
128436851e7fSLois Curfman McInnes Level: intermediate
128536851e7fSLois Curfman McInnes
1286ce78bad3SBarry Smith Fortran Notes:
12872a8381b2SBarry Smith This only works when the context is a Fortran derived type or a `PetscObject`. Declare `ctx` with
1288ce78bad3SBarry Smith .vb
1289ce78bad3SBarry Smith type(tUsertype), pointer :: ctx
1290ce78bad3SBarry Smith .ve
1291dc4c0fb0SBarry Smith
1292420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
12939b94acceSBarry Smith @*/
SNESGetApplicationContext(SNES snes,PetscCtxRt ctx)12942a8381b2SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PetscCtxRt ctx)
1295d71ae5a4SJacob Faibussowitsch {
12963a40ed3dSBarry Smith PetscFunctionBegin;
12970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
129849abdd8aSBarry Smith *(void **)ctx = snes->ctx;
12993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13009b94acceSBarry Smith }
130174679c65SBarry Smith
13029b94acceSBarry Smith /*@
1303420bcc1bSBarry Smith SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13043565c898SBarry Smith
1305dc4c0fb0SBarry Smith Logically Collective
13063565c898SBarry Smith
13073565c898SBarry Smith Input Parameters:
1308f6dfbefdSBarry Smith + snes - `SNES` context
1309f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1310f6dfbefdSBarry 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
1311420bcc1bSBarry Smith this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13123565c898SBarry Smith
1313f6dfbefdSBarry Smith Options Database Keys:
131401c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1315f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator
1316ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences.
1317ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow)
13183565c898SBarry Smith
13193565c898SBarry Smith Level: intermediate
13203565c898SBarry Smith
1321f6dfbefdSBarry Smith Note:
1322420bcc1bSBarry Smith `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1323420bcc1bSBarry Smith and computing explicitly with
1324f6dfbefdSBarry Smith finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1325ec5066bdSBarry Smith
1326420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13273565c898SBarry Smith @*/
SNESSetUseMatrixFree(SNES snes,PetscBool mf_operator,PetscBool mf)1328d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1329d71ae5a4SJacob Faibussowitsch {
13303565c898SBarry Smith PetscFunctionBegin;
13313565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
133288b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
133388b4c220SStefano Zampini PetscValidLogicalCollectiveBool(snes, mf, 3);
13344ddffce6SLisandro Dalcin snes->mf = mf_operator ? PETSC_TRUE : mf;
13353565c898SBarry Smith snes->mf_operator = mf_operator;
13363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13373565c898SBarry Smith }
13383565c898SBarry Smith
13393565c898SBarry Smith /*@
1340dc4c0fb0SBarry Smith SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13413565c898SBarry Smith
1342420bcc1bSBarry Smith Not Collective, but the resulting flags will be the same on all MPI processes
13433565c898SBarry Smith
13443565c898SBarry Smith Input Parameter:
1345f6dfbefdSBarry Smith . snes - `SNES` context
13463565c898SBarry Smith
13473565c898SBarry Smith Output Parameters:
1348f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1349f6dfbefdSBarry 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
13503565c898SBarry Smith
13513565c898SBarry Smith Level: intermediate
13523565c898SBarry Smith
13531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13543565c898SBarry Smith @*/
SNESGetUseMatrixFree(SNES snes,PetscBool * mf_operator,PetscBool * mf)1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1356d71ae5a4SJacob Faibussowitsch {
13573565c898SBarry Smith PetscFunctionBegin;
13583565c898SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13593565c898SBarry Smith if (mf) *mf = snes->mf;
13603565c898SBarry Smith if (mf_operator) *mf_operator = snes->mf_operator;
13613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13623565c898SBarry Smith }
13633565c898SBarry Smith
13643565c898SBarry Smith /*@
1365420bcc1bSBarry Smith SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13669b94acceSBarry Smith
1367c7afd0dbSLois Curfman McInnes Not Collective
1368c7afd0dbSLois Curfman McInnes
13699b94acceSBarry Smith Input Parameter:
1370f6dfbefdSBarry Smith . snes - `SNES` context
13719b94acceSBarry Smith
13729b94acceSBarry Smith Output Parameter:
13739b94acceSBarry Smith . iter - iteration number
13749b94acceSBarry Smith
1375dc4c0fb0SBarry Smith Level: intermediate
1376dc4c0fb0SBarry Smith
1377c8228a4eSBarry Smith Notes:
1378c8228a4eSBarry Smith For example, during the computation of iteration 2 this would return 1.
1379c8228a4eSBarry Smith
1380c8228a4eSBarry Smith This is useful for using lagged Jacobians (where one does not recompute the
1381f6dfbefdSBarry Smith Jacobian at each `SNES` iteration). For example, the code
138208405cd6SLois Curfman McInnes .vb
138308405cd6SLois Curfman McInnes ierr = SNESGetIterationNumber(snes,&it);
138408405cd6SLois Curfman McInnes if (!(it % 2)) {
138508405cd6SLois Curfman McInnes [compute Jacobian here]
138608405cd6SLois Curfman McInnes }
138708405cd6SLois Curfman McInnes .ve
1388f6dfbefdSBarry Smith can be used in your function that computes the Jacobian to cause the Jacobian to be
1389f6dfbefdSBarry Smith recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1390c8228a4eSBarry Smith
1391f6dfbefdSBarry Smith After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1392c04deec6SBarry Smith
1393420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
13949b94acceSBarry Smith @*/
SNESGetIterationNumber(SNES snes,PetscInt * iter)1395d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1396d71ae5a4SJacob Faibussowitsch {
13973a40ed3dSBarry Smith PetscFunctionBegin;
13980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13994f572ea9SToby Isaac PetscAssertPointer(iter, 2);
14009b94acceSBarry Smith *iter = snes->iter;
14013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14029b94acceSBarry Smith }
140374679c65SBarry Smith
1404360c497dSPeter Brune /*@
1405360c497dSPeter Brune SNESSetIterationNumber - Sets the current iteration number.
1406360c497dSPeter Brune
1407360c497dSPeter Brune Not Collective
1408360c497dSPeter Brune
1409d8d19677SJose E. Roman Input Parameters:
1410f6dfbefdSBarry Smith + snes - `SNES` context
1411a2b725a8SWilliam Gropp - iter - iteration number
1412360c497dSPeter Brune
1413360c497dSPeter Brune Level: developer
1414360c497dSPeter Brune
1415420bcc1bSBarry Smith Note:
1416420bcc1bSBarry Smith This should only be called inside a `SNES` nonlinear solver.
1417420bcc1bSBarry Smith
14181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1419360c497dSPeter Brune @*/
SNESSetIterationNumber(SNES snes,PetscInt iter)1420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1421d71ae5a4SJacob Faibussowitsch {
1422360c497dSPeter Brune PetscFunctionBegin;
1423360c497dSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14249566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1425360c497dSPeter Brune snes->iter = iter;
14269566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1428360c497dSPeter Brune }
1429360c497dSPeter Brune
14309b94acceSBarry Smith /*@
1431b850b91aSLisandro Dalcin SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
143276c63389SBarry Smith taken by the nonlinear solver in the current or most recent `SNESSolve()` .
14339b94acceSBarry Smith
1434c7afd0dbSLois Curfman McInnes Not Collective
1435c7afd0dbSLois Curfman McInnes
14369b94acceSBarry Smith Input Parameter:
1437f6dfbefdSBarry Smith . snes - `SNES` context
14389b94acceSBarry Smith
14399b94acceSBarry Smith Output Parameter:
14409b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14419b94acceSBarry Smith
1442dc4c0fb0SBarry Smith Level: intermediate
1443dc4c0fb0SBarry Smith
144476c63389SBarry Smith Notes:
144576c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested step criteria. For example,
144676c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase).
144776c63389SBarry Smith
144876c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()`
144976c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`.
145076c63389SBarry Smith
145176c63389SBarry Smith `SNESSetMaxNonlinearStepFailures()` determines how many unsuccessful steps are allowed before the `SNESSolve()` terminates
145276c63389SBarry Smith
1453f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`.
1454c96a6f78SLois Curfman McInnes
14551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1456db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14579b94acceSBarry Smith @*/
SNESGetNonlinearStepFailures(SNES snes,PetscInt * nfails)1458d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1459d71ae5a4SJacob Faibussowitsch {
14603a40ed3dSBarry Smith PetscFunctionBegin;
14610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14624f572ea9SToby Isaac PetscAssertPointer(nfails, 2);
146350ffb88aSMatthew Knepley *nfails = snes->numFailures;
14643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
146550ffb88aSMatthew Knepley }
146650ffb88aSMatthew Knepley
146750ffb88aSMatthew Knepley /*@
1468b850b91aSLisandro Dalcin SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1469420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
147050ffb88aSMatthew Knepley
147150ffb88aSMatthew Knepley Not Collective
147250ffb88aSMatthew Knepley
147350ffb88aSMatthew Knepley Input Parameters:
1474f6dfbefdSBarry Smith + snes - `SNES` context
147577e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
147650ffb88aSMatthew Knepley
1477420bcc1bSBarry Smith Options Database Key:
1478420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1479420bcc1bSBarry Smith
148050ffb88aSMatthew Knepley Level: intermediate
148150ffb88aSMatthew Knepley
148276c63389SBarry Smith Note:
148376c63389SBarry Smith A failed step is a step that was generated and taken but did not satisfy the requested criteria. For example,
148476c63389SBarry Smith the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase).
148576c63389SBarry Smith
148676c63389SBarry Smith Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()`
148776c63389SBarry Smith will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`.
148876c63389SBarry Smith
1489420bcc1bSBarry Smith Developer Note:
1490420bcc1bSBarry Smith The options database key is wrong for this function name
1491420bcc1bSBarry Smith
149276c63389SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
149376c63389SBarry Smith `SNESGetLinearSolveFailures()`, `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`, `SNESCheckLineSearchFailure()`
149450ffb88aSMatthew Knepley @*/
SNESSetMaxNonlinearStepFailures(SNES snes,PetscInt maxFails)1495d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1496d71ae5a4SJacob Faibussowitsch {
149750ffb88aSMatthew Knepley PetscFunctionBegin;
14980700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
149977e5a1f9SBarry Smith
150077e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) {
15011690c2aeSBarry Smith snes->maxFailures = PETSC_INT_MAX;
150277e5a1f9SBarry Smith } else {
150377e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
150450ffb88aSMatthew Knepley snes->maxFailures = maxFails;
150577e5a1f9SBarry Smith }
15063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
150750ffb88aSMatthew Knepley }
150850ffb88aSMatthew Knepley
150950ffb88aSMatthew Knepley /*@
1510b850b91aSLisandro Dalcin SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1511420bcc1bSBarry Smith attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
151250ffb88aSMatthew Knepley
151350ffb88aSMatthew Knepley Not Collective
151450ffb88aSMatthew Knepley
151550ffb88aSMatthew Knepley Input Parameter:
151620f4b53cSBarry Smith . snes - `SNES` context
151750ffb88aSMatthew Knepley
151850ffb88aSMatthew Knepley Output Parameter:
151950ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
152050ffb88aSMatthew Knepley
152150ffb88aSMatthew Knepley Level: intermediate
152250ffb88aSMatthew Knepley
15231cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1524db781477SPatrick Sanan `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
152550ffb88aSMatthew Knepley @*/
SNESGetMaxNonlinearStepFailures(SNES snes,PetscInt * maxFails)1526d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1527d71ae5a4SJacob Faibussowitsch {
152850ffb88aSMatthew Knepley PetscFunctionBegin;
15290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15304f572ea9SToby Isaac PetscAssertPointer(maxFails, 2);
153150ffb88aSMatthew Knepley *maxFails = snes->maxFailures;
15323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15339b94acceSBarry Smith }
1534a847f771SSatish Balay
15352541af92SBarry Smith /*@
15362541af92SBarry Smith SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1537420bcc1bSBarry Smith done by the `SNES` object in the current or most recent `SNESSolve()`
15382541af92SBarry Smith
15392541af92SBarry Smith Not Collective
15402541af92SBarry Smith
15412541af92SBarry Smith Input Parameter:
1542f6dfbefdSBarry Smith . snes - `SNES` context
15432541af92SBarry Smith
15442541af92SBarry Smith Output Parameter:
15452541af92SBarry Smith . nfuncs - number of evaluations
15462541af92SBarry Smith
15472541af92SBarry Smith Level: intermediate
15482541af92SBarry Smith
1549f6dfbefdSBarry Smith Note:
1550f6dfbefdSBarry Smith Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1551971e163fSPeter Brune
15521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15532541af92SBarry Smith @*/
SNESGetNumberFunctionEvals(SNES snes,PetscInt * nfuncs)1554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1555d71ae5a4SJacob Faibussowitsch {
15562541af92SBarry Smith PetscFunctionBegin;
15570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15584f572ea9SToby Isaac PetscAssertPointer(nfuncs, 2);
15592541af92SBarry Smith *nfuncs = snes->nfuncs;
15603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15612541af92SBarry Smith }
15622541af92SBarry Smith
15633d4c4710SBarry Smith /*@
15643d4c4710SBarry Smith SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1565420bcc1bSBarry Smith linear solvers in the current or most recent `SNESSolve()`
15663d4c4710SBarry Smith
15673d4c4710SBarry Smith Not Collective
15683d4c4710SBarry Smith
15693d4c4710SBarry Smith Input Parameter:
1570f6dfbefdSBarry Smith . snes - `SNES` context
15713d4c4710SBarry Smith
15723d4c4710SBarry Smith Output Parameter:
15733d4c4710SBarry Smith . nfails - number of failed solves
15743d4c4710SBarry Smith
1575f6dfbefdSBarry Smith Options Database Key:
15769d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15779d85da0cSMatthew G. Knepley
1578f6dfbefdSBarry Smith Level: intermediate
1579f6dfbefdSBarry Smith
1580f6dfbefdSBarry Smith Note:
1581f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()`.
15823d4c4710SBarry Smith
15831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15843d4c4710SBarry Smith @*/
SNESGetLinearSolveFailures(SNES snes,PetscInt * nfails)1585d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1586d71ae5a4SJacob Faibussowitsch {
15873d4c4710SBarry Smith PetscFunctionBegin;
15880700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15894f572ea9SToby Isaac PetscAssertPointer(nfails, 2);
15903d4c4710SBarry Smith *nfails = snes->numLinearSolveFailures;
15913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15923d4c4710SBarry Smith }
15933d4c4710SBarry Smith
15943d4c4710SBarry Smith /*@
15953d4c4710SBarry Smith SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1596f6dfbefdSBarry Smith allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15973d4c4710SBarry Smith
1598c3339decSBarry Smith Logically Collective
15993d4c4710SBarry Smith
16003d4c4710SBarry Smith Input Parameters:
1601f6dfbefdSBarry Smith + snes - `SNES` context
160277e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16033d4c4710SBarry Smith
1604f6dfbefdSBarry Smith Options Database Key:
16059d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16069d85da0cSMatthew G. Knepley
1607dc4c0fb0SBarry Smith Level: intermediate
1608dc4c0fb0SBarry Smith
1609f6dfbefdSBarry Smith Note:
1610f6dfbefdSBarry Smith By default this is 0; that is `SNES` returns on the first failed linear solve
16113d4c4710SBarry Smith
1612420bcc1bSBarry Smith Developer Note:
1613420bcc1bSBarry Smith The options database key is wrong for this function name
1614420bcc1bSBarry Smith
16151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16163d4c4710SBarry Smith @*/
SNESSetMaxLinearSolveFailures(SNES snes,PetscInt maxFails)1617d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1618d71ae5a4SJacob Faibussowitsch {
16193d4c4710SBarry Smith PetscFunctionBegin;
16200700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1621c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxFails, 2);
162277e5a1f9SBarry Smith
162377e5a1f9SBarry Smith if (maxFails == PETSC_UNLIMITED) {
16241690c2aeSBarry Smith snes->maxLinearSolveFailures = PETSC_INT_MAX;
162577e5a1f9SBarry Smith } else {
162677e5a1f9SBarry Smith PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16273d4c4710SBarry Smith snes->maxLinearSolveFailures = maxFails;
162877e5a1f9SBarry Smith }
16293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16303d4c4710SBarry Smith }
16313d4c4710SBarry Smith
16323d4c4710SBarry Smith /*@
16333d4c4710SBarry Smith SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1634f6dfbefdSBarry Smith are allowed before `SNES` returns as unsuccessful
16353d4c4710SBarry Smith
16363d4c4710SBarry Smith Not Collective
16373d4c4710SBarry Smith
16383d4c4710SBarry Smith Input Parameter:
1639f6dfbefdSBarry Smith . snes - `SNES` context
16403d4c4710SBarry Smith
16413d4c4710SBarry Smith Output Parameter:
16423d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16433d4c4710SBarry Smith
16443d4c4710SBarry Smith Level: intermediate
16453d4c4710SBarry Smith
1646f6dfbefdSBarry Smith Note:
1647f6dfbefdSBarry Smith By default this is 1; that is `SNES` returns on the first failed linear solve
16483d4c4710SBarry Smith
16491cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16503d4c4710SBarry Smith @*/
SNESGetMaxLinearSolveFailures(SNES snes,PetscInt * maxFails)1651d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1652d71ae5a4SJacob Faibussowitsch {
16533d4c4710SBarry Smith PetscFunctionBegin;
16540700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16554f572ea9SToby Isaac PetscAssertPointer(maxFails, 2);
16563d4c4710SBarry Smith *maxFails = snes->maxLinearSolveFailures;
16573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16583d4c4710SBarry Smith }
16593d4c4710SBarry Smith
1660c96a6f78SLois Curfman McInnes /*@
1661b850b91aSLisandro Dalcin SNESGetLinearSolveIterations - Gets the total number of linear iterations
1662420bcc1bSBarry Smith used by the nonlinear solver in the most recent `SNESSolve()`
1663c96a6f78SLois Curfman McInnes
1664c7afd0dbSLois Curfman McInnes Not Collective
1665c7afd0dbSLois Curfman McInnes
1666c96a6f78SLois Curfman McInnes Input Parameter:
1667f6dfbefdSBarry Smith . snes - `SNES` context
1668c96a6f78SLois Curfman McInnes
1669c96a6f78SLois Curfman McInnes Output Parameter:
1670c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1671c96a6f78SLois Curfman McInnes
1672dc4c0fb0SBarry Smith Level: intermediate
1673dc4c0fb0SBarry Smith
1674c96a6f78SLois Curfman McInnes Notes:
1675f6dfbefdSBarry Smith This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1676c96a6f78SLois Curfman McInnes
1677f6dfbefdSBarry 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
1678f6dfbefdSBarry Smith then call `KSPGetIterationNumber()` after the failed solve.
1679010be392SBarry Smith
16801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1681c96a6f78SLois Curfman McInnes @*/
SNESGetLinearSolveIterations(SNES snes,PetscInt * lits)1682d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1683d71ae5a4SJacob Faibussowitsch {
16843a40ed3dSBarry Smith PetscFunctionBegin;
16850700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16864f572ea9SToby Isaac PetscAssertPointer(lits, 2);
1687c96a6f78SLois Curfman McInnes *lits = snes->linear_its;
16883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1689c96a6f78SLois Curfman McInnes }
1690c96a6f78SLois Curfman McInnes
1691971e163fSPeter Brune /*@
1692971e163fSPeter Brune SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1693f6dfbefdSBarry Smith are reset every time `SNESSolve()` is called.
1694971e163fSPeter Brune
1695c3339decSBarry Smith Logically Collective
1696971e163fSPeter Brune
1697d8d19677SJose E. Roman Input Parameters:
1698f6dfbefdSBarry Smith + snes - `SNES` context
1699f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1700971e163fSPeter Brune
1701971e163fSPeter Brune Level: developer
1702971e163fSPeter Brune
17031cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1704971e163fSPeter Brune @*/
SNESSetCountersReset(SNES snes,PetscBool reset)1705d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1706d71ae5a4SJacob Faibussowitsch {
1707971e163fSPeter Brune PetscFunctionBegin;
1708971e163fSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1709971e163fSPeter Brune PetscValidLogicalCollectiveBool(snes, reset, 2);
1710971e163fSPeter Brune snes->counters_reset = reset;
17113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1712971e163fSPeter Brune }
1713971e163fSPeter Brune
17142999313aSBarry Smith /*@
171512b1dd1aSStefano Zampini SNESResetCounters - Reset counters for linear iterations and function evaluations.
171612b1dd1aSStefano Zampini
171712b1dd1aSStefano Zampini Logically Collective
171812b1dd1aSStefano Zampini
171912b1dd1aSStefano Zampini Input Parameters:
172012b1dd1aSStefano Zampini . snes - `SNES` context
172112b1dd1aSStefano Zampini
172212b1dd1aSStefano Zampini Level: developer
172312b1dd1aSStefano Zampini
172412b1dd1aSStefano Zampini Note:
172512b1dd1aSStefano Zampini It honors the flag set with `SNESSetCountersReset()`
172612b1dd1aSStefano Zampini
172712b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
172812b1dd1aSStefano Zampini @*/
SNESResetCounters(SNES snes)172912b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
173012b1dd1aSStefano Zampini {
173112b1dd1aSStefano Zampini PetscFunctionBegin;
173212b1dd1aSStefano Zampini PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
173312b1dd1aSStefano Zampini if (snes->counters_reset) {
173412b1dd1aSStefano Zampini snes->nfuncs = 0;
173512b1dd1aSStefano Zampini snes->linear_its = 0;
173612b1dd1aSStefano Zampini snes->numFailures = 0;
173712b1dd1aSStefano Zampini }
173812b1dd1aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
173912b1dd1aSStefano Zampini }
174012b1dd1aSStefano Zampini
174112b1dd1aSStefano Zampini /*@
1742f6dfbefdSBarry Smith SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17432999313aSBarry Smith
1744420bcc1bSBarry Smith Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17452999313aSBarry Smith
17462999313aSBarry Smith Input Parameters:
1747f6dfbefdSBarry Smith + snes - the `SNES` context
1748f6dfbefdSBarry Smith - ksp - the `KSP` context
17492999313aSBarry Smith
1750dc4c0fb0SBarry Smith Level: developer
1751dc4c0fb0SBarry Smith
17522999313aSBarry Smith Notes:
1753f6dfbefdSBarry Smith The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17542999313aSBarry Smith so this routine is rarely needed.
17552999313aSBarry Smith
1756f6dfbefdSBarry Smith The `KSP` object that is already in the `SNES` object has its reference count
1757420bcc1bSBarry Smith decreased by one when this is called.
17582999313aSBarry Smith
175942747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17602999313aSBarry Smith @*/
SNESSetKSP(SNES snes,KSP ksp)1761d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1762d71ae5a4SJacob Faibussowitsch {
17632999313aSBarry Smith PetscFunctionBegin;
17640700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17650700a824SBarry Smith PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17662999313aSBarry Smith PetscCheckSameComm(snes, 1, ksp, 2);
17679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ksp));
17689566063dSJacob Faibussowitsch if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17692999313aSBarry Smith snes->ksp = ksp;
17703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17712999313aSBarry Smith }
17722999313aSBarry Smith
177352baeb72SSatish Balay /*@
177477e5a1f9SBarry Smith SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
177577e5a1f9SBarry Smith currently contain default values
177677e5a1f9SBarry Smith
177777e5a1f9SBarry Smith Collective
177877e5a1f9SBarry Smith
177977e5a1f9SBarry Smith Input Parameter:
178077e5a1f9SBarry Smith . snes - the `SNES` object
178177e5a1f9SBarry Smith
178277e5a1f9SBarry Smith Level: developer
178377e5a1f9SBarry Smith
178477e5a1f9SBarry Smith Developer Note:
178577e5a1f9SBarry Smith This is called by all the `SNESCreate_XXX()` routines.
178677e5a1f9SBarry Smith
178777e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
178877e5a1f9SBarry Smith `PetscObjectParameterSetDefault()`
178977e5a1f9SBarry Smith @*/
SNESParametersInitialize(SNES snes)179077e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
179177e5a1f9SBarry Smith {
179277e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_its, 50);
179377e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, max_funcs, 10000);
179477e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179577e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
179677e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179777e5a1f9SBarry Smith PetscObjectParameterSetDefault(snes, divtol, 1.e4);
179877e5a1f9SBarry Smith return PETSC_SUCCESS;
179977e5a1f9SBarry Smith }
180077e5a1f9SBarry Smith
180177e5a1f9SBarry Smith /*@
1802dc4c0fb0SBarry Smith SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18039b94acceSBarry Smith
1804d083f849SBarry Smith Collective
1805c7afd0dbSLois Curfman McInnes
1806f6dfbefdSBarry Smith Input Parameter:
1807906ed7ccSBarry Smith . comm - MPI communicator
18089b94acceSBarry Smith
18099b94acceSBarry Smith Output Parameter:
181020f4b53cSBarry Smith . outsnes - the new `SNES` context
18119b94acceSBarry Smith
1812c7afd0dbSLois Curfman McInnes Options Database Keys:
18137addb90fSBarry Smith + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18147addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1815dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1816c7afd0dbSLois Curfman McInnes - -snes_fd - Uses (slow!) finite differences to compute Jacobian
1817c1f60f51SBarry Smith
181836851e7fSLois Curfman McInnes Level: beginner
181936851e7fSLois Curfman McInnes
182095452b02SPatrick Sanan Developer Notes:
1821f6dfbefdSBarry Smith `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1822efd4aadfSBarry Smith unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1823f6dfbefdSBarry Smith particular method does use `KSP` and regulates if the information about the `KSP` is printed
1824f6dfbefdSBarry Smith in `SNESView()`.
1825efd4aadfSBarry Smith
1826f6dfbefdSBarry Smith `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1827f6dfbefdSBarry Smith by help messages about meaningless `SNES` options.
1828f6dfbefdSBarry Smith
18297addb90fSBarry Smith `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1830efd4aadfSBarry Smith
1831e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18329b94acceSBarry Smith @*/
SNESCreate(MPI_Comm comm,SNES * outsnes)1833d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1834d71ae5a4SJacob Faibussowitsch {
18359b94acceSBarry Smith SNES snes;
1836fa9f3622SBarry Smith SNESKSPEW *kctx;
183737fcc0dbSBarry Smith
18383a40ed3dSBarry Smith PetscFunctionBegin;
18394f572ea9SToby Isaac PetscAssertPointer(outsnes, 2);
18409566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage());
18418ba1e511SMatthew Knepley
18429566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18438d359177SBarry Smith snes->ops->converged = SNESConvergedDefault;
18442c155ee1SBarry Smith snes->usesksp = PETSC_TRUE;
18459b94acceSBarry Smith snes->norm = 0.0;
1846c1e67a49SFande Kong snes->xnorm = 0.0;
1847c1e67a49SFande Kong snes->ynorm = 0.0;
1848365a6726SPeter Brune snes->normschedule = SNES_NORM_ALWAYS;
18496c67d002SPeter Brune snes->functype = SNES_FUNCTION_DEFAULT;
1850b4874afaSBarry Smith snes->ttol = 0.0;
185177e5a1f9SBarry Smith
1852e37c518bSBarry Smith snes->rnorm0 = 0;
18539b94acceSBarry Smith snes->nfuncs = 0;
185450ffb88aSMatthew Knepley snes->numFailures = 0;
185550ffb88aSMatthew Knepley snes->maxFailures = 1;
18567a00f4a9SLois Curfman McInnes snes->linear_its = 0;
1857e35cf81dSBarry Smith snes->lagjacobian = 1;
185837ec4e1aSPeter Brune snes->jac_iter = 0;
185937ec4e1aSPeter Brune snes->lagjac_persist = PETSC_FALSE;
1860a8054027SBarry Smith snes->lagpreconditioner = 1;
186137ec4e1aSPeter Brune snes->pre_iter = 0;
186237ec4e1aSPeter Brune snes->lagpre_persist = PETSC_FALSE;
1863639f9d9dSBarry Smith snes->numbermonitors = 0;
1864c4421ceaSFande Kong snes->numberreasonviews = 0;
18659e5d0892SLisandro Dalcin snes->data = NULL;
18664dc4c822SBarry Smith snes->setupcalled = PETSC_FALSE;
1867186905e3SBarry Smith snes->ksp_ewconv = PETSC_FALSE;
18686f24a144SLois Curfman McInnes snes->nwork = 0;
18699e5d0892SLisandro Dalcin snes->work = NULL;
187058c9b817SLisandro Dalcin snes->nvwork = 0;
18719e5d0892SLisandro Dalcin snes->vwork = NULL;
1872758f92a0SBarry Smith snes->conv_hist_len = 0;
1873758f92a0SBarry Smith snes->conv_hist_max = 0;
18740298fd71SBarry Smith snes->conv_hist = NULL;
18750298fd71SBarry Smith snes->conv_hist_its = NULL;
1876758f92a0SBarry Smith snes->conv_hist_reset = PETSC_TRUE;
1877971e163fSPeter Brune snes->counters_reset = PETSC_TRUE;
1878e4ed7901SPeter Brune snes->vec_func_init_set = PETSC_FALSE;
1879184914b5SBarry Smith snes->reason = SNES_CONVERGED_ITERATING;
1880efd4aadfSBarry Smith snes->npcside = PC_RIGHT;
1881b3cd9a81SMatthew G. Knepley snes->setfromoptionscalled = 0;
1882c40d0f55SPeter Brune
1883d8f46077SPeter Brune snes->mf = PETSC_FALSE;
1884d8f46077SPeter Brune snes->mf_operator = PETSC_FALSE;
1885d8f46077SPeter Brune snes->mf_version = 1;
1886d8f46077SPeter Brune
18873d4c4710SBarry Smith snes->numLinearSolveFailures = 0;
18883d4c4710SBarry Smith snes->maxLinearSolveFailures = 1;
18893d4c4710SBarry Smith
1890349187a7SBarry Smith snes->vizerotolerance = 1.e-8;
189176bd3646SJed Brown snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1892349187a7SBarry Smith
18934fc747eaSLawrence Mitchell /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18944fc747eaSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE;
18954fc747eaSLawrence Mitchell
18969b94acceSBarry Smith /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18974dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&kctx));
1898f5af7f23SKarl Rupp
1899835f2295SStefano Zampini snes->kspconvctx = kctx;
19009b94acceSBarry Smith kctx->version = 2;
19010f0abf79SStefano Zampini kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19029b94acceSBarry Smith this was too large for some test cases */
190375567043SBarry Smith kctx->rtol_last = 0.0;
19040f0abf79SStefano Zampini kctx->rtol_max = 0.9;
19059b94acceSBarry Smith kctx->gamma = 1.0;
19060f0abf79SStefano Zampini kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0));
190771f87433Sdalcinl kctx->alpha2 = kctx->alpha;
19080f0abf79SStefano Zampini kctx->threshold = 0.1;
190975567043SBarry Smith kctx->lresid_last = 0.0;
191075567043SBarry Smith kctx->norm_last = 0.0;
19119b94acceSBarry Smith
19120f0abf79SStefano Zampini kctx->rk_last = 0.0;
19130f0abf79SStefano Zampini kctx->rk_last_2 = 0.0;
19140f0abf79SStefano Zampini kctx->rtol_last_2 = 0.0;
19150f0abf79SStefano Zampini kctx->v4_p1 = 0.1;
19160f0abf79SStefano Zampini kctx->v4_p2 = 0.4;
19170f0abf79SStefano Zampini kctx->v4_p3 = 0.7;
19180f0abf79SStefano Zampini kctx->v4_m1 = 0.8;
19190f0abf79SStefano Zampini kctx->v4_m2 = 0.5;
19200f0abf79SStefano Zampini kctx->v4_m3 = 0.1;
19210f0abf79SStefano Zampini kctx->v4_m4 = 0.5;
19220f0abf79SStefano Zampini
1923b50c806fSBarry Smith PetscCall(SNESParametersInitialize(snes));
19249b94acceSBarry Smith *outsnes = snes;
19253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19269b94acceSBarry Smith }
19279b94acceSBarry Smith
19289b94acceSBarry Smith /*@C
19299b94acceSBarry Smith SNESSetFunction - Sets the function evaluation routine and function
1930f6dfbefdSBarry Smith vector for use by the `SNES` routines in solving systems of nonlinear
19319b94acceSBarry Smith equations.
19329b94acceSBarry Smith
1933c3339decSBarry Smith Logically Collective
1934fee21e36SBarry Smith
1935c7afd0dbSLois Curfman McInnes Input Parameters:
1936f6dfbefdSBarry Smith + snes - the `SNES` context
1937dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL`
19388434afd1SBarry Smith . f - function evaluation routine; for calling sequence see `SNESFunctionFn`
1939c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the
1940dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`)
19419b94acceSBarry Smith
194236851e7fSLois Curfman McInnes Level: beginner
194336851e7fSLois Curfman McInnes
19448434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19459b94acceSBarry Smith @*/
SNESSetFunction(SNES snes,Vec r,SNESFunctionFn * f,PetscCtx ctx)19462a8381b2SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, PetscCtx ctx)
1947d71ae5a4SJacob Faibussowitsch {
19486cab3a1bSJed Brown DM dm;
19496cab3a1bSJed Brown
19503a40ed3dSBarry Smith PetscFunctionBegin;
19510700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1952d2a683ecSLisandro Dalcin if (r) {
1953d2a683ecSLisandro Dalcin PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1954d2a683ecSLisandro Dalcin PetscCheckSameComm(snes, 1, r, 2);
19559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)r));
19569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func));
195785385478SLisandro Dalcin snes->vec_func = r;
1958d2a683ecSLisandro Dalcin }
19599566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
19609566063dSJacob Faibussowitsch PetscCall(DMSNESSetFunction(dm, f, ctx));
196148a46eb9SPierre Jolivet if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19639b94acceSBarry Smith }
19649b94acceSBarry Smith
1965e4ed7901SPeter Brune /*@C
19660b4db180SJacob Faibussowitsch SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1967e4ed7901SPeter Brune
1968c3339decSBarry Smith Logically Collective
1969e4ed7901SPeter Brune
1970e4ed7901SPeter Brune Input Parameters:
1971f6dfbefdSBarry Smith + snes - the `SNES` context
1972e4ed7901SPeter Brune - f - vector to store function value
1973e4ed7901SPeter Brune
1974dc4c0fb0SBarry Smith Level: developer
1975dc4c0fb0SBarry Smith
1976e4ed7901SPeter Brune Notes:
1977e4ed7901SPeter Brune This should not be modified during the solution procedure.
1978e4ed7901SPeter Brune
1979f6dfbefdSBarry Smith This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1980e4ed7901SPeter Brune
19811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1982e4ed7901SPeter Brune @*/
SNESSetInitialFunction(SNES snes,Vec f)1983d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1984d71ae5a4SJacob Faibussowitsch {
1985e4ed7901SPeter Brune Vec vec_func;
1986e4ed7901SPeter Brune
1987e4ed7901SPeter Brune PetscFunctionBegin;
1988e4ed7901SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1989e4ed7901SPeter Brune PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1990e4ed7901SPeter Brune PetscCheckSameComm(snes, 1, f, 2);
1991efd4aadfSBarry Smith if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1992902f982fSPeter Brune snes->vec_func_init_set = PETSC_FALSE;
19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1994902f982fSPeter Brune }
19959566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19969566063dSJacob Faibussowitsch PetscCall(VecCopy(f, vec_func));
1997f5af7f23SKarl Rupp
1998217b9c2eSPeter Brune snes->vec_func_init_set = PETSC_TRUE;
19993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2000e4ed7901SPeter Brune }
2001e4ed7901SPeter Brune
2002534ebe21SPeter Brune /*@
2003f6dfbefdSBarry Smith SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2004f6dfbefdSBarry Smith of the `SNES` method, when norms are computed in the solving process
2005534ebe21SPeter Brune
2006c3339decSBarry Smith Logically Collective
2007534ebe21SPeter Brune
2008534ebe21SPeter Brune Input Parameters:
2009f6dfbefdSBarry Smith + snes - the `SNES` context
2010365a6726SPeter Brune - normschedule - the frequency of norm computation
2011534ebe21SPeter Brune
2012517f1916SMatthew G. Knepley Options Database Key:
201367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2014517f1916SMatthew G. Knepley
2015dc4c0fb0SBarry Smith Level: advanced
2016dc4c0fb0SBarry Smith
2017534ebe21SPeter Brune Notes:
2018f6dfbefdSBarry Smith Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation
2019534ebe21SPeter Brune of the nonlinear function and the taking of its norm at every iteration to
2020534ebe21SPeter Brune even ensure convergence at all. However, methods such as custom Gauss-Seidel methods
2021f6dfbefdSBarry Smith `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2022534ebe21SPeter Brune may either be monitored for convergence or not. As these are often used as nonlinear
2023534ebe21SPeter Brune preconditioners, monitoring the norm of their error is not a useful enterprise within
2024534ebe21SPeter Brune their solution.
2025534ebe21SPeter Brune
2026e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2027534ebe21SPeter Brune @*/
SNESSetNormSchedule(SNES snes,SNESNormSchedule normschedule)2028d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2029d71ae5a4SJacob Faibussowitsch {
2030534ebe21SPeter Brune PetscFunctionBegin;
2031534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2032365a6726SPeter Brune snes->normschedule = normschedule;
20333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2034534ebe21SPeter Brune }
2035534ebe21SPeter Brune
2036534ebe21SPeter Brune /*@
2037f6dfbefdSBarry Smith SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2038f6dfbefdSBarry Smith of the `SNES` method.
2039534ebe21SPeter Brune
2040c3339decSBarry Smith Logically Collective
2041534ebe21SPeter Brune
2042534ebe21SPeter Brune Input Parameters:
2043f6dfbefdSBarry Smith + snes - the `SNES` context
2044365a6726SPeter Brune - normschedule - the type of the norm used
2045534ebe21SPeter Brune
2046534ebe21SPeter Brune Level: advanced
2047534ebe21SPeter Brune
20481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2049534ebe21SPeter Brune @*/
SNESGetNormSchedule(SNES snes,SNESNormSchedule * normschedule)2050d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2051d71ae5a4SJacob Faibussowitsch {
2052534ebe21SPeter Brune PetscFunctionBegin;
2053534ebe21SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2054365a6726SPeter Brune *normschedule = snes->normschedule;
20553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2056534ebe21SPeter Brune }
2057534ebe21SPeter Brune
2058c5ce4427SMatthew G. Knepley /*@
2059c5ce4427SMatthew G. Knepley SNESSetFunctionNorm - Sets the last computed residual norm.
2060c5ce4427SMatthew G. Knepley
2061c3339decSBarry Smith Logically Collective
2062c5ce4427SMatthew G. Knepley
2063c5ce4427SMatthew G. Knepley Input Parameters:
2064f6dfbefdSBarry Smith + snes - the `SNES` context
2065f6dfbefdSBarry Smith - norm - the value of the norm
2066c5ce4427SMatthew G. Knepley
2067c5ce4427SMatthew G. Knepley Level: developer
2068c5ce4427SMatthew G. Knepley
20691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2070c5ce4427SMatthew G. Knepley @*/
SNESSetFunctionNorm(SNES snes,PetscReal norm)2071d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2072d71ae5a4SJacob Faibussowitsch {
2073c5ce4427SMatthew G. Knepley PetscFunctionBegin;
2074c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2075c5ce4427SMatthew G. Knepley snes->norm = norm;
20763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2077c5ce4427SMatthew G. Knepley }
2078c5ce4427SMatthew G. Knepley
2079c5ce4427SMatthew G. Knepley /*@
2080c5ce4427SMatthew G. Knepley SNESGetFunctionNorm - Gets the last computed norm of the residual
2081c5ce4427SMatthew G. Knepley
2082c5ce4427SMatthew G. Knepley Not Collective
2083c5ce4427SMatthew G. Knepley
2084c5ce4427SMatthew G. Knepley Input Parameter:
2085f6dfbefdSBarry Smith . snes - the `SNES` context
2086c5ce4427SMatthew G. Knepley
2087c5ce4427SMatthew G. Knepley Output Parameter:
2088c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2089c5ce4427SMatthew G. Knepley
2090c5ce4427SMatthew G. Knepley Level: developer
2091c5ce4427SMatthew G. Knepley
20921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2093c5ce4427SMatthew G. Knepley @*/
SNESGetFunctionNorm(SNES snes,PetscReal * norm)2094d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2095d71ae5a4SJacob Faibussowitsch {
2096c5ce4427SMatthew G. Knepley PetscFunctionBegin;
2097c5ce4427SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20984f572ea9SToby Isaac PetscAssertPointer(norm, 2);
2099c5ce4427SMatthew G. Knepley *norm = snes->norm;
21003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2101c5ce4427SMatthew G. Knepley }
2102c5ce4427SMatthew G. Knepley
2103c1e67a49SFande Kong /*@
2104f6dfbefdSBarry Smith SNESGetUpdateNorm - Gets the last computed norm of the solution update
2105c1e67a49SFande Kong
2106c1e67a49SFande Kong Not Collective
2107c1e67a49SFande Kong
2108c1e67a49SFande Kong Input Parameter:
2109f6dfbefdSBarry Smith . snes - the `SNES` context
2110c1e67a49SFande Kong
2111c1e67a49SFande Kong Output Parameter:
2112c1e67a49SFande Kong . ynorm - the last computed update norm
2113c1e67a49SFande Kong
2114c1e67a49SFande Kong Level: developer
2115c1e67a49SFande Kong
2116f6dfbefdSBarry Smith Note:
2117f6dfbefdSBarry Smith The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2118f6dfbefdSBarry Smith
21191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2120c1e67a49SFande Kong @*/
SNESGetUpdateNorm(SNES snes,PetscReal * ynorm)2121d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2122d71ae5a4SJacob Faibussowitsch {
2123c1e67a49SFande Kong PetscFunctionBegin;
2124c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21254f572ea9SToby Isaac PetscAssertPointer(ynorm, 2);
2126c1e67a49SFande Kong *ynorm = snes->ynorm;
21273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2128c1e67a49SFande Kong }
2129c1e67a49SFande Kong
2130c1e67a49SFande Kong /*@
21314591eaf2SFande Kong SNESGetSolutionNorm - Gets the last computed norm of the solution
2132c1e67a49SFande Kong
2133c1e67a49SFande Kong Not Collective
2134c1e67a49SFande Kong
2135c1e67a49SFande Kong Input Parameter:
2136f6dfbefdSBarry Smith . snes - the `SNES` context
2137c1e67a49SFande Kong
2138c1e67a49SFande Kong Output Parameter:
2139c1e67a49SFande Kong . xnorm - the last computed solution norm
2140c1e67a49SFande Kong
2141c1e67a49SFande Kong Level: developer
2142c1e67a49SFande Kong
21431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2144c1e67a49SFande Kong @*/
SNESGetSolutionNorm(SNES snes,PetscReal * xnorm)2145d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2146d71ae5a4SJacob Faibussowitsch {
2147c1e67a49SFande Kong PetscFunctionBegin;
2148c1e67a49SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21494f572ea9SToby Isaac PetscAssertPointer(xnorm, 2);
2150c1e67a49SFande Kong *xnorm = snes->xnorm;
21513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2152c1e67a49SFande Kong }
2153c1e67a49SFande Kong
2154cc4c1da9SBarry Smith /*@
2155f6dfbefdSBarry Smith SNESSetFunctionType - Sets the `SNESFunctionType`
2156f6dfbefdSBarry Smith of the `SNES` method.
215747073ea2SPeter Brune
2158c3339decSBarry Smith Logically Collective
215947073ea2SPeter Brune
216047073ea2SPeter Brune Input Parameters:
2161f6dfbefdSBarry Smith + snes - the `SNES` context
2162f6dfbefdSBarry Smith - type - the function type
216347073ea2SPeter Brune
216447073ea2SPeter Brune Level: developer
216547073ea2SPeter Brune
2166420bcc1bSBarry Smith Values of the function type\:
2167f6dfbefdSBarry Smith + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2168f6dfbefdSBarry Smith . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2169f6dfbefdSBarry Smith - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2170f6dfbefdSBarry Smith
2171420bcc1bSBarry Smith Note:
2172f6dfbefdSBarry Smith Different `SNESType`s use this value in different ways
2173f6dfbefdSBarry Smith
21741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
217547073ea2SPeter Brune @*/
SNESSetFunctionType(SNES snes,SNESFunctionType type)2176d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2177d71ae5a4SJacob Faibussowitsch {
217847073ea2SPeter Brune PetscFunctionBegin;
217947073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
218047073ea2SPeter Brune snes->functype = type;
21813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
218247073ea2SPeter Brune }
218347073ea2SPeter Brune
2184cc4c1da9SBarry Smith /*@
2185f6dfbefdSBarry Smith SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
218647073ea2SPeter Brune of the SNES method.
218747073ea2SPeter Brune
2188c3339decSBarry Smith Logically Collective
218947073ea2SPeter Brune
219047073ea2SPeter Brune Input Parameters:
2191f6dfbefdSBarry Smith + snes - the `SNES` context
2192f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
219347073ea2SPeter Brune
219447073ea2SPeter Brune Level: advanced
219547073ea2SPeter Brune
21961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
219747073ea2SPeter Brune @*/
SNESGetFunctionType(SNES snes,SNESFunctionType * type)2198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2199d71ae5a4SJacob Faibussowitsch {
220047073ea2SPeter Brune PetscFunctionBegin;
220147073ea2SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
220247073ea2SPeter Brune *type = snes->functype;
22033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2204534ebe21SPeter Brune }
2205534ebe21SPeter Brune
2206c79ef259SPeter Brune /*@C
2207be95d8f1SBarry Smith SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2208c79ef259SPeter Brune use with composed nonlinear solvers.
2209c79ef259SPeter Brune
2210c79ef259SPeter Brune Input Parameters:
22119bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22128434afd1SBarry Smith . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
221377e5a1f9SBarry Smith - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2214c79ef259SPeter Brune
2215dc4c0fb0SBarry Smith Level: intermediate
2216dc4c0fb0SBarry Smith
2217f6dfbefdSBarry Smith Note:
2218f6dfbefdSBarry Smith The `SNESNGS` routines are used by the composed nonlinear solver to generate
2219f6dfbefdSBarry Smith a problem appropriate update to the solution, particularly `SNESFAS`.
2220c79ef259SPeter Brune
22218434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2222c79ef259SPeter Brune @*/
SNESSetNGS(SNES snes,SNESNGSFn * f,PetscCtx ctx)22232a8381b2SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, PetscCtx ctx)
2224d71ae5a4SJacob Faibussowitsch {
22256cab3a1bSJed Brown DM dm;
22266cab3a1bSJed Brown
2227646217ecSPeter Brune PetscFunctionBegin;
22286cab3a1bSJed Brown PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22299566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
22309566063dSJacob Faibussowitsch PetscCall(DMSNESSetNGS(dm, f, ctx));
22313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2232646217ecSPeter Brune }
2233646217ecSPeter Brune
2234bbc1464cSBarry Smith /*
2235bbc1464cSBarry Smith This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2236bbc1464cSBarry Smith changed during the KSPSolve()
2237bbc1464cSBarry Smith */
SNESPicardComputeMFFunction(SNES snes,Vec x,Vec f,PetscCtx ctx)22382a8381b2SBarry Smith PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, PetscCtx ctx)
2239d71ae5a4SJacob Faibussowitsch {
2240bbc1464cSBarry Smith DM dm;
2241bbc1464cSBarry Smith DMSNES sdm;
2242bbc1464cSBarry Smith
2243bbc1464cSBarry Smith PetscFunctionBegin;
22449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
22459566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
2246bbc1464cSBarry Smith /* A(x)*x - b(x) */
2247bbc1464cSBarry Smith if (sdm->ops->computepfunction) {
2248792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22499566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0));
22500df40c35SBarry Smith /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2251ef1023bdSBarry Smith if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2252792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22539566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->picard, x, f, f));
2254bbc1464cSBarry Smith } else {
2255792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22569566063dSJacob Faibussowitsch PetscCall(MatMult(snes->picard, x, f));
2257bbc1464cSBarry Smith }
22583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2259bbc1464cSBarry Smith }
2260bbc1464cSBarry Smith
SNESPicardComputeFunction(SNES snes,Vec x,Vec f,PetscCtx ctx)22612a8381b2SBarry Smith PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, PetscCtx ctx)
2262d71ae5a4SJacob Faibussowitsch {
2263e03ab78fSPeter Brune DM dm;
2264942e3340SBarry Smith DMSNES sdm;
22656cab3a1bSJed Brown
22668b0a5094SBarry Smith PetscFunctionBegin;
22679566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
22689566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
22698b0a5094SBarry Smith /* A(x)*x - b(x) */
2270bbc1464cSBarry Smith if (sdm->ops->computepfunction) {
2271792fecdfSBarry Smith PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22729566063dSJacob Faibussowitsch PetscCall(VecScale(f, -1.0));
2273792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22749566063dSJacob Faibussowitsch PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2275bbc1464cSBarry Smith } else {
2276792fecdfSBarry Smith PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22779566063dSJacob Faibussowitsch PetscCall(MatMult(snes->jacobian_pre, x, f));
2278bbc1464cSBarry Smith }
22793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22808b0a5094SBarry Smith }
22818b0a5094SBarry Smith
SNESPicardComputeJacobian(SNES snes,Vec x1,Mat J,Mat B,PetscCtx ctx)22822a8381b2SBarry Smith PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, PetscCtx ctx)
2283d71ae5a4SJacob Faibussowitsch {
22848b0a5094SBarry Smith PetscFunctionBegin;
2285e03ab78fSPeter Brune /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2286bbc1464cSBarry Smith /* must assembly if matrix-free to get the last SNES solution */
22879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22908b0a5094SBarry Smith }
22918b0a5094SBarry Smith
22928b0a5094SBarry Smith /*@C
22931d27aa22SBarry Smith SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22948b0a5094SBarry Smith
2295c3339decSBarry Smith Logically Collective
22968b0a5094SBarry Smith
22978b0a5094SBarry Smith Input Parameters:
2298f6dfbefdSBarry Smith + snes - the `SNES` context
2299dc4c0fb0SBarry Smith . r - vector to store function values, may be `NULL`
23008434afd1SBarry Smith . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
230126a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2302dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23038434afd1SBarry Smith . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2304dc4c0fb0SBarry Smith - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2305dc4c0fb0SBarry Smith
2306dc4c0fb0SBarry Smith Level: intermediate
23078b0a5094SBarry Smith
23088b0a5094SBarry Smith Notes:
230926a11704SBarry Smith It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2310f450aa47SBarry 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.
2311f450aa47SBarry Smith
2312f6dfbefdSBarry Smith One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23138b0a5094SBarry Smith
23141d27aa22SBarry 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}$.
23151d27aa22SBarry Smith When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23168b0a5094SBarry Smith
231726a11704SBarry Smith Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23188b0a5094SBarry Smith
23190d04baf8SBarry Smith We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23201d27aa22SBarry Smith the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23218b0a5094SBarry Smith
23228b0a5094SBarry 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
23231d27aa22SBarry 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
23241d27aa22SBarry Smith different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23258b0a5094SBarry Smith
23261d27aa22SBarry 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
232726a11704SBarry Smith $A(x^{n})$ is used to build the preconditioner
23286b7fb656SBarry Smith
232915229ffcSPierre 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.
23306b7fb656SBarry Smith
2331dc4c0fb0SBarry 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
233226a11704SBarry 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
233326a11704SBarry 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`.
2334aaa8cc7dSPierre Jolivet See the comment in src/snes/tutorials/ex15.c.
2335bbc1464cSBarry Smith
23369bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23378434afd1SBarry Smith `SNESFunctionFn`, `SNESJacobianFn`
23388b0a5094SBarry Smith @*/
SNESSetPicard(SNES snes,Vec r,SNESFunctionFn * bp,Mat Amat,Mat Pmat,SNESJacobianFn * J,PetscCtx ctx)23392a8381b2SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, PetscCtx ctx)
2340d71ae5a4SJacob Faibussowitsch {
2341e03ab78fSPeter Brune DM dm;
2342e03ab78fSPeter Brune
23438b0a5094SBarry Smith PetscFunctionBegin;
23448b0a5094SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23459566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
23469566063dSJacob Faibussowitsch PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23479566063dSJacob Faibussowitsch PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23489566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23499566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23518b0a5094SBarry Smith }
23528b0a5094SBarry Smith
23537971a8bfSPeter Brune /*@C
23547971a8bfSPeter Brune SNESGetPicard - Returns the context for the Picard iteration
23557971a8bfSPeter Brune
2356f6dfbefdSBarry Smith Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23577971a8bfSPeter Brune
23587971a8bfSPeter Brune Input Parameter:
2359f6dfbefdSBarry Smith . snes - the `SNES` context
23607971a8bfSPeter Brune
2361d8d19677SJose E. Roman Output Parameters:
2362dc4c0fb0SBarry Smith + r - the function (or `NULL`)
23638434afd1SBarry Smith . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn`
2364dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2365dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23668434afd1SBarry Smith . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn`
2367dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
23687971a8bfSPeter Brune
23697971a8bfSPeter Brune Level: advanced
23707971a8bfSPeter Brune
23718434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23727971a8bfSPeter Brune @*/
SNESGetPicard(SNES snes,Vec * r,SNESFunctionFn ** f,Mat * Amat,Mat * Pmat,SNESJacobianFn ** J,PetscCtxRt ctx)23732a8381b2SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, PetscCtxRt ctx)
2374d71ae5a4SJacob Faibussowitsch {
23757971a8bfSPeter Brune DM dm;
23767971a8bfSPeter Brune
23777971a8bfSPeter Brune PetscFunctionBegin;
23787971a8bfSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23799566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23809566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23819566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
23829566063dSJacob Faibussowitsch PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23847971a8bfSPeter Brune }
23857971a8bfSPeter Brune
2386d25893d9SBarry Smith /*@C
2387dc4c0fb0SBarry Smith SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2388d25893d9SBarry Smith
2389c3339decSBarry Smith Logically Collective
2390d25893d9SBarry Smith
2391d25893d9SBarry Smith Input Parameters:
2392f6dfbefdSBarry Smith + snes - the `SNES` context
23938434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2394d25893d9SBarry Smith - ctx - [optional] user-defined context for private data for the
2395dc4c0fb0SBarry Smith function evaluation routine (may be `NULL`)
2396d25893d9SBarry Smith
2397d25893d9SBarry Smith Level: intermediate
2398d25893d9SBarry Smith
23998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2400d25893d9SBarry Smith @*/
SNESSetComputeInitialGuess(SNES snes,SNESInitialGuessFn * func,PetscCtx ctx)24012a8381b2SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, PetscCtx ctx)
2402d71ae5a4SJacob Faibussowitsch {
2403d25893d9SBarry Smith PetscFunctionBegin;
2404d25893d9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2405d25893d9SBarry Smith if (func) snes->ops->computeinitialguess = func;
2406d25893d9SBarry Smith if (ctx) snes->initialguessP = ctx;
24073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2408d25893d9SBarry Smith }
2409d25893d9SBarry Smith
24101096aae1SMatthew Knepley /*@C
2411dc4c0fb0SBarry Smith SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2412dd8e379bSPierre Jolivet it assumes a zero right-hand side.
24131096aae1SMatthew Knepley
2414c3339decSBarry Smith Logically Collective
24151096aae1SMatthew Knepley
24161096aae1SMatthew Knepley Input Parameter:
2417f6dfbefdSBarry Smith . snes - the `SNES` context
24181096aae1SMatthew Knepley
24191096aae1SMatthew Knepley Output Parameter:
2420dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24211096aae1SMatthew Knepley
24221096aae1SMatthew Knepley Level: intermediate
24231096aae1SMatthew Knepley
24241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24251096aae1SMatthew Knepley @*/
SNESGetRhs(SNES snes,Vec * rhs)2426d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2427d71ae5a4SJacob Faibussowitsch {
24281096aae1SMatthew Knepley PetscFunctionBegin;
24290700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24304f572ea9SToby Isaac PetscAssertPointer(rhs, 2);
243185385478SLisandro Dalcin *rhs = snes->vec_rhs;
24323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24331096aae1SMatthew Knepley }
24341096aae1SMatthew Knepley
24359b94acceSBarry Smith /*@
2436f6dfbefdSBarry Smith SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24379b94acceSBarry Smith
2438c3339decSBarry Smith Collective
2439c7afd0dbSLois Curfman McInnes
24409b94acceSBarry Smith Input Parameters:
2441f6dfbefdSBarry Smith + snes - the `SNES` context
2442c7afd0dbSLois Curfman McInnes - x - input vector
24439b94acceSBarry Smith
24449b94acceSBarry Smith Output Parameter:
244576c63389SBarry Smith . f - function vector, as set by `SNESSetFunction()`
24469b94acceSBarry Smith
2447dc4c0fb0SBarry Smith Level: developer
2448dc4c0fb0SBarry Smith
244900677de2SStefano Zampini Notes:
2450f6dfbefdSBarry Smith `SNESComputeFunction()` is typically used within nonlinear solvers
2451bbc1464cSBarry Smith implementations, so users would not generally call this routine themselves.
245236851e7fSLois Curfman McInnes
245376c63389SBarry Smith When solving for $F(x) = b$, this routine computes $f = F(x) - b$.
245400677de2SStefano Zampini
245576c63389SBarry Smith This function usually appears in the pattern.
245676c63389SBarry Smith .vb
245776c63389SBarry Smith SNESComputeFunction(snes, x, f);
245876c63389SBarry Smith VecNorm(f, &fnorm);
245976c63389SBarry Smith SNESCheckFunctionDomainError(snes, fnorm); or SNESLineSearchCheckFunctionDomainError(ls, fnorm);
246076c63389SBarry Smith .ve
246176c63389SBarry Smith to collectively handle the use of `SNESSetFunctionDomainError()` in the provided callback function.
246276c63389SBarry Smith
246376c63389SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`, `SNESSetFunctionDomainError()`
24649b94acceSBarry Smith @*/
SNESComputeFunction(SNES snes,Vec x,Vec f)246576c63389SBarry Smith PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec f)
2466d71ae5a4SJacob Faibussowitsch {
24676cab3a1bSJed Brown DM dm;
2468942e3340SBarry Smith DMSNES sdm;
24699b94acceSBarry Smith
24703a40ed3dSBarry Smith PetscFunctionBegin;
24710700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24720700a824SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
247376c63389SBarry Smith PetscValidHeaderSpecific(f, VEC_CLASSID, 3);
2474c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, x, 2);
247576c63389SBarry Smith PetscCheckSameComm(snes, 1, f, 3);
2476e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2477184914b5SBarry Smith
24789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
24799566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
24800fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computefunction || snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
248132f3f7c2SPeter Brune if (sdm->ops->computefunction) {
248276c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, f, 0));
24839566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x));
24848ddeebeaSSteve Benbow /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
248576c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE;
2486800f99ffSJeremy L Thompson {
2487800f99ffSJeremy L Thompson void *ctx;
24888434afd1SBarry Smith SNESFunctionFn *computefunction;
2489800f99ffSJeremy L Thompson PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
249076c63389SBarry Smith PetscCallBack("SNES callback function", (*computefunction)(snes, x, f, ctx));
2491800f99ffSJeremy L Thompson }
24929566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x));
249376c63389SBarry Smith if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, f, 0));
24940fdf79fbSJacob Faibussowitsch } else /* if (snes->vec_rhs) */ {
249576c63389SBarry Smith PetscCall(MatMult(snes->jacobian, x, f));
24960fdf79fbSJacob Faibussowitsch }
249776c63389SBarry Smith if (snes->vec_rhs) PetscCall(VecAXPY(f, -1.0, snes->vec_rhs));
2498ae3c334cSLois Curfman McInnes snes->nfuncs++;
2499422a814eSBarry Smith /*
250076c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will
2501422a814eSBarry Smith propagate the value to all processes
2502422a814eSBarry Smith */
250376c63389SBarry Smith PetscCall(VecFlag(f, snes->functiondomainerror));
25043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
25059b94acceSBarry Smith }
25069b94acceSBarry Smith
2507c79ef259SPeter Brune /*@
25080b4b7b1cSBarry Smith SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2509bbc1464cSBarry Smith
2510c3339decSBarry Smith Collective
2511bbc1464cSBarry Smith
2512bbc1464cSBarry Smith Input Parameters:
2513f6dfbefdSBarry Smith + snes - the `SNES` context
2514bbc1464cSBarry Smith - x - input vector
2515bbc1464cSBarry Smith
2516bbc1464cSBarry Smith Output Parameter:
25170b4b7b1cSBarry Smith . y - output vector
2518bbc1464cSBarry Smith
2519dc4c0fb0SBarry Smith Level: developer
2520dc4c0fb0SBarry Smith
2521bbc1464cSBarry Smith Notes:
2522420bcc1bSBarry Smith `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2523bbc1464cSBarry Smith so users would not generally call this routine themselves.
2524bbc1464cSBarry Smith
2525dd8e379bSPierre Jolivet Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2526f6dfbefdSBarry Smith while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the
2527dd8e379bSPierre Jolivet same function as `SNESComputeFunction()` if a `SNESSolve()` right-hand side vector is use because the two functions difference would include this right hand side function.
2528bbc1464cSBarry Smith
25290b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2530bbc1464cSBarry Smith @*/
SNESComputeMFFunction(SNES snes,Vec x,Vec y)2531d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2532d71ae5a4SJacob Faibussowitsch {
2533bbc1464cSBarry Smith DM dm;
2534bbc1464cSBarry Smith DMSNES sdm;
2535bbc1464cSBarry Smith
2536bbc1464cSBarry Smith PetscFunctionBegin;
2537bbc1464cSBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2538bbc1464cSBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2539bbc1464cSBarry Smith PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2540bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, x, 2);
2541bbc1464cSBarry Smith PetscCheckSameComm(snes, 1, y, 3);
2542e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2543bbc1464cSBarry Smith
25449566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
25459566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
25469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25479566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(x));
2548bbc1464cSBarry Smith /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
254976c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE;
2550792fecdfSBarry Smith PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25519566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(x));
25529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2553bbc1464cSBarry Smith snes->nfuncs++;
2554bbc1464cSBarry Smith /*
255576c63389SBarry Smith domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will
2556bbc1464cSBarry Smith propagate the value to all processes
2557bbc1464cSBarry Smith */
255876c63389SBarry Smith PetscCall(VecFlag(y, snes->functiondomainerror));
25593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2560bbc1464cSBarry Smith }
2561bbc1464cSBarry Smith
2562bbc1464cSBarry Smith /*@
2563f6dfbefdSBarry Smith SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2564c79ef259SPeter Brune
2565c3339decSBarry Smith Collective
2566c79ef259SPeter Brune
2567c79ef259SPeter Brune Input Parameters:
2568f6dfbefdSBarry Smith + snes - the `SNES` context
2569c79ef259SPeter Brune . x - input vector
2570c79ef259SPeter Brune - b - rhs vector
2571c79ef259SPeter Brune
2572c79ef259SPeter Brune Output Parameter:
2573c79ef259SPeter Brune . x - new solution vector
2574c79ef259SPeter Brune
2575dc4c0fb0SBarry Smith Level: developer
2576dc4c0fb0SBarry Smith
2577f6dfbefdSBarry Smith Note:
2578f6dfbefdSBarry Smith `SNESComputeNGS()` is typically used within composed nonlinear solver
2579c79ef259SPeter Brune implementations, so most users would not generally call this routine
2580c79ef259SPeter Brune themselves.
2581c79ef259SPeter Brune
25828434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2583c79ef259SPeter Brune @*/
SNESComputeNGS(SNES snes,Vec b,Vec x)2584d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2585d71ae5a4SJacob Faibussowitsch {
25866cab3a1bSJed Brown DM dm;
2587942e3340SBarry Smith DMSNES sdm;
2588646217ecSPeter Brune
2589646217ecSPeter Brune PetscFunctionBegin;
2590646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2591064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2592064a246eSJacob Faibussowitsch if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2593064a246eSJacob Faibussowitsch PetscCheckSameComm(snes, 1, x, 3);
2594064a246eSJacob Faibussowitsch if (b) PetscCheckSameComm(snes, 1, b, 2);
2595e0f629ddSJacob Faibussowitsch if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25979566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
25989566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
25990fdf79fbSJacob Faibussowitsch PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26009566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPush(b));
2601792fecdfSBarry Smith PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26029566063dSJacob Faibussowitsch if (b) PetscCall(VecLockReadPop(b));
26039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2605646217ecSPeter Brune }
2606646217ecSPeter Brune
SNESComputeFunction_FD(SNES snes,Vec Xin,Vec G)2607494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2608494a190aSStefano Zampini {
2609494a190aSStefano Zampini Vec X;
2610494a190aSStefano Zampini PetscScalar *g;
2611494a190aSStefano Zampini PetscReal f, f2;
2612494a190aSStefano Zampini PetscInt low, high, N, i;
2613494a190aSStefano Zampini PetscBool flg;
2614494a190aSStefano Zampini PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2615494a190aSStefano Zampini
2616494a190aSStefano Zampini PetscFunctionBegin;
2617494a190aSStefano Zampini PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2618494a190aSStefano Zampini PetscCall(VecDuplicate(Xin, &X));
2619494a190aSStefano Zampini PetscCall(VecCopy(Xin, X));
2620494a190aSStefano Zampini PetscCall(VecGetSize(X, &N));
2621494a190aSStefano Zampini PetscCall(VecGetOwnershipRange(X, &low, &high));
2622494a190aSStefano Zampini PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2623494a190aSStefano Zampini PetscCall(VecGetArray(G, &g));
2624494a190aSStefano Zampini for (i = 0; i < N; i++) {
2625494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2626494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X));
2627494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X));
2628494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f));
2629494a190aSStefano Zampini PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2630494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X));
2631494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X));
2632494a190aSStefano Zampini PetscCall(SNESComputeObjective(snes, X, &f2));
2633494a190aSStefano Zampini PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2634494a190aSStefano Zampini PetscCall(VecAssemblyBegin(X));
2635494a190aSStefano Zampini PetscCall(VecAssemblyEnd(X));
2636494a190aSStefano Zampini if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2637494a190aSStefano Zampini }
2638494a190aSStefano Zampini PetscCall(VecRestoreArray(G, &g));
2639494a190aSStefano Zampini PetscCall(VecDestroy(&X));
2640494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
2641494a190aSStefano Zampini }
2642494a190aSStefano Zampini
26431dfd7622SMatthew Knepley /*@
26441dfd7622SMatthew Knepley SNESTestFunction - Computes the difference between the computed and finite-difference functions
26451dfd7622SMatthew Knepley
26461dfd7622SMatthew Knepley Collective
26471dfd7622SMatthew Knepley
2648d5bfe6baSJose E. Roman Input Parameter:
26491dfd7622SMatthew Knepley . snes - the `SNES` context
26501dfd7622SMatthew Knepley
26511dfd7622SMatthew Knepley Options Database Keys:
26521dfd7622SMatthew Knepley + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors.
26531dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference
26541dfd7622SMatthew Knepley
26551dfd7622SMatthew Knepley Level: developer
26561dfd7622SMatthew Knepley
26571dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()`
26581dfd7622SMatthew Knepley @*/
SNESTestFunction(SNES snes)2659494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2660494a190aSStefano Zampini {
2661494a190aSStefano Zampini Vec x, g1, g2, g3;
26621dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE;
2663494a190aSStefano Zampini PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2664494a190aSStefano Zampini PetscScalar dot;
2665494a190aSStefano Zampini MPI_Comm comm;
2666494a190aSStefano Zampini PetscViewer viewer, mviewer;
2667494a190aSStefano Zampini PetscViewerFormat format;
2668494a190aSStefano Zampini PetscInt tabs;
2669494a190aSStefano Zampini static PetscBool directionsprinted = PETSC_FALSE;
26708434afd1SBarry Smith SNESObjectiveFn *objective;
2671494a190aSStefano Zampini
2672494a190aSStefano Zampini PetscFunctionBegin;
2673494a190aSStefano Zampini PetscCall(SNESGetObjective(snes, &objective, NULL));
2674494a190aSStefano Zampini if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2675494a190aSStefano Zampini
2676494a190aSStefano Zampini PetscObjectOptionsBegin((PetscObject)snes);
2677494a190aSStefano Zampini PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2678494a190aSStefano Zampini PetscOptionsEnd();
2679494a190aSStefano Zampini
2680494a190aSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2681494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2682494a190aSStefano Zampini PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2683494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2684494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n"));
2685494a190aSStefano Zampini if (!complete_print && !directionsprinted) {
2686494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2687494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n"));
2688494a190aSStefano Zampini }
2689494a190aSStefano Zampini if (!directionsprinted) {
2690494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2691494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n"));
2692494a190aSStefano Zampini directionsprinted = PETSC_TRUE;
2693494a190aSStefano Zampini }
2694494a190aSStefano Zampini if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2695494a190aSStefano Zampini
2696494a190aSStefano Zampini PetscCall(SNESGetSolution(snes, &x));
2697494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g1));
2698494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g2));
2699494a190aSStefano Zampini PetscCall(VecDuplicate(x, &g3));
270076c63389SBarry Smith PetscCall(SNESComputeFunction(snes, x, g1)); /* does not handle use of SNESSetFunctionDomainError() corrrectly */
2701494a190aSStefano Zampini PetscCall(SNESComputeFunction_FD(snes, x, g2));
2702494a190aSStefano Zampini
2703494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2704494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2705494a190aSStefano Zampini PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2706494a190aSStefano Zampini PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2707494a190aSStefano Zampini PetscCall(VecDot(g1, g2, &dot));
2708494a190aSStefano Zampini PetscCall(VecCopy(g1, g3));
2709494a190aSStefano Zampini PetscCall(VecAXPY(g3, -1.0, g2));
2710494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2711494a190aSStefano Zampini PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2712494a190aSStefano 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))));
2713494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2714494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2715494a190aSStefano Zampini
2716494a190aSStefano Zampini if (complete_print) {
2717494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n"));
2718494a190aSStefano Zampini PetscCall(VecView(g1, mviewer));
2719494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n"));
2720494a190aSStefano Zampini PetscCall(VecView(g2, mviewer));
2721494a190aSStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n"));
2722494a190aSStefano Zampini PetscCall(VecView(g3, mviewer));
2723494a190aSStefano Zampini }
2724494a190aSStefano Zampini PetscCall(VecDestroy(&g1));
2725494a190aSStefano Zampini PetscCall(VecDestroy(&g2));
2726494a190aSStefano Zampini PetscCall(VecDestroy(&g3));
2727494a190aSStefano Zampini
2728494a190aSStefano Zampini if (complete_print) {
2729494a190aSStefano Zampini PetscCall(PetscViewerPopFormat(mviewer));
2730494a190aSStefano Zampini PetscCall(PetscViewerDestroy(&mviewer));
2731494a190aSStefano Zampini }
2732494a190aSStefano Zampini PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2733494a190aSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
2734494a190aSStefano Zampini }
2735494a190aSStefano Zampini
2736cbf8f02cSMatthew G. Knepley /*@
2737cbf8f02cSMatthew G. Knepley SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2738cbf8f02cSMatthew G. Knepley
2739cbf8f02cSMatthew G. Knepley Collective
2740cbf8f02cSMatthew G. Knepley
2741d5bfe6baSJose E. Roman Input Parameter:
2742cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2743cbf8f02cSMatthew G. Knepley
2744cbf8f02cSMatthew G. Knepley Output Parameters:
27451dfd7622SMatthew Knepley + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL`
27461dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL`
2747cbf8f02cSMatthew G. Knepley
2748cbf8f02cSMatthew G. Knepley Options Database Keys:
2749cbf8f02cSMatthew G. Knepley + -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.
2750cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference
2751cbf8f02cSMatthew G. Knepley
2752cbf8f02cSMatthew G. Knepley Level: developer
2753cbf8f02cSMatthew G. Knepley
27541dfd7622SMatthew Knepley Note:
27551dfd7622SMatthew Knepley Directions and norms are printed to stdout if `diffNorm` is `NULL`.
27561dfd7622SMatthew Knepley
27571dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()`
2758cbf8f02cSMatthew G. Knepley @*/
SNESTestJacobian(SNES snes,PetscReal * Jnorm,PetscReal * diffNorm)2759cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2760d71ae5a4SJacob Faibussowitsch {
276112837594SBarry Smith Mat A, B, C, D, jacobian;
27624df93895SStefano Zampini Vec x = snes->vec_sol, f;
2763e885f1abSBarry Smith PetscReal nrm, gnorm;
276481e7118cSBarry Smith PetscReal threshold = 1.e-5;
27650e276705SLisandro Dalcin MatType mattype;
2766e885f1abSBarry Smith PetscInt m, n, M, N;
2767e885f1abSBarry Smith void *functx;
27681dfd7622SMatthew Knepley PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose;
27691dfd7622SMatthew Knepley PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE;
27703325ff46SBarry Smith PetscViewer viewer, mviewer;
2771e885f1abSBarry Smith MPI_Comm comm;
2772e885f1abSBarry Smith PetscInt tabs;
277312837594SBarry Smith static PetscBool directionsprinted = PETSC_FALSE;
27743325ff46SBarry Smith PetscViewerFormat format;
2775e885f1abSBarry Smith
2776e885f1abSBarry Smith PetscFunctionBegin;
2777d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)snes);
27789566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27799566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27804ead3382SBarry Smith PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27819566063dSJacob Faibussowitsch PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27829566063dSJacob 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));
2783d0609cedSBarry Smith PetscOptionsEnd();
2784e885f1abSBarry Smith
27859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27891dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n"));
27901dfd7622SMatthew Knepley if (!complete_print && !silent && !directionsprinted) {
27919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
279312837594SBarry Smith }
27941dfd7622SMatthew Knepley if (!directionsprinted && !silent) {
27959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
279712837594SBarry Smith directionsprinted = PETSC_TRUE;
2798e885f1abSBarry Smith }
27991baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2800e885f1abSBarry Smith
28019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
280212837594SBarry Smith if (!flg) jacobian = snes->jacobian;
280312837594SBarry Smith else jacobian = snes->jacobian_pre;
280412837594SBarry Smith
28054df93895SStefano Zampini if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
28064df93895SStefano Zampini else PetscCall(PetscObjectReference((PetscObject)x));
28079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &f));
28084df93895SStefano Zampini
2809a82339d0SMatthew G. Knepley /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
28109566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, x, f));
28119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&f));
28129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
281312837594SBarry Smith while (jacobian) {
28142cd624f9SStefano Zampini Mat JT = NULL, Jsave = NULL;
28152cd624f9SStefano Zampini
28162cd624f9SStefano Zampini if (istranspose) {
28179566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(jacobian, &JT));
28182cd624f9SStefano Zampini Jsave = jacobian;
28192cd624f9SStefano Zampini jacobian = JT;
28202cd624f9SStefano Zampini }
28219566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
282212837594SBarry Smith if (flg) {
282312837594SBarry Smith A = jacobian;
28249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A));
282512837594SBarry Smith } else {
28269566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
282712837594SBarry Smith }
2828e885f1abSBarry Smith
28299566063dSJacob Faibussowitsch PetscCall(MatGetType(A, &mattype));
28309566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N));
28319566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &m, &n));
28329566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28339566063dSJacob Faibussowitsch PetscCall(MatSetType(B, mattype));
28349566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N));
28359566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A));
28369566063dSJacob Faibussowitsch PetscCall(MatSetUp(B));
28379566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2838e885f1abSBarry Smith
28399566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28409566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
284112837594SBarry Smith
28429566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28439566063dSJacob Faibussowitsch PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28449566063dSJacob Faibussowitsch PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28459566063dSJacob Faibussowitsch PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&D));
284712837594SBarry Smith if (!gnorm) gnorm = 1; /* just in case */
28481dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
2849e885f1abSBarry Smith if (complete_print) {
28509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n"));
28519566063dSJacob Faibussowitsch PetscCall(MatView(A, mviewer));
28529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n"));
28539566063dSJacob Faibussowitsch PetscCall(MatView(B, mviewer));
2854e885f1abSBarry Smith }
2855e885f1abSBarry Smith
2856df10fb39SFande Kong if (threshold_print || complete_print) {
2857e885f1abSBarry Smith PetscInt Istart, Iend, *ccols, bncols, cncols, j, row;
2858e885f1abSBarry Smith PetscScalar *cvals;
2859e885f1abSBarry Smith const PetscInt *bcols;
2860e885f1abSBarry Smith const PetscScalar *bvals;
2861e885f1abSBarry Smith
28629566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28639566063dSJacob Faibussowitsch PetscCall(MatSetType(C, mattype));
28649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, m, n, M, N));
28659566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C, A, A));
28669566063dSJacob Faibussowitsch PetscCall(MatSetUp(C));
28679566063dSJacob Faibussowitsch PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28680e276705SLisandro Dalcin
28699566063dSJacob Faibussowitsch PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28709566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2871e885f1abSBarry Smith
2872e885f1abSBarry Smith for (row = Istart; row < Iend; row++) {
28739566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28749566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2875e885f1abSBarry Smith for (j = 0, cncols = 0; j < bncols; j++) {
287623a52b1dSBarry Smith if (PetscAbsScalar(bvals[j]) > threshold) {
2877e885f1abSBarry Smith ccols[cncols] = bcols[j];
2878e885f1abSBarry Smith cvals[cncols] = bvals[j];
2879e885f1abSBarry Smith cncols += 1;
2880e885f1abSBarry Smith }
2881e885f1abSBarry Smith }
288248a46eb9SPierre Jolivet if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28839566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28849566063dSJacob Faibussowitsch PetscCall(PetscFree2(ccols, cvals));
2885e885f1abSBarry Smith }
28869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28899566063dSJacob Faibussowitsch PetscCall(MatView(C, complete_print ? mviewer : viewer));
28909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C));
2891e885f1abSBarry Smith }
28929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A));
28939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B));
28949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&JT));
28952cd624f9SStefano Zampini if (Jsave) jacobian = Jsave;
289612837594SBarry Smith if (jacobian != snes->jacobian_pre) {
289712837594SBarry Smith jacobian = snes->jacobian_pre;
28981dfd7622SMatthew Knepley if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n"));
28999371c9d4SSatish Balay } else jacobian = NULL;
290012837594SBarry Smith }
29019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x));
29021baa6e33SBarry Smith if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2903648c30bcSBarry Smith if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
29049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2905cbf8f02cSMatthew G. Knepley
2906cbf8f02cSMatthew G. Knepley if (Jnorm) *Jnorm = gnorm;
2907cbf8f02cSMatthew G. Knepley if (diffNorm) *diffNorm = nrm;
29083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2909e885f1abSBarry Smith }
2910e885f1abSBarry Smith
291162fef451SLois Curfman McInnes /*@
2912f6dfbefdSBarry Smith SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
291362fef451SLois Curfman McInnes
2914c3339decSBarry Smith Collective
2915c7afd0dbSLois Curfman McInnes
291662fef451SLois Curfman McInnes Input Parameters:
2917f6dfbefdSBarry Smith + snes - the `SNES` context
2918e4094ef1SJacob Faibussowitsch - X - input vector
291962fef451SLois Curfman McInnes
292062fef451SLois Curfman McInnes Output Parameters:
2921c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2922420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2923fee21e36SBarry Smith
2924e35cf81dSBarry Smith Options Database Keys:
292567b8a455SSatish Balay + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
292667b8a455SSatish Balay . -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2927455a5933SJed 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.
2928455a5933SJed 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
2929693365a8SJed Brown . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2930693365a8SJed Brown . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2931693365a8SJed Brown . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29327addb90fSBarry Smith . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
293394d6a431SBarry Smith . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2934a5b23f4aSJose E. Roman . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2935c01495d3SJed Brown . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2936dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2937dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2938a5b23f4aSJose E. Roman . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2939a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2940c01495d3SJed Brown
2941dc4c0fb0SBarry Smith Level: developer
2942dc4c0fb0SBarry Smith
2943f6dfbefdSBarry Smith Note:
294462fef451SLois Curfman McInnes Most users should not need to explicitly call this routine, as it
294562fef451SLois Curfman McInnes is used internally within the nonlinear solvers.
294662fef451SLois Curfman McInnes
2947420bcc1bSBarry Smith Developer Note:
2948dc4c0fb0SBarry 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
2949420bcc1bSBarry Smith with the `SNESType` of test that has been removed.
2950e885f1abSBarry Smith
295176c63389SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
295276c63389SBarry Smith `SNESSetJacobianDomainError()`, `SNESCheckJacobianDomainError()`, `SNESSetCheckJacobianDomainError()`
295362fef451SLois Curfman McInnes @*/
SNESComputeJacobian(SNES snes,Vec X,Mat A,Mat B)2954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2955d71ae5a4SJacob Faibussowitsch {
2956ace3abfcSBarry Smith PetscBool flag;
29576cab3a1bSJed Brown DM dm;
2958942e3340SBarry Smith DMSNES sdm;
2959e0e3a89bSBarry Smith KSP ksp;
29603a40ed3dSBarry Smith
29613a40ed3dSBarry Smith PetscFunctionBegin;
29620700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29630700a824SBarry Smith PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2964c9780b6fSBarry Smith PetscCheckSameComm(snes, 1, X, 2);
2965e0f629ddSJacob Faibussowitsch PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
29679566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
29683232da50SPeter Brune
296901c1178eSBarry Smith /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2970fe3ffe1eSBarry Smith if (snes->lagjacobian == -2) {
2971fe3ffe1eSBarry Smith snes->lagjacobian = -1;
2972f5af7f23SKarl Rupp
29739566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2974fe3ffe1eSBarry Smith } else if (snes->lagjacobian == -1) {
29759566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2977ebd3b9afSBarry Smith if (flag) {
29789566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29799566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2980ebd3b9afSBarry Smith }
29813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
298237ec4e1aSPeter Brune } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
298363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2985ebd3b9afSBarry Smith if (flag) {
29869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2988ebd3b9afSBarry Smith }
29893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2990e35cf81dSBarry Smith }
2991efd4aadfSBarry Smith if (snes->npc && snes->npcside == PC_LEFT) {
29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2995d728fb7dSPeter Brune }
2996e35cf81dSBarry Smith
29979566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29989566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(X));
2999800f99ffSJeremy L Thompson {
3000800f99ffSJeremy L Thompson void *ctx;
30018434afd1SBarry Smith SNESJacobianFn *J;
3002800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
3003800f99ffSJeremy L Thompson PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
3004800f99ffSJeremy L Thompson }
30059566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(X));
30069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
300728d58a37SPierre Jolivet
30087addb90fSBarry Smith /* attach latest linearization point to the matrix used to construct the preconditioner */
30099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
3010a8054027SBarry Smith
3011e0e3a89bSBarry Smith /* the next line ensures that snes->ksp exists */
30129566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
30133b4f5425SBarry Smith if (snes->lagpreconditioner == -2) {
30149566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
30159566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
30163b4f5425SBarry Smith snes->lagpreconditioner = -1;
30173b4f5425SBarry Smith } else if (snes->lagpreconditioner == -1) {
30189566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
30199566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
302037ec4e1aSPeter Brune } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
302163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
30229566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
3023d1e9a80fSBarry Smith } else {
30249566063dSJacob Faibussowitsch PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
30259566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
3026a8054027SBarry Smith }
3027a8054027SBarry Smith
30284df93895SStefano Zampini /* monkey business to allow testing Jacobians in multilevel solvers.
30294df93895SStefano Zampini This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30304df93895SStefano Zampini {
30314df93895SStefano Zampini Vec xsave = snes->vec_sol;
30324df93895SStefano Zampini Mat jacobiansave = snes->jacobian;
30334df93895SStefano Zampini Mat jacobian_presave = snes->jacobian_pre;
30344df93895SStefano Zampini
30354df93895SStefano Zampini snes->vec_sol = X;
30364df93895SStefano Zampini snes->jacobian = A;
30374df93895SStefano Zampini snes->jacobian_pre = B;
30381dfd7622SMatthew Knepley if (snes->testFunc) PetscCall(SNESTestFunction(snes));
30391dfd7622SMatthew Knepley if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL));
3040494a190aSStefano Zampini
30414df93895SStefano Zampini snes->vec_sol = xsave;
30424df93895SStefano Zampini snes->jacobian = jacobiansave;
30434df93895SStefano Zampini snes->jacobian_pre = jacobian_presave;
30444df93895SStefano Zampini }
30454df93895SStefano Zampini
3046693365a8SJed Brown {
3047693365a8SJed Brown PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3048648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3049648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3050648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3051648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3052693365a8SJed Brown if (flag || flag_draw || flag_contour) {
30530298fd71SBarry Smith Mat Bexp_mine = NULL, Bexp, FDexp;
3054693365a8SJed Brown PetscViewer vdraw, vstdout;
30556b3a5b13SJed Brown PetscBool flg;
3056693365a8SJed Brown if (flag_operator) {
30579566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3058693365a8SJed Brown Bexp = Bexp_mine;
3059693365a8SJed Brown } else {
30607addb90fSBarry Smith /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30612b2f8cc6SPierre Jolivet PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
306294ab13aaSBarry Smith if (flg) Bexp = B;
3063693365a8SJed Brown else {
3064693365a8SJed Brown /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30659566063dSJacob Faibussowitsch PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3066693365a8SJed Brown Bexp = Bexp_mine;
3067693365a8SJed Brown }
3068693365a8SJed Brown }
30699566063dSJacob Faibussowitsch PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30709566063dSJacob Faibussowitsch PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3072693365a8SJed Brown if (flag_draw || flag_contour) {
30739566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30749566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30750298fd71SBarry Smith } else vdraw = NULL;
30769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30779566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(Bexp, vstdout));
30789566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bexp, vdraw));
30799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30809566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout));
30819566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(FDexp, vdraw));
30829566063dSJacob Faibussowitsch PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30849566063dSJacob Faibussowitsch if (flag) PetscCall(MatView(FDexp, vstdout));
3085693365a8SJed Brown if (vdraw) { /* Always use contour for the difference */
30869566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30879566063dSJacob Faibussowitsch PetscCall(MatView(FDexp, vdraw));
30889566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw));
3089693365a8SJed Brown }
30909566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30919566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw));
30929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bexp_mine));
30939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&FDexp));
3094693365a8SJed Brown }
3095693365a8SJed Brown }
30964c30e9fbSJed Brown {
30976719d8e4SJed Brown PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30986719d8e4SJed Brown PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3099648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3100648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3101648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3102648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3103648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
310427b0f280SBarry Smith if (flag_threshold) {
31059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
31069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
310727b0f280SBarry Smith }
31086719d8e4SJed Brown if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
31094c30e9fbSJed Brown Mat Bfd;
31104c30e9fbSJed Brown PetscViewer vdraw, vstdout;
3111335efc43SPeter Brune MatColoring coloring;
31124c30e9fbSJed Brown ISColoring iscoloring;
31134c30e9fbSJed Brown MatFDColoring matfdcoloring;
31148434afd1SBarry Smith SNESFunctionFn *func;
31154c30e9fbSJed Brown void *funcctx;
31166719d8e4SJed Brown PetscReal norm1, norm2, normmax;
31174c30e9fbSJed Brown
31189566063dSJacob Faibussowitsch PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
31199566063dSJacob Faibussowitsch PetscCall(MatColoringCreate(Bfd, &coloring));
31209566063dSJacob Faibussowitsch PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
31219566063dSJacob Faibussowitsch PetscCall(MatColoringSetFromOptions(coloring));
31229566063dSJacob Faibussowitsch PetscCall(MatColoringApply(coloring, &iscoloring));
31239566063dSJacob Faibussowitsch PetscCall(MatColoringDestroy(&coloring));
31249566063dSJacob Faibussowitsch PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
31259566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31269566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31279566063dSJacob Faibussowitsch PetscCall(ISColoringDestroy(&iscoloring));
31284c30e9fbSJed Brown
31294c30e9fbSJed Brown /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31309566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31312ba42892SBarry Smith PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31339566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31349566063dSJacob Faibussowitsch PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31359566063dSJacob Faibussowitsch PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31369566063dSJacob Faibussowitsch PetscCall(MatFDColoringDestroy(&matfdcoloring));
31374c30e9fbSJed Brown
31389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31394c30e9fbSJed Brown if (flag_draw || flag_contour) {
31409566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31419566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31420298fd71SBarry Smith } else vdraw = NULL;
31439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31449566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(B, vstdout));
31459566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(B, vdraw));
31469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31479566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout));
31489566063dSJacob Faibussowitsch if (vdraw) PetscCall(MatView(Bfd, vdraw));
31499566063dSJacob Faibussowitsch PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31509566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31519566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31529566063dSJacob Faibussowitsch PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31549566063dSJacob Faibussowitsch if (flag_display) PetscCall(MatView(Bfd, vstdout));
31554c30e9fbSJed Brown if (vdraw) { /* Always use contour for the difference */
31569566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31579566063dSJacob Faibussowitsch PetscCall(MatView(Bfd, vdraw));
31589566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(vdraw));
31594c30e9fbSJed Brown }
31609566063dSJacob Faibussowitsch if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31616719d8e4SJed Brown
31626719d8e4SJed Brown if (flag_threshold) {
31636719d8e4SJed Brown PetscInt bs, rstart, rend, i;
31649566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(B, &bs));
31659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31666719d8e4SJed Brown for (i = rstart; i < rend; i++) {
31676719d8e4SJed Brown const PetscScalar *ba, *ca;
31686719d8e4SJed Brown const PetscInt *bj, *cj;
31696719d8e4SJed Brown PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31706719d8e4SJed Brown PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0;
31719566063dSJacob Faibussowitsch PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31729566063dSJacob Faibussowitsch PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31735f80ce2aSJacob Faibussowitsch PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31746719d8e4SJed Brown for (j = 0; j < bn; j++) {
31756719d8e4SJed Brown PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31766719d8e4SJed Brown if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31776719d8e4SJed Brown maxentrycol = bj[j];
31786719d8e4SJed Brown maxentry = PetscRealPart(ba[j]);
31796719d8e4SJed Brown }
31806719d8e4SJed Brown if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31816719d8e4SJed Brown maxdiffcol = bj[j];
31826719d8e4SJed Brown maxdiff = PetscRealPart(ca[j]);
31836719d8e4SJed Brown }
31846719d8e4SJed Brown if (rdiff > maxrdiff) {
31856719d8e4SJed Brown maxrdiffcol = bj[j];
31866719d8e4SJed Brown maxrdiff = rdiff;
31876719d8e4SJed Brown }
31886719d8e4SJed Brown }
31896719d8e4SJed Brown if (maxrdiff > 1) {
319063a3b9bcSJacob 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));
31916719d8e4SJed Brown for (j = 0; j < bn; j++) {
31926719d8e4SJed Brown PetscReal rdiff;
31936719d8e4SJed Brown rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
319448a46eb9SPierre Jolivet if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31956719d8e4SJed Brown }
319663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31976719d8e4SJed Brown }
31989566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31999566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
32006719d8e4SJed Brown }
32016719d8e4SJed Brown }
32029566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&vdraw));
32039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bfd));
32044c30e9fbSJed Brown }
32054c30e9fbSJed Brown }
32063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32079b94acceSBarry Smith }
32089b94acceSBarry Smith
32099b94acceSBarry Smith /*@C
32109b94acceSBarry Smith SNESSetJacobian - Sets the function to compute Jacobian as well as the
3211044dda88SLois Curfman McInnes location to store the matrix.
32129b94acceSBarry Smith
3213c3339decSBarry Smith Logically Collective
3214c7afd0dbSLois Curfman McInnes
32159b94acceSBarry Smith Input Parameters:
3216f6dfbefdSBarry Smith + snes - the `SNES` context
3217e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3218dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
32198434afd1SBarry Smith . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3220c7afd0dbSLois Curfman McInnes - ctx - [optional] user-defined context for private data for the
3221dc4c0fb0SBarry Smith Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3222dc4c0fb0SBarry Smith
3223dc4c0fb0SBarry Smith Level: beginner
32249b94acceSBarry Smith
32259b94acceSBarry Smith Notes:
3226dc4c0fb0SBarry Smith If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
322716913363SBarry Smith each matrix.
322816913363SBarry Smith
3229dc4c0fb0SBarry Smith If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3230dc4c0fb0SBarry Smith space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3231895c21f2SBarry Smith
3232dc4c0fb0SBarry Smith If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3233f6dfbefdSBarry Smith must be a `MatFDColoring`.
3234a8a26c1eSJed Brown
3235c3cc8fd1SJed Brown Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common
3236f6dfbefdSBarry Smith example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3237c3cc8fd1SJed Brown
32381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32398434afd1SBarry Smith `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32409b94acceSBarry Smith @*/
SNESSetJacobian(SNES snes,Mat Amat,Mat Pmat,SNESJacobianFn * J,PetscCtx ctx)32412a8381b2SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, PetscCtx ctx)
3242d71ae5a4SJacob Faibussowitsch {
32436cab3a1bSJed Brown DM dm;
32443a7fca6bSBarry Smith
32453a40ed3dSBarry Smith PetscFunctionBegin;
32460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3247e5d3d808SBarry Smith if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3248e5d3d808SBarry Smith if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3249e5d3d808SBarry Smith if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3250e5d3d808SBarry Smith if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32519566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
32529566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, J, ctx));
3253e5d3d808SBarry Smith if (Amat) {
32549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Amat));
32559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian));
3256f5af7f23SKarl Rupp
3257e5d3d808SBarry Smith snes->jacobian = Amat;
32583a7fca6bSBarry Smith }
3259e5d3d808SBarry Smith if (Pmat) {
32609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)Pmat));
32619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre));
3262f5af7f23SKarl Rupp
3263e5d3d808SBarry Smith snes->jacobian_pre = Pmat;
32643a7fca6bSBarry Smith }
32653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32669b94acceSBarry Smith }
326762fef451SLois Curfman McInnes
3268c2aafc4cSSatish Balay /*@C
3269b4fd4287SBarry Smith SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3270b4fd4287SBarry Smith provided context for evaluating the Jacobian.
3271b4fd4287SBarry Smith
3272420bcc1bSBarry Smith Not Collective, but `Mat` object will be parallel if `SNES` is
3273c7afd0dbSLois Curfman McInnes
3274b4fd4287SBarry Smith Input Parameter:
3275b4fd4287SBarry Smith . snes - the nonlinear solver context
3276b4fd4287SBarry Smith
3277b4fd4287SBarry Smith Output Parameters:
3278dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3279dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32808434afd1SBarry Smith . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3281dc4c0fb0SBarry Smith - ctx - location to stash Jacobian ctx (or `NULL`)
3282fee21e36SBarry Smith
328336851e7fSLois Curfman McInnes Level: advanced
328436851e7fSLois Curfman McInnes
32858434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3286b4fd4287SBarry Smith @*/
SNESGetJacobian(SNES snes,Mat * Amat,Mat * Pmat,SNESJacobianFn ** J,PetscCtxRt ctx)32872a8381b2SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, PetscCtxRt ctx)
3288d71ae5a4SJacob Faibussowitsch {
32896cab3a1bSJed Brown DM dm;
32906cab3a1bSJed Brown
32913a40ed3dSBarry Smith PetscFunctionBegin;
32920700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3293e5d3d808SBarry Smith if (Amat) *Amat = snes->jacobian;
3294e5d3d808SBarry Smith if (Pmat) *Pmat = snes->jacobian_pre;
32959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
3296800f99ffSJeremy L Thompson PetscCall(DMSNESGetJacobian(dm, J, ctx));
32973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3298b4fd4287SBarry Smith }
3299b4fd4287SBarry Smith
SNESSetDefaultComputeJacobian(SNES snes)3300d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3301d71ae5a4SJacob Faibussowitsch {
330258b371f3SBarry Smith DM dm;
330358b371f3SBarry Smith DMSNES sdm;
330458b371f3SBarry Smith
330558b371f3SBarry Smith PetscFunctionBegin;
33069566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
33079566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
330858b371f3SBarry Smith if (!sdm->ops->computejacobian && snes->jacobian_pre) {
330958b371f3SBarry Smith DM dm;
331058b371f3SBarry Smith PetscBool isdense, ismf;
331158b371f3SBarry Smith
33129566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
33139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
33149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
331558b371f3SBarry Smith if (isdense) {
33169566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
331758b371f3SBarry Smith } else if (!ismf) {
33189566063dSJacob Faibussowitsch PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
331958b371f3SBarry Smith }
332058b371f3SBarry Smith }
33213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
332258b371f3SBarry Smith }
332358b371f3SBarry Smith
33249b94acceSBarry Smith /*@
33259b94acceSBarry Smith SNESSetUp - Sets up the internal data structures for the later use
33260b4b7b1cSBarry Smith of a nonlinear solver `SNESSolve()`.
33279b94acceSBarry Smith
3328c3339decSBarry Smith Collective
3329fee21e36SBarry Smith
33302fe279fdSBarry Smith Input Parameter:
3331f6dfbefdSBarry Smith . snes - the `SNES` context
3332c7afd0dbSLois Curfman McInnes
3333dc4c0fb0SBarry Smith Level: advanced
3334dc4c0fb0SBarry Smith
3335f6dfbefdSBarry Smith Note:
33360b4b7b1cSBarry Smith For basic use of the `SNES` solvers the user does not need to explicitly call
3337f6dfbefdSBarry Smith `SNESSetUp()`, since these actions will automatically occur during
3338f6dfbefdSBarry Smith the call to `SNESSolve()`. However, if one wishes to control this
3339f6dfbefdSBarry Smith phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3340f6dfbefdSBarry Smith and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3341272ac6f2SLois Curfman McInnes
33420b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33439b94acceSBarry Smith @*/
SNESSetUp(SNES snes)3344d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3345d71ae5a4SJacob Faibussowitsch {
33466cab3a1bSJed Brown DM dm;
3347942e3340SBarry Smith DMSNES sdm;
3348c35f09e5SBarry Smith SNESLineSearch linesearch, pclinesearch;
33496e2a1849SPeter Brune void *lsprectx, *lspostctx;
33509b5c1c08SStefano Zampini PetscBool mf_operator, mf;
33519b5c1c08SStefano Zampini Vec f, fpc;
33529b5c1c08SStefano Zampini void *funcctx;
33539b5c1c08SStefano Zampini void *jacctx, *appctx;
33549b5c1c08SStefano Zampini Mat j, jpre;
33556b2b7091SBarry Smith PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33566b2b7091SBarry Smith PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33578434afd1SBarry Smith SNESFunctionFn *func;
33588434afd1SBarry Smith SNESJacobianFn *jac;
33593a40ed3dSBarry Smith
33603a40ed3dSBarry Smith PetscFunctionBegin;
33610700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33623ba16761SJacob Faibussowitsch if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3363fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33649b94acceSBarry Smith
336548a46eb9SPierre Jolivet if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
336685385478SLisandro Dalcin
33679566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
336858c9b817SLisandro Dalcin
33699566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
33709566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(dm, &sdm));
33719566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes));
337258b371f3SBarry Smith
337348a46eb9SPierre Jolivet if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3374efd51863SBarry Smith
337548a46eb9SPierre Jolivet if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3376b710008aSBarry Smith
3377d8d34be6SBarry Smith if (snes->linesearch) {
33789566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33799566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3380d8d34be6SBarry Smith }
33819e764e56SPeter Brune
33829b5c1c08SStefano Zampini PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3383b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) {
3384172a4300SPeter Brune snes->mf = PETSC_TRUE;
3385172a4300SPeter Brune snes->mf_operator = PETSC_FALSE;
3386172a4300SPeter Brune }
3387d8f46077SPeter Brune
3388efd4aadfSBarry Smith if (snes->npc) {
33896e2a1849SPeter Brune /* copy the DM over */
33909566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
33919566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, dm));
33926e2a1849SPeter Brune
33939566063dSJacob Faibussowitsch PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(f, &fpc));
33959566063dSJacob Faibussowitsch PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33969566063dSJacob Faibussowitsch PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33979566063dSJacob Faibussowitsch PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33989566063dSJacob Faibussowitsch PetscCall(SNESGetApplicationContext(snes, &appctx));
33999566063dSJacob Faibussowitsch PetscCall(SNESSetApplicationContext(snes->npc, appctx));
34009b5c1c08SStefano Zampini PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
34019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fpc));
34026e2a1849SPeter Brune
34036e2a1849SPeter Brune /* copy the function pointers over */
34049566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
34056e2a1849SPeter Brune
34066e2a1849SPeter Brune /* default to 1 iteration */
34079566063dSJacob Faibussowitsch PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3408efd4aadfSBarry Smith if (snes->npcside == PC_RIGHT) {
34099566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3410a9936a0cSPeter Brune } else {
34119566063dSJacob Faibussowitsch PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3412a9936a0cSPeter Brune }
34139566063dSJacob Faibussowitsch PetscCall(SNESSetFromOptions(snes->npc));
34146e2a1849SPeter Brune
34156e2a1849SPeter Brune /* copy the line search context over */
3416d8d34be6SBarry Smith if (snes->linesearch && snes->npc->linesearch) {
34179566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch));
34189566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
34199566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
34209566063dSJacob Faibussowitsch PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
34219566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
34229566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
34239566063dSJacob Faibussowitsch PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
34246e2a1849SPeter Brune }
3425d8d34be6SBarry Smith }
34261baa6e33SBarry Smith if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
34272a8381b2SBarry Smith if (snes->ops->ctxcompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->ctxcompute)(snes, &snes->ctx));
34286e2a1849SPeter Brune
342937ec4e1aSPeter Brune snes->jac_iter = 0;
343037ec4e1aSPeter Brune snes->pre_iter = 0;
343137ec4e1aSPeter Brune
3432dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, setup);
343358c9b817SLisandro Dalcin
34349566063dSJacob Faibussowitsch PetscCall(SNESSetDefaultComputeJacobian(snes));
343558b371f3SBarry Smith
3436b552625fSStefano Zampini if (snes->npc && snes->npcside == PC_LEFT) {
34376c67d002SPeter Brune if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3438d8d34be6SBarry Smith if (snes->linesearch) {
34399566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &linesearch));
34409566063dSJacob Faibussowitsch PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34416c67d002SPeter Brune }
34426c67d002SPeter Brune }
3443d8d34be6SBarry Smith }
3444fc8bc0e3SRichard Tran Mills PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34457aaed0d8SBarry Smith snes->setupcalled = PETSC_TRUE;
34463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
34479b94acceSBarry Smith }
34489b94acceSBarry Smith
344937596af1SLisandro Dalcin /*@
34500b4b7b1cSBarry Smith SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures
345137596af1SLisandro Dalcin
3452c3339decSBarry Smith Collective
345337596af1SLisandro Dalcin
345437596af1SLisandro Dalcin Input Parameter:
34550b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
345637596af1SLisandro Dalcin
3457d25893d9SBarry Smith Level: intermediate
3458d25893d9SBarry Smith
345995452b02SPatrick Sanan Notes:
34600b4b7b1cSBarry Smith Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34610b4b7b1cSBarry Smith
3462f6dfbefdSBarry Smith Call this if you wish to reuse a `SNES` but with different size vectors
346337596af1SLisandro Dalcin
3464f6dfbefdSBarry Smith Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3465f6dfbefdSBarry Smith
34661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
346737596af1SLisandro Dalcin @*/
SNESReset(SNES snes)3468d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3469d71ae5a4SJacob Faibussowitsch {
347037596af1SLisandro Dalcin PetscFunctionBegin;
347137596af1SLisandro Dalcin PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
347249abdd8aSBarry Smith if (snes->ops->ctxdestroy && snes->ctx) {
3473835f2295SStefano Zampini PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
347449abdd8aSBarry Smith snes->ctx = NULL;
3475d25893d9SBarry Smith }
34761baa6e33SBarry Smith if (snes->npc) PetscCall(SNESReset(snes->npc));
34778a23116dSBarry Smith
3478dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, reset);
34791baa6e33SBarry Smith if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34809e764e56SPeter Brune
34811baa6e33SBarry Smith if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34829e764e56SPeter Brune
34839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs));
34849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol));
34859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol_update));
34869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_func));
34879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian));
34889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->jacobian_pre));
34899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&snes->picard));
34909566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34919566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3492f5af7f23SKarl Rupp
349340fdac6aSLawrence Mitchell snes->alwayscomputesfinalresidual = PETSC_FALSE;
349440fdac6aSLawrence Mitchell
349537596af1SLisandro Dalcin snes->nwork = snes->nvwork = 0;
349637596af1SLisandro Dalcin snes->setupcalled = PETSC_FALSE;
34973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
349837596af1SLisandro Dalcin }
349937596af1SLisandro Dalcin
350052baeb72SSatish Balay /*@
350136d43d94SBarry Smith SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
350236d43d94SBarry Smith removes the default viewer.
3503c4421ceaSFande Kong
3504c3339decSBarry Smith Collective
3505c4421ceaSFande Kong
3506c4421ceaSFande Kong Input Parameter:
35070b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3508c4421ceaSFande Kong
3509c4421ceaSFande Kong Level: intermediate
3510c4421ceaSFande Kong
3511420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3512c4421ceaSFande Kong @*/
SNESConvergedReasonViewCancel(SNES snes)3513d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3514d71ae5a4SJacob Faibussowitsch {
3515c4421ceaSFande Kong PetscInt i;
3516c4421ceaSFande Kong
3517c4421ceaSFande Kong PetscFunctionBegin;
3518c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3519c4421ceaSFande Kong for (i = 0; i < snes->numberreasonviews; i++) {
352048a46eb9SPierre Jolivet if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3521c4421ceaSFande Kong }
3522c4421ceaSFande Kong snes->numberreasonviews = 0;
3523648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
35243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3525c4421ceaSFande Kong }
3526c4421ceaSFande Kong
35270764c050SBarry Smith /*@
35289b94acceSBarry Smith SNESDestroy - Destroys the nonlinear solver context that was created
3529f6dfbefdSBarry Smith with `SNESCreate()`.
35309b94acceSBarry Smith
3531c3339decSBarry Smith Collective
3532c7afd0dbSLois Curfman McInnes
35339b94acceSBarry Smith Input Parameter:
3534f6dfbefdSBarry Smith . snes - the `SNES` context
35359b94acceSBarry Smith
353636851e7fSLois Curfman McInnes Level: beginner
353736851e7fSLois Curfman McInnes
35381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35399b94acceSBarry Smith @*/
SNESDestroy(SNES * snes)3540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3541d71ae5a4SJacob Faibussowitsch {
354292e852f7SPablo Brubeck DM dm;
354392e852f7SPablo Brubeck
35443a40ed3dSBarry Smith PetscFunctionBegin;
35453ba16761SJacob Faibussowitsch if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3546f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3547f4f49eeaSPierre Jolivet if (--((PetscObject)*snes)->refct > 0) {
35489371c9d4SSatish Balay *snes = NULL;
35493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
35509371c9d4SSatish Balay }
3551d4bb536fSBarry Smith
3552f4f49eeaSPierre Jolivet PetscCall(SNESReset(*snes));
35539566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&(*snes)->npc));
35546b8b9a38SLisandro Dalcin
3555e04113cfSBarry Smith /* if memory was published with SAWs then destroy it */
35569566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3557f4f49eeaSPierre Jolivet PetscTryTypeMethod(*snes, destroy);
35586d4c513bSLisandro Dalcin
355992e852f7SPablo Brubeck dm = (*snes)->dm;
356092e852f7SPablo Brubeck while (dm) {
356192e852f7SPablo Brubeck PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
356292e852f7SPablo Brubeck PetscCall(DMGetCoarseDM(dm, &dm));
356392e852f7SPablo Brubeck }
356492e852f7SPablo Brubeck
35659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*snes)->dm));
35669566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&(*snes)->ksp));
35679566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35686b8b9a38SLisandro Dalcin
35699566063dSJacob Faibussowitsch PetscCall(PetscFree((*snes)->kspconvctx));
357012651944SBarry Smith if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP));
357148a46eb9SPierre Jolivet if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3572f4f49eeaSPierre Jolivet PetscCall(SNESMonitorCancel(*snes));
3573f4f49eeaSPierre Jolivet PetscCall(SNESConvergedReasonViewCancel(*snes));
35749566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(snes));
35753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
35769b94acceSBarry Smith }
35779b94acceSBarry Smith
35789b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35799b94acceSBarry Smith
3580a8054027SBarry Smith /*@
35810b4b7b1cSBarry Smith SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3582a8054027SBarry Smith
3583c3339decSBarry Smith Logically Collective
3584a8054027SBarry Smith
3585a8054027SBarry Smith Input Parameters:
3586f6dfbefdSBarry Smith + snes - the `SNES` context
3587d8e291bfSBarry Smith - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35883b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3589a8054027SBarry Smith
3590a8054027SBarry Smith Options Database Keys:
3591420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35923d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag
3593420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35943d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3595a8054027SBarry Smith
3596dc4c0fb0SBarry Smith Level: intermediate
3597dc4c0fb0SBarry Smith
3598420bcc1bSBarry Smith Notes:
3599a8054027SBarry Smith The default is 1
3600420bcc1bSBarry Smith
3601f6dfbefdSBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3602d8e291bfSBarry Smith
3603f6dfbefdSBarry Smith `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3604a8054027SBarry Smith
36053201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3606f6dfbefdSBarry Smith `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3607a8054027SBarry Smith @*/
SNESSetLagPreconditioner(SNES snes,PetscInt lag)3608d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3609d71ae5a4SJacob Faibussowitsch {
3610a8054027SBarry Smith PetscFunctionBegin;
36110700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36125f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36135f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3614c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2);
3615a8054027SBarry Smith snes->lagpreconditioner = lag;
36163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3617a8054027SBarry Smith }
3618a8054027SBarry Smith
3619efd51863SBarry Smith /*@
3620f6dfbefdSBarry Smith SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3621efd51863SBarry Smith
3622c3339decSBarry Smith Logically Collective
3623efd51863SBarry Smith
3624efd51863SBarry Smith Input Parameters:
3625f6dfbefdSBarry Smith + snes - the `SNES` context
3626efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3627efd51863SBarry Smith
3628f6dfbefdSBarry Smith Options Database Key:
362967b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3630efd51863SBarry Smith
3631efd51863SBarry Smith Level: intermediate
3632efd51863SBarry Smith
36330b4b7b1cSBarry Smith Notes:
36340b4b7b1cSBarry Smith Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36350b4b7b1cSBarry Smith
3636f6dfbefdSBarry Smith Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3637c0df2a02SJed Brown
36383201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
363954c05997SPierre Jolivet `SNESSetDM()`, `SNESSolve()`
3640efd51863SBarry Smith @*/
SNESSetGridSequence(SNES snes,PetscInt steps)3641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3642d71ae5a4SJacob Faibussowitsch {
3643efd51863SBarry Smith PetscFunctionBegin;
3644efd51863SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3645efd51863SBarry Smith PetscValidLogicalCollectiveInt(snes, steps, 2);
3646efd51863SBarry Smith snes->gridsequence = steps;
36473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3648efd51863SBarry Smith }
3649efd51863SBarry Smith
3650fa19ca70SBarry Smith /*@
3651f6dfbefdSBarry Smith SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3652fa19ca70SBarry Smith
3653c3339decSBarry Smith Logically Collective
3654fa19ca70SBarry Smith
3655fa19ca70SBarry Smith Input Parameter:
3656f6dfbefdSBarry Smith . snes - the `SNES` context
3657fa19ca70SBarry Smith
3658fa19ca70SBarry Smith Output Parameter:
3659fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3660fa19ca70SBarry Smith
3661fa19ca70SBarry Smith Level: intermediate
3662fa19ca70SBarry Smith
36633201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3664fa19ca70SBarry Smith @*/
SNESGetGridSequence(SNES snes,PetscInt * steps)3665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3666d71ae5a4SJacob Faibussowitsch {
3667fa19ca70SBarry Smith PetscFunctionBegin;
3668fa19ca70SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3669fa19ca70SBarry Smith *steps = snes->gridsequence;
36703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3671fa19ca70SBarry Smith }
3672fa19ca70SBarry Smith
3673a8054027SBarry Smith /*@
3674f6dfbefdSBarry Smith SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3675a8054027SBarry Smith
36763f9fe445SBarry Smith Not Collective
3677a8054027SBarry Smith
3678a8054027SBarry Smith Input Parameter:
3679f6dfbefdSBarry Smith . snes - the `SNES` context
3680a8054027SBarry Smith
3681a8054027SBarry Smith Output Parameter:
3682a8054027SBarry 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
36833b4f5425SBarry Smith the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3684a8054027SBarry Smith
3685dc4c0fb0SBarry Smith Level: intermediate
3686dc4c0fb0SBarry Smith
3687a8054027SBarry Smith Notes:
3688a8054027SBarry Smith The default is 1
3689f6dfbefdSBarry Smith
3690a8054027SBarry Smith The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3691a8054027SBarry Smith
36923201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3693a8054027SBarry Smith @*/
SNESGetLagPreconditioner(SNES snes,PetscInt * lag)3694d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3695d71ae5a4SJacob Faibussowitsch {
3696a8054027SBarry Smith PetscFunctionBegin;
36970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3698a8054027SBarry Smith *lag = snes->lagpreconditioner;
36993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3700a8054027SBarry Smith }
3701a8054027SBarry Smith
3702e35cf81dSBarry Smith /*@
3703f6dfbefdSBarry Smith SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3704e35cf81dSBarry Smith often the preconditioner is rebuilt.
3705e35cf81dSBarry Smith
3706c3339decSBarry Smith Logically Collective
3707e35cf81dSBarry Smith
3708e35cf81dSBarry Smith Input Parameters:
3709f6dfbefdSBarry Smith + snes - the `SNES` context
3710e35cf81dSBarry 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
3711fe3ffe1eSBarry Smith the Jacobian is built etc. -2 means rebuild at next chance but then never again
3712e35cf81dSBarry Smith
3713e35cf81dSBarry Smith Options Database Keys:
371479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
37153d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag
371679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37173d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3718e35cf81dSBarry Smith
3719dc4c0fb0SBarry Smith Level: intermediate
3720dc4c0fb0SBarry Smith
3721e35cf81dSBarry Smith Notes:
3722e35cf81dSBarry Smith The default is 1
3723f6dfbefdSBarry Smith
3724e35cf81dSBarry Smith The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3725f6dfbefdSBarry Smith
3726fe3ffe1eSBarry 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
3727fe3ffe1eSBarry Smith at the next Newton step but never again (unless it is reset to another value)
3728e35cf81dSBarry Smith
37293201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3730e35cf81dSBarry Smith @*/
SNESSetLagJacobian(SNES snes,PetscInt lag)3731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3732d71ae5a4SJacob Faibussowitsch {
3733e35cf81dSBarry Smith PetscFunctionBegin;
37340700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37355f80ce2aSJacob Faibussowitsch PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37365f80ce2aSJacob Faibussowitsch PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3737c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, lag, 2);
3738e35cf81dSBarry Smith snes->lagjacobian = lag;
37393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3740e35cf81dSBarry Smith }
3741e35cf81dSBarry Smith
3742e35cf81dSBarry Smith /*@
3743f6dfbefdSBarry Smith SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3744e35cf81dSBarry Smith
37453f9fe445SBarry Smith Not Collective
3746e35cf81dSBarry Smith
3747e35cf81dSBarry Smith Input Parameter:
3748f6dfbefdSBarry Smith . snes - the `SNES` context
3749e35cf81dSBarry Smith
3750e35cf81dSBarry Smith Output Parameter:
3751e35cf81dSBarry 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
3752e35cf81dSBarry Smith the Jacobian is built etc.
3753e35cf81dSBarry Smith
3754dc4c0fb0SBarry Smith Level: intermediate
3755dc4c0fb0SBarry Smith
3756e35cf81dSBarry Smith Notes:
3757e35cf81dSBarry Smith The default is 1
3758f6dfbefdSBarry Smith
3759f6dfbefdSBarry Smith The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3760e35cf81dSBarry Smith
37613201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3762e35cf81dSBarry Smith
3763e35cf81dSBarry Smith @*/
SNESGetLagJacobian(SNES snes,PetscInt * lag)3764d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3765d71ae5a4SJacob Faibussowitsch {
3766e35cf81dSBarry Smith PetscFunctionBegin;
37670700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3768e35cf81dSBarry Smith *lag = snes->lagjacobian;
37693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3770e35cf81dSBarry Smith }
3771e35cf81dSBarry Smith
377237ec4e1aSPeter Brune /*@
3773f6dfbefdSBarry Smith SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
377437ec4e1aSPeter Brune
3775c3339decSBarry Smith Logically collective
377637ec4e1aSPeter Brune
3777d8d19677SJose E. Roman Input Parameters:
3778f6dfbefdSBarry Smith + snes - the `SNES` context
37799d7e2deaSPeter Brune - flg - jacobian lagging persists if true
378037ec4e1aSPeter Brune
378137ec4e1aSPeter Brune Options Database Keys:
378279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
37833d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag
378479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37853d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
37863d5a8a6aSBarry Smith
3787dc4c0fb0SBarry Smith Level: advanced
3788dc4c0fb0SBarry Smith
378995452b02SPatrick Sanan Notes:
3790420bcc1bSBarry Smith Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3791f6dfbefdSBarry Smith
379295452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
379337ec4e1aSPeter Brune several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
379437ec4e1aSPeter Brune timesteps may present huge efficiency gains.
379537ec4e1aSPeter Brune
379642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
379737ec4e1aSPeter Brune @*/
SNESSetLagJacobianPersists(SNES snes,PetscBool flg)3798d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3799d71ae5a4SJacob Faibussowitsch {
380037ec4e1aSPeter Brune PetscFunctionBegin;
380137ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380237ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2);
380337ec4e1aSPeter Brune snes->lagjac_persist = flg;
38043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
380537ec4e1aSPeter Brune }
380637ec4e1aSPeter Brune
380737ec4e1aSPeter Brune /*@
3808d8e291bfSBarry Smith SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
380937ec4e1aSPeter Brune
3810c3339decSBarry Smith Logically Collective
381137ec4e1aSPeter Brune
3812d8d19677SJose E. Roman Input Parameters:
3813f6dfbefdSBarry Smith + snes - the `SNES` context
38149d7e2deaSPeter Brune - flg - preconditioner lagging persists if true
381537ec4e1aSPeter Brune
381637ec4e1aSPeter Brune Options Database Keys:
381779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
38183d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...> - sets the lag
381979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
38203d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...> - sets the lag
382137ec4e1aSPeter Brune
3822dc4c0fb0SBarry Smith Level: developer
3823dc4c0fb0SBarry Smith
382495452b02SPatrick Sanan Notes:
3825420bcc1bSBarry Smith Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3826f6dfbefdSBarry Smith
382795452b02SPatrick Sanan This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
382837ec4e1aSPeter Brune by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
382937ec4e1aSPeter Brune several timesteps may present huge efficiency gains.
383037ec4e1aSPeter Brune
38311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
383237ec4e1aSPeter Brune @*/
SNESSetLagPreconditionerPersists(SNES snes,PetscBool flg)3833d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3834d71ae5a4SJacob Faibussowitsch {
383537ec4e1aSPeter Brune PetscFunctionBegin;
383637ec4e1aSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
383737ec4e1aSPeter Brune PetscValidLogicalCollectiveBool(snes, flg, 2);
383837ec4e1aSPeter Brune snes->lagpre_persist = flg;
38393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
384037ec4e1aSPeter Brune }
384137ec4e1aSPeter Brune
38429b94acceSBarry Smith /*@
3843f6dfbefdSBarry Smith SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3844be5caee7SBarry Smith
3845c3339decSBarry Smith Logically Collective
3846be5caee7SBarry Smith
3847be5caee7SBarry Smith Input Parameters:
3848f6dfbefdSBarry Smith + snes - the `SNES` context
3849f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3850be5caee7SBarry Smith
3851f6dfbefdSBarry Smith Options Database Key:
3852be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3853be5caee7SBarry Smith
3854dc4c0fb0SBarry Smith Level: intermediate
3855dc4c0fb0SBarry Smith
3856f6dfbefdSBarry Smith Note:
3857f6dfbefdSBarry Smith This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3858be5caee7SBarry Smith
38593201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3860be5caee7SBarry Smith @*/
SNESSetForceIteration(SNES snes,PetscBool force)3861d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3862d71ae5a4SJacob Faibussowitsch {
3863be5caee7SBarry Smith PetscFunctionBegin;
3864be5caee7SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3865be5caee7SBarry Smith snes->forceiteration = force;
38663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3867be5caee7SBarry Smith }
3868be5caee7SBarry Smith
386985216dc7SFande Kong /*@
3870f6dfbefdSBarry Smith SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
387185216dc7SFande Kong
3872c3339decSBarry Smith Logically Collective
387385216dc7SFande Kong
38742fe279fdSBarry Smith Input Parameter:
3875f6dfbefdSBarry Smith . snes - the `SNES` context
387685216dc7SFande Kong
387785216dc7SFande Kong Output Parameter:
3878dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
387985216dc7SFande Kong
388006dd6b0eSSatish Balay Level: intermediate
388106dd6b0eSSatish Balay
38823201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
388385216dc7SFande Kong @*/
SNESGetForceIteration(SNES snes,PetscBool * force)3884d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3885d71ae5a4SJacob Faibussowitsch {
388685216dc7SFande Kong PetscFunctionBegin;
388785216dc7SFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
388885216dc7SFande Kong *force = snes->forceiteration;
38893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
389085216dc7SFande Kong }
3891be5caee7SBarry Smith
3892be5caee7SBarry Smith /*@
38930b4b7b1cSBarry Smith SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38949b94acceSBarry Smith
3895c3339decSBarry Smith Logically Collective
3896c7afd0dbSLois Curfman McInnes
38979b94acceSBarry Smith Input Parameters:
3898f6dfbefdSBarry Smith + snes - the `SNES` context
38990b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
39000b4b7b1cSBarry Smith . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
39015358d0d4SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x ||
39020b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed in the solver, default 50.
39030b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3904fee21e36SBarry Smith
390533174efeSLois Curfman McInnes Options Database Keys:
390677e5a1f9SBarry Smith + -snes_atol <abstol> - Sets `abstol`
390777e5a1f9SBarry Smith . -snes_rtol <rtol> - Sets `rtol`
390877e5a1f9SBarry Smith . -snes_stol <stol> - Sets `stol`
390977e5a1f9SBarry Smith . -snes_max_it <maxit> - Sets `maxit`
391077e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
39119b94acceSBarry Smith
391236851e7fSLois Curfman McInnes Level: intermediate
391336851e7fSLois Curfman McInnes
391477e5a1f9SBarry Smith Note:
391577e5a1f9SBarry Smith All parameters must be non-negative
391677e5a1f9SBarry Smith
391777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
391877e5a1f9SBarry Smith The default value is the value in the object when its type is set.
391977e5a1f9SBarry Smith
392077e5a1f9SBarry Smith Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
392177e5a1f9SBarry Smith
392277e5a1f9SBarry Smith Fortran Note:
392377e5a1f9SBarry Smith Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
392477e5a1f9SBarry Smith
39253201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
39269b94acceSBarry Smith @*/
SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf)3927d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3928d71ae5a4SJacob Faibussowitsch {
39293a40ed3dSBarry Smith PetscFunctionBegin;
39300700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3931c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, abstol, 2);
3932c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol, 3);
3933c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, stol, 4);
3934c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxit, 5);
3935c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, maxf, 6);
3936c5eb9154SBarry Smith
393777e5a1f9SBarry Smith if (abstol == (PetscReal)PETSC_DETERMINE) {
393877e5a1f9SBarry Smith snes->abstol = snes->default_abstol;
393977e5a1f9SBarry Smith } else if (abstol != (PetscReal)PETSC_CURRENT) {
39405f80ce2aSJacob Faibussowitsch PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3941ab54825eSJed Brown snes->abstol = abstol;
3942ab54825eSJed Brown }
394377e5a1f9SBarry Smith
394477e5a1f9SBarry Smith if (rtol == (PetscReal)PETSC_DETERMINE) {
394577e5a1f9SBarry Smith snes->rtol = snes->default_rtol;
394677e5a1f9SBarry Smith } else if (rtol != (PetscReal)PETSC_CURRENT) {
39475f80ce2aSJacob 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);
3948ab54825eSJed Brown snes->rtol = rtol;
3949ab54825eSJed Brown }
395077e5a1f9SBarry Smith
395177e5a1f9SBarry Smith if (stol == (PetscReal)PETSC_DETERMINE) {
395277e5a1f9SBarry Smith snes->stol = snes->default_stol;
395377e5a1f9SBarry Smith } else if (stol != (PetscReal)PETSC_CURRENT) {
39545f80ce2aSJacob Faibussowitsch PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3955c60f73f4SPeter Brune snes->stol = stol;
3956ab54825eSJed Brown }
395777e5a1f9SBarry Smith
3958835f2295SStefano Zampini if (maxit == PETSC_DETERMINE) {
395977e5a1f9SBarry Smith snes->max_its = snes->default_max_its;
3960835f2295SStefano Zampini } else if (maxit == PETSC_UNLIMITED) {
396177e5a1f9SBarry Smith snes->max_its = PETSC_INT_MAX;
396277e5a1f9SBarry Smith } else if (maxit != PETSC_CURRENT) {
396363a3b9bcSJacob Faibussowitsch PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3964ab54825eSJed Brown snes->max_its = maxit;
3965ab54825eSJed Brown }
396677e5a1f9SBarry Smith
3967835f2295SStefano Zampini if (maxf == PETSC_DETERMINE) {
396877e5a1f9SBarry Smith snes->max_funcs = snes->default_max_funcs;
3969835f2295SStefano Zampini } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
397077e5a1f9SBarry Smith snes->max_funcs = PETSC_UNLIMITED;
397177e5a1f9SBarry Smith } else if (maxf != PETSC_CURRENT) {
397277e5a1f9SBarry Smith PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3973ab54825eSJed Brown snes->max_funcs = maxf;
3974ab54825eSJed Brown }
39753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
39769b94acceSBarry Smith }
39779b94acceSBarry Smith
3978e4d06f11SPatrick Farrell /*@
3979f6dfbefdSBarry Smith SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3980e4d06f11SPatrick Farrell
3981c3339decSBarry Smith Logically Collective
3982e4d06f11SPatrick Farrell
3983e4d06f11SPatrick Farrell Input Parameters:
3984f6dfbefdSBarry Smith + snes - the `SNES` context
39850b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver
39860b4b7b1cSBarry Smith is stopped due to divergence.
3987e4d06f11SPatrick Farrell
3988f6dfbefdSBarry Smith Options Database Key:
3989dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3990e4d06f11SPatrick Farrell
3991e4d06f11SPatrick Farrell Level: intermediate
3992e4d06f11SPatrick Farrell
399377e5a1f9SBarry Smith Notes:
399477e5a1f9SBarry Smith Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3995e5cd489fSStefano Zampini
399677e5a1f9SBarry Smith Fortran Note:
399777e5a1f9SBarry Smith Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
399877e5a1f9SBarry Smith
399977e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
4000e4d06f11SPatrick Farrell @*/
SNESSetDivergenceTolerance(SNES snes,PetscReal divtol)4001d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
4002d71ae5a4SJacob Faibussowitsch {
4003e4d06f11SPatrick Farrell PetscFunctionBegin;
4004e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4005e4d06f11SPatrick Farrell PetscValidLogicalCollectiveReal(snes, divtol, 2);
400677e5a1f9SBarry Smith
400777e5a1f9SBarry Smith if (divtol == (PetscReal)PETSC_DETERMINE) {
400877e5a1f9SBarry Smith snes->divtol = snes->default_divtol;
400977e5a1f9SBarry Smith } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
401077e5a1f9SBarry Smith snes->divtol = PETSC_UNLIMITED;
401177e5a1f9SBarry Smith } else if (divtol != (PetscReal)PETSC_CURRENT) {
401277e5a1f9SBarry Smith PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
401377e5a1f9SBarry Smith snes->divtol = divtol;
401477e5a1f9SBarry Smith }
40153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4016e4d06f11SPatrick Farrell }
4017e4d06f11SPatrick Farrell
40189b94acceSBarry Smith /*@
40190b4b7b1cSBarry Smith SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
402033174efeSLois Curfman McInnes
4021c7afd0dbSLois Curfman McInnes Not Collective
4022c7afd0dbSLois Curfman McInnes
402377e5a1f9SBarry Smith Input Parameter:
402477e5a1f9SBarry Smith . snes - the `SNES` context
402577e5a1f9SBarry Smith
402677e5a1f9SBarry Smith Output Parameters:
40270b4b7b1cSBarry Smith + atol - the absolute convergence tolerance
40280b4b7b1cSBarry Smith . rtol - the relative convergence tolerance
402977e5a1f9SBarry Smith . stol - convergence tolerance in terms of the norm of the change in the solution between steps
40300b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
40310b4b7b1cSBarry Smith - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4032fee21e36SBarry Smith
403336851e7fSLois Curfman McInnes Level: intermediate
403436851e7fSLois Curfman McInnes
40350b4b7b1cSBarry Smith Notes:
40360b4b7b1cSBarry Smith See `SNESSetTolerances()` for details on the parameters.
40370b4b7b1cSBarry Smith
4038dc4c0fb0SBarry Smith The user can specify `NULL` for any parameter that is not needed.
4039dc4c0fb0SBarry Smith
40401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
404133174efeSLois Curfman McInnes @*/
SNESGetTolerances(SNES snes,PetscReal * atol,PetscReal * rtol,PetscReal * stol,PetscInt * maxit,PetscInt * maxf)4042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4043d71ae5a4SJacob Faibussowitsch {
40443a40ed3dSBarry Smith PetscFunctionBegin;
40450700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
404685385478SLisandro Dalcin if (atol) *atol = snes->abstol;
404733174efeSLois Curfman McInnes if (rtol) *rtol = snes->rtol;
4048c60f73f4SPeter Brune if (stol) *stol = snes->stol;
404933174efeSLois Curfman McInnes if (maxit) *maxit = snes->max_its;
405033174efeSLois Curfman McInnes if (maxf) *maxf = snes->max_funcs;
40513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
405233174efeSLois Curfman McInnes }
405333174efeSLois Curfman McInnes
4054e4d06f11SPatrick Farrell /*@
4055e4d06f11SPatrick Farrell SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4056e4d06f11SPatrick Farrell
4057e4d06f11SPatrick Farrell Not Collective
4058e4d06f11SPatrick Farrell
4059e4d06f11SPatrick Farrell Input Parameters:
4060f6dfbefdSBarry Smith + snes - the `SNES` context
4061e4d06f11SPatrick Farrell - divtol - divergence tolerance
4062e4d06f11SPatrick Farrell
4063e4d06f11SPatrick Farrell Level: intermediate
4064e4d06f11SPatrick Farrell
40651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4066e4d06f11SPatrick Farrell @*/
SNESGetDivergenceTolerance(SNES snes,PetscReal * divtol)4067d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4068d71ae5a4SJacob Faibussowitsch {
4069e4d06f11SPatrick Farrell PetscFunctionBegin;
4070e4d06f11SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4071e4d06f11SPatrick Farrell if (divtol) *divtol = snes->divtol;
40723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4073e4d06f11SPatrick Farrell }
4074e4d06f11SPatrick Farrell
40756ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40766ba87a44SLisandro Dalcin
SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void * monctx)4077d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4078d71ae5a4SJacob Faibussowitsch {
4079b271bb04SBarry Smith PetscDrawLG lg;
4080b271bb04SBarry Smith PetscReal x, y, per;
4081b271bb04SBarry Smith PetscViewer v = (PetscViewer)monctx;
4082b271bb04SBarry Smith static PetscReal prev; /* should be in the context */
4083b271bb04SBarry Smith PetscDraw draw;
4084b271bb04SBarry Smith
4085459f5d12SBarry Smith PetscFunctionBegin;
40864d4332d5SBarry Smith PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40879566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40889566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg));
40899566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw));
40909566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4091b271bb04SBarry Smith x = (PetscReal)n;
409277b4d14cSPeter Brune if (rnorm > 0.0) y = PetscLog10Real(rnorm);
409394c9c6d3SKarl Rupp else y = -15.0;
40949566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40956934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) {
40969566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg));
40979566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg));
4098b271bb04SBarry Smith }
4099b271bb04SBarry Smith
41009566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
41019566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg));
41029566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw));
4103aaa8cc7dSPierre Jolivet PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
41049566063dSJacob Faibussowitsch PetscCall(SNESMonitorRange_Private(snes, n, &per));
4105b271bb04SBarry Smith x = (PetscReal)n;
4106b271bb04SBarry Smith y = 100.0 * per;
41079566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41086934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) {
41099566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg));
41109566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg));
4111b271bb04SBarry Smith }
4112b271bb04SBarry Smith
41139566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
41149371c9d4SSatish Balay if (!n) {
41159371c9d4SSatish Balay prev = rnorm;
41169371c9d4SSatish Balay PetscCall(PetscDrawLGReset(lg));
41179371c9d4SSatish Balay }
41189566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw));
41199566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4120b271bb04SBarry Smith x = (PetscReal)n;
4121b271bb04SBarry Smith y = (prev - rnorm) / prev;
41229566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41236934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) {
41249566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg));
41259566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg));
4126b271bb04SBarry Smith }
4127b271bb04SBarry Smith
41289566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
41299566063dSJacob Faibussowitsch if (!n) PetscCall(PetscDrawLGReset(lg));
41309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGGetDraw(lg, &draw));
41319566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4132b271bb04SBarry Smith x = (PetscReal)n;
4133b271bb04SBarry Smith y = (prev - rnorm) / (prev * per);
4134b271bb04SBarry Smith if (n > 2) { /*skip initial crazy value */
41359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4136b271bb04SBarry Smith }
41376934998bSLisandro Dalcin if (n < 20 || !(n % 5) || snes->reason) {
41389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg));
41399566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSave(lg));
4140b271bb04SBarry Smith }
4141b271bb04SBarry Smith prev = rnorm;
41423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4143b271bb04SBarry Smith }
4144b271bb04SBarry Smith
4145228d79bcSJed Brown /*@
41462d157150SStefano Zampini SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41472d157150SStefano Zampini
41482d157150SStefano Zampini Collective
41492d157150SStefano Zampini
41502d157150SStefano Zampini Input Parameters:
41512d157150SStefano Zampini + snes - the `SNES` context
41522d157150SStefano Zampini . it - current iteration
41532d157150SStefano Zampini . xnorm - 2-norm of current iterate
41542d157150SStefano Zampini . snorm - 2-norm of current step
41552d157150SStefano Zampini - fnorm - 2-norm of function
41562d157150SStefano Zampini
41572d157150SStefano Zampini Level: developer
41582d157150SStefano Zampini
41592d157150SStefano Zampini Note:
4160420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations.
41612d157150SStefano Zampini It does not typically need to be called by the user.
41622d157150SStefano Zampini
4163c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41642d157150SStefano Zampini @*/
SNESConverged(SNES snes,PetscInt it,PetscReal xnorm,PetscReal snorm,PetscReal fnorm)41652d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41662d157150SStefano Zampini {
41672d157150SStefano Zampini PetscFunctionBegin;
41682d157150SStefano Zampini if (!snes->reason) {
41692d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41702d157150SStefano Zampini if (it == snes->max_its && !snes->reason) {
41712d157150SStefano Zampini if (snes->normschedule == SNES_NORM_ALWAYS) {
41722d157150SStefano Zampini PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41732d157150SStefano Zampini snes->reason = SNES_DIVERGED_MAX_IT;
41742d157150SStefano Zampini } else snes->reason = SNES_CONVERGED_ITS;
41752d157150SStefano Zampini }
41762d157150SStefano Zampini }
41772d157150SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
41782d157150SStefano Zampini }
41792d157150SStefano Zampini
41802d157150SStefano Zampini /*@
41810b4b7b1cSBarry Smith SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4182228d79bcSJed Brown
4183c3339decSBarry Smith Collective
4184228d79bcSJed Brown
4185228d79bcSJed Brown Input Parameters:
4186f6dfbefdSBarry Smith + snes - nonlinear solver context obtained from `SNESCreate()`
41870b4b7b1cSBarry Smith . iter - current iteration number
41880b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4189228d79bcSJed Brown
4190dc4c0fb0SBarry Smith Level: developer
4191dc4c0fb0SBarry Smith
4192f6dfbefdSBarry Smith Note:
4193420bcc1bSBarry Smith This routine is called by the `SNESSolve()` implementations.
4194228d79bcSJed Brown It does not typically need to be called by the user.
4195228d79bcSJed Brown
41961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4197228d79bcSJed Brown @*/
SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm)4198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4199d71ae5a4SJacob Faibussowitsch {
42007a03ce2fSLisandro Dalcin PetscInt i, n = snes->numbermonitors;
42017a03ce2fSLisandro Dalcin
42027a03ce2fSLisandro Dalcin PetscFunctionBegin;
42039566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(snes->vec_sol));
420448a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
42059566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(snes->vec_sol));
42063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42077a03ce2fSLisandro Dalcin }
42087a03ce2fSLisandro Dalcin
42099b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
42109b94acceSBarry Smith
4211bf388a1fSBarry Smith /*MC
4212f6dfbefdSBarry Smith SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4213bf388a1fSBarry Smith
4214bf388a1fSBarry Smith Synopsis:
4215aaa7dc30SBarry Smith #include <petscsnes.h>
421637fdd005SBarry Smith PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4217bf388a1fSBarry Smith
4218c3339decSBarry Smith Collective
42191843f636SBarry Smith
42201843f636SBarry Smith Input Parameters:
4221f6dfbefdSBarry Smith + snes - the `SNES` context
4222bf388a1fSBarry Smith . its - iteration number
4223bf388a1fSBarry Smith . norm - 2-norm function value (may be estimated)
4224bf388a1fSBarry Smith - mctx - [optional] monitoring context
4225bf388a1fSBarry Smith
4226878cb397SSatish Balay Level: advanced
4227878cb397SSatish Balay
422856296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()`
4229bf388a1fSBarry Smith M*/
4230bf388a1fSBarry Smith
42319b94acceSBarry Smith /*@C
4232a6570f20SBarry Smith SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42330b4b7b1cSBarry Smith iteration of the `SNES` nonlinear solver to display the iteration's
42349b94acceSBarry Smith progress.
42359b94acceSBarry Smith
4236c3339decSBarry Smith Logically Collective
4237fee21e36SBarry Smith
4238c7afd0dbSLois Curfman McInnes Input Parameters:
4239f6dfbefdSBarry Smith + snes - the `SNES` context
424020f4b53cSBarry Smith . f - the monitor function, for the calling sequence see `SNESMonitorFunction`
4241420bcc1bSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
424249abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42439b94acceSBarry Smith
42449665c990SLois Curfman McInnes Options Database Keys:
4245f6dfbefdSBarry Smith + -snes_monitor - sets `SNESMonitorDefault()`
4246798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4247dc4c0fb0SBarry 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
4248c7afd0dbSLois Curfman McInnes the options database.
42499665c990SLois Curfman McInnes
4250dc4c0fb0SBarry Smith Level: intermediate
4251dc4c0fb0SBarry Smith
4252f6dfbefdSBarry Smith Note:
42536bc08f3fSLois Curfman McInnes Several different monitoring routines may be set by calling
4254f6dfbefdSBarry Smith `SNESMonitorSet()` multiple times; all will be called in the
42556bc08f3fSLois Curfman McInnes order in which they were set.
4256639f9d9dSBarry Smith
4257420bcc1bSBarry Smith Fortran Note:
4258f6dfbefdSBarry Smith Only a single monitor function can be set for each `SNES` object
4259025f1a04SBarry Smith
426049abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42619b94acceSBarry Smith @*/
SNESMonitorSet(SNES snes,PetscErrorCode (* f)(SNES,PetscInt,PetscReal,PetscCtx),PetscCtx mctx,PetscCtxDestroyFn * monitordestroy)42622a8381b2SBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, PetscCtx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
4263d71ae5a4SJacob Faibussowitsch {
42643a40ed3dSBarry Smith PetscFunctionBegin;
42650700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4266453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numbermonitors; i++) {
4267453a69bbSBarry Smith PetscBool identical;
4268453a69bbSBarry Smith
4269453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42703ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4271649052a6SBarry Smith }
42725f80ce2aSJacob Faibussowitsch PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42736e4dcb14SBarry Smith snes->monitor[snes->numbermonitors] = f;
4274b8a78c4aSBarry Smith snes->monitordestroy[snes->numbermonitors] = monitordestroy;
4275835f2295SStefano Zampini snes->monitorcontext[snes->numbermonitors++] = mctx;
42763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42779b94acceSBarry Smith }
42789b94acceSBarry Smith
4279a278d85bSSatish Balay /*@
4280f6dfbefdSBarry Smith SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42815cd90555SBarry Smith
4282c3339decSBarry Smith Logically Collective
4283c7afd0dbSLois Curfman McInnes
42842fe279fdSBarry Smith Input Parameter:
4285f6dfbefdSBarry Smith . snes - the `SNES` context
42865cd90555SBarry Smith
42871a480d89SAdministrator Options Database Key:
4288a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4289dc4c0fb0SBarry Smith into a code by calls to `SNESMonitorSet()`, but does not cancel those
4290c7afd0dbSLois Curfman McInnes set via the options database
42915cd90555SBarry Smith
4292dc4c0fb0SBarry Smith Level: intermediate
4293dc4c0fb0SBarry Smith
4294f6dfbefdSBarry Smith Note:
4295f6dfbefdSBarry Smith There is no way to clear one specific monitor from a `SNES` object.
42965cd90555SBarry Smith
429756296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42985cd90555SBarry Smith @*/
SNESMonitorCancel(SNES snes)4299d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4300d71ae5a4SJacob Faibussowitsch {
4301d952e501SBarry Smith PetscInt i;
4302d952e501SBarry Smith
43035cd90555SBarry Smith PetscFunctionBegin;
43040700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4305d952e501SBarry Smith for (i = 0; i < snes->numbermonitors; i++) {
430648a46eb9SPierre Jolivet if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4307d952e501SBarry Smith }
43085cd90555SBarry Smith snes->numbermonitors = 0;
43093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43105cd90555SBarry Smith }
43115cd90555SBarry Smith
4312bf388a1fSBarry Smith /*MC
4313bf388a1fSBarry Smith SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4314bf388a1fSBarry Smith
4315bf388a1fSBarry Smith Synopsis:
4316aaa7dc30SBarry Smith #include <petscsnes.h>
431737fdd005SBarry Smith PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4318bf388a1fSBarry Smith
4319c3339decSBarry Smith Collective
43201843f636SBarry Smith
43211843f636SBarry Smith Input Parameters:
4322f6dfbefdSBarry Smith + snes - the `SNES` context
4323bf388a1fSBarry Smith . it - current iteration (0 is the first and is before any Newton step)
4324bf388a1fSBarry Smith . xnorm - 2-norm of current iterate
4325bf388a1fSBarry Smith . gnorm - 2-norm of current step
43261843f636SBarry Smith . f - 2-norm of function
43271843f636SBarry Smith - cctx - [optional] convergence context
43281843f636SBarry Smith
43291843f636SBarry Smith Output Parameter:
43301843f636SBarry Smith . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4331bf388a1fSBarry Smith
4332878cb397SSatish Balay Level: intermediate
4333bf388a1fSBarry Smith
4334c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4335bf388a1fSBarry Smith M*/
4336bf388a1fSBarry Smith
43379b94acceSBarry Smith /*@C
43389b94acceSBarry Smith SNESSetConvergenceTest - Sets the function that is to be used
43399b94acceSBarry Smith to test for convergence of the nonlinear iterative solution.
43409b94acceSBarry Smith
4341c3339decSBarry Smith Logically Collective
4342fee21e36SBarry Smith
4343c7afd0dbSLois Curfman McInnes Input Parameters:
4344f6dfbefdSBarry Smith + snes - the `SNES` context
4345e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
43462a8381b2SBarry Smith . ctx - [optional] context for private data for the convergence routine (may be `NULL`)
4347dc4c0fb0SBarry Smith - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43489b94acceSBarry Smith
434936851e7fSLois Curfman McInnes Level: advanced
435036851e7fSLois Curfman McInnes
43511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43529b94acceSBarry Smith @*/
SNESSetConvergenceTest(SNES snes,PetscErrorCode (* SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason *,void *),PetscCtx ctx,PetscCtxDestroyFn * destroy)43532a8381b2SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), PetscCtx ctx, PetscCtxDestroyFn *destroy)
4354d71ae5a4SJacob Faibussowitsch {
43553a40ed3dSBarry Smith PetscFunctionBegin;
43560700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4357e2a6519dSDmitry Karpeev if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
435812651944SBarry Smith if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP));
4359bf388a1fSBarry Smith snes->ops->converged = SNESConvergenceTestFunction;
43607f7931b9SBarry Smith snes->ops->convergeddestroy = destroy;
43612a8381b2SBarry Smith snes->cnvP = ctx;
43623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43639b94acceSBarry Smith }
43649b94acceSBarry Smith
436552baeb72SSatish Balay /*@
43660b4b7b1cSBarry Smith SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4367184914b5SBarry Smith
4368184914b5SBarry Smith Not Collective
4369184914b5SBarry Smith
4370184914b5SBarry Smith Input Parameter:
4371f6dfbefdSBarry Smith . snes - the `SNES` context
4372184914b5SBarry Smith
4373184914b5SBarry Smith Output Parameter:
4374f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4375184914b5SBarry Smith
4376f6dfbefdSBarry Smith Options Database Key:
43776a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43786a4d7782SBarry Smith
4379184914b5SBarry Smith Level: intermediate
4380184914b5SBarry Smith
4381f6dfbefdSBarry Smith Note:
4382f6dfbefdSBarry Smith Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4383184914b5SBarry Smith
43841cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4385184914b5SBarry Smith @*/
SNESGetConvergedReason(SNES snes,SNESConvergedReason * reason)4386d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4387d71ae5a4SJacob Faibussowitsch {
4388184914b5SBarry Smith PetscFunctionBegin;
43890700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43904f572ea9SToby Isaac PetscAssertPointer(reason, 2);
4391184914b5SBarry Smith *reason = snes->reason;
43923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4393184914b5SBarry Smith }
4394184914b5SBarry Smith
4395c4421ceaSFande Kong /*@C
4396f6dfbefdSBarry Smith SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4397c4421ceaSFande Kong
4398c4421ceaSFande Kong Not Collective
4399c4421ceaSFande Kong
4400c4421ceaSFande Kong Input Parameter:
4401f6dfbefdSBarry Smith . snes - the `SNES` context
4402c4421ceaSFande Kong
4403c4421ceaSFande Kong Output Parameter:
4404dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4405c4421ceaSFande Kong
440699c90e12SSatish Balay Level: beginner
4407c4421ceaSFande Kong
44081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4409c4421ceaSFande Kong @*/
SNESGetConvergedReasonString(SNES snes,const char ** strreason)4410d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4411d71ae5a4SJacob Faibussowitsch {
4412c4421ceaSFande Kong PetscFunctionBegin;
4413c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44144f572ea9SToby Isaac PetscAssertPointer(strreason, 2);
4415c4421ceaSFande Kong *strreason = SNESConvergedReasons[snes->reason];
44163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4417c4421ceaSFande Kong }
4418c4421ceaSFande Kong
441933866048SMatthew G. Knepley /*@
4420f6dfbefdSBarry Smith SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
442133866048SMatthew G. Knepley
442233866048SMatthew G. Knepley Not Collective
442333866048SMatthew G. Knepley
442433866048SMatthew G. Knepley Input Parameters:
4425f6dfbefdSBarry Smith + snes - the `SNES` context
4426f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
442733866048SMatthew G. Knepley manual pages for the individual convergence tests for complete lists
442833866048SMatthew G. Knepley
4429f6dfbefdSBarry Smith Level: developer
4430f6dfbefdSBarry Smith
4431420bcc1bSBarry Smith Developer Note:
4432f6dfbefdSBarry Smith Called inside the various `SNESSolve()` implementations
443333866048SMatthew G. Knepley
44341cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
443533866048SMatthew G. Knepley @*/
SNESSetConvergedReason(SNES snes,SNESConvergedReason reason)4436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4437d71ae5a4SJacob Faibussowitsch {
443833866048SMatthew G. Knepley PetscFunctionBegin;
443933866048SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44405f3c5e7aSBarry Smith PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
444133866048SMatthew G. Knepley snes->reason = reason;
44423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
444333866048SMatthew G. Knepley }
444433866048SMatthew G. Knepley
4445c9005455SLois Curfman McInnes /*@
4446420bcc1bSBarry Smith SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4447c9005455SLois Curfman McInnes
4448c3339decSBarry Smith Logically Collective
4449fee21e36SBarry Smith
4450c7afd0dbSLois Curfman McInnes Input Parameters:
4451f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
44528c7482ecSBarry Smith . a - array to hold history, this array will contain the function norms computed at each step
4453cd5578b5SBarry Smith . its - integer array holds the number of linear iterations for each solve.
4454420bcc1bSBarry Smith . na - size of `a` and `its`
4455f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4456758f92a0SBarry Smith else it continues storing new values for new nonlinear solves after the old ones
4457c7afd0dbSLois Curfman McInnes
4458dc4c0fb0SBarry Smith Level: intermediate
4459dc4c0fb0SBarry Smith
4460308dcc3eSBarry Smith Notes:
4461ce78bad3SBarry Smith If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a
446277e5a1f9SBarry Smith default array of length 1,000 is allocated.
4463308dcc3eSBarry Smith
4464c9005455SLois Curfman McInnes This routine is useful, e.g., when running a code for purposes
4465c9005455SLois Curfman McInnes of accurate performance monitoring, when no I/O should be done
4466c9005455SLois Curfman McInnes during the section of code that is being timed.
4467c9005455SLois Curfman McInnes
4468420bcc1bSBarry Smith If the arrays run out of space after a number of iterations then the later values are not saved in the history
4469420bcc1bSBarry Smith
44701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4471c9005455SLois Curfman McInnes @*/
SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset)4472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4473d71ae5a4SJacob Faibussowitsch {
44743a40ed3dSBarry Smith PetscFunctionBegin;
44750700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44764f572ea9SToby Isaac if (a) PetscAssertPointer(a, 2);
44774f572ea9SToby Isaac if (its) PetscAssertPointer(its, 3);
44787a1ec6d4SBarry Smith if (!a) {
447977e5a1f9SBarry Smith if (na == PETSC_DECIDE) na = 1000;
44809566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(na, &a, na, &its));
4481071fcb05SBarry Smith snes->conv_hist_alloc = PETSC_TRUE;
4482308dcc3eSBarry Smith }
4483c9005455SLois Curfman McInnes snes->conv_hist = a;
4484758f92a0SBarry Smith snes->conv_hist_its = its;
4485115dd874SBarry Smith snes->conv_hist_max = (size_t)na;
4486a12bc48fSLisandro Dalcin snes->conv_hist_len = 0;
4487758f92a0SBarry Smith snes->conv_hist_reset = reset;
44883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4489758f92a0SBarry Smith }
4490758f92a0SBarry Smith
4491d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4492c6db04a5SJed Brown #include <engine.h> /* MATLAB include file */
4493c6db04a5SJed Brown #include <mex.h> /* MATLAB include file */
449499e0435eSBarry Smith
SNESGetConvergenceHistoryMatlab(SNES snes)4495d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4496d71ae5a4SJacob Faibussowitsch {
4497308dcc3eSBarry Smith mxArray *mat;
4498308dcc3eSBarry Smith PetscInt i;
4499308dcc3eSBarry Smith PetscReal *ar;
4500308dcc3eSBarry Smith
4501308dcc3eSBarry Smith mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4502308dcc3eSBarry Smith ar = (PetscReal *)mxGetData(mat);
4503f5af7f23SKarl Rupp for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
450411cc89d2SBarry Smith return mat;
4505308dcc3eSBarry Smith }
4506308dcc3eSBarry Smith #endif
4507308dcc3eSBarry Smith
45080c4c9dddSBarry Smith /*@C
4509420bcc1bSBarry Smith SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4510758f92a0SBarry Smith
45113f9fe445SBarry Smith Not Collective
4512758f92a0SBarry Smith
4513758f92a0SBarry Smith Input Parameter:
4514f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4515758f92a0SBarry Smith
4516758f92a0SBarry Smith Output Parameters:
4517f6dfbefdSBarry Smith + a - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4518758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4519758f92a0SBarry Smith negative if not converged) for each solve.
452020f4b53cSBarry Smith - na - size of `a` and `its`
4521758f92a0SBarry Smith
4522dc4c0fb0SBarry Smith Level: intermediate
4523dc4c0fb0SBarry Smith
452420f4b53cSBarry Smith Note:
452520f4b53cSBarry Smith This routine is useful, e.g., when running a code for purposes
452620f4b53cSBarry Smith of accurate performance monitoring, when no I/O should be done
452720f4b53cSBarry Smith during the section of code that is being timed.
452820f4b53cSBarry Smith
4529ce78bad3SBarry Smith Fortran Notes:
4530ce78bad3SBarry Smith Return the arrays with ``SNESRestoreConvergenceHistory()`
4531ce78bad3SBarry Smith
4532ce78bad3SBarry Smith Use the arguments
4533dc4c0fb0SBarry Smith .vb
4534ce78bad3SBarry Smith PetscReal, pointer :: a(:)
4535ce78bad3SBarry Smith PetscInt, pointer :: its(:)
4536dc4c0fb0SBarry Smith .ve
4537758f92a0SBarry Smith
45381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4539758f92a0SBarry Smith @*/
SNESGetConvergenceHistory(SNES snes,PetscReal * a[],PetscInt * its[],PetscInt * na)4540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4541d71ae5a4SJacob Faibussowitsch {
4542758f92a0SBarry Smith PetscFunctionBegin;
45430700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4544758f92a0SBarry Smith if (a) *a = snes->conv_hist;
4545758f92a0SBarry Smith if (its) *its = snes->conv_hist_its;
4546115dd874SBarry Smith if (na) *na = (PetscInt)snes->conv_hist_len;
45473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4548c9005455SLois Curfman McInnes }
4549c9005455SLois Curfman McInnes
4550ac226902SBarry Smith /*@C
455176b2cf59SMatthew Knepley SNESSetUpdate - Sets the general-purpose update function called
4552eec8f646SJed Brown at the beginning of every iteration of the nonlinear solve. Specifically
455353e5d35bSStefano Zampini it is called just before the Jacobian is "evaluated" and after the function
455453e5d35bSStefano Zampini evaluation.
455576b2cf59SMatthew Knepley
4556c3339decSBarry Smith Logically Collective
455776b2cf59SMatthew Knepley
455876b2cf59SMatthew Knepley Input Parameters:
4559a2b725a8SWilliam Gropp + snes - The nonlinear solver context
456053e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
456176b2cf59SMatthew Knepley
4562fe97e370SBarry Smith Level: advanced
4563fe97e370SBarry Smith
4564420bcc1bSBarry Smith Notes:
4565f6dfbefdSBarry 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
4566f6dfbefdSBarry Smith to `SNESSetFunction()`, or `SNESSetPicard()`
456753e5d35bSStefano Zampini This is not used by most users, and it is intended to provide a general hook that is run
456853e5d35bSStefano Zampini right before the direction step is computed.
4569ce78bad3SBarry Smith
457053e5d35bSStefano Zampini Users are free to modify the current residual vector,
457153e5d35bSStefano Zampini the current linearization point, or any other vector associated to the specific solver used.
457253e5d35bSStefano Zampini If such modifications take place, it is the user responsibility to update all the relevant
4573ce78bad3SBarry Smith vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4574ce78bad3SBarry Smith .vb
4575ce78bad3SBarry Smith PetscErrorCode update(SNES snes, PetscInt iteration)
4576ce78bad3SBarry Smith {
4577ce78bad3SBarry Smith PetscFunctionBeginUser;
4578ce78bad3SBarry Smith if (iteration > 0) {
4579ce78bad3SBarry Smith // update the model parameters here
4580ce78bad3SBarry Smith Vec x,f;
4581ce78bad3SBarry Smith PetscCall(SNESGetSolution(snes,&x));
4582ce78bad3SBarry Smith PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4583ce78bad3SBarry Smith PetscCall(SNESComputeFunction(snes,x,f));
4584ce78bad3SBarry Smith }
4585ce78bad3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS);
4586ce78bad3SBarry Smith }
4587ce78bad3SBarry Smith .ve
458876b2cf59SMatthew Knepley
4589aaa8cc7dSPierre 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.
45906b7fb656SBarry Smith
4591e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
459253e5d35bSStefano Zampini `SNESMonitorSet()`
459376b2cf59SMatthew Knepley @*/
SNESSetUpdate(SNES snes,SNESUpdateFn * func)459453e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4595d71ae5a4SJacob Faibussowitsch {
459676b2cf59SMatthew Knepley PetscFunctionBegin;
45970700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4598e7788613SBarry Smith snes->ops->update = func;
45993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
460076b2cf59SMatthew Knepley }
460176b2cf59SMatthew Knepley
4602ffeef943SBarry Smith /*@
4603f6dfbefdSBarry Smith SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
46042a359c20SBarry Smith
4605c3339decSBarry Smith Collective
46062a359c20SBarry Smith
4607e4094ef1SJacob Faibussowitsch Input Parameters:
4608f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
46092a359c20SBarry Smith - viewer - the viewer to display the reason
46102a359c20SBarry Smith
46112a359c20SBarry Smith Options Database Keys:
4612ee300463SSatish Balay + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4613ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4614eafd5ff0SAlex Lindsay
4615420bcc1bSBarry Smith Level: beginner
4616420bcc1bSBarry Smith
4617f6dfbefdSBarry Smith Note:
4618f6dfbefdSBarry Smith To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4619f6dfbefdSBarry Smith use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
46202a359c20SBarry Smith
46211cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4622f6dfbefdSBarry Smith `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4623f6dfbefdSBarry Smith `SNESConvergedReasonViewFromOptions()`,
4624db781477SPatrick Sanan `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
46252a359c20SBarry Smith @*/
SNESConvergedReasonView(SNES snes,PetscViewer viewer)4626d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4627d71ae5a4SJacob Faibussowitsch {
462875cca76cSMatthew G. Knepley PetscViewerFormat format;
46292a359c20SBarry Smith PetscBool isAscii;
46302a359c20SBarry Smith
46312a359c20SBarry Smith PetscFunctionBegin;
463219a666eeSBarry Smith if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46342a359c20SBarry Smith if (isAscii) {
46359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format));
463665bf60d2SBarry Smith PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
463775cca76cSMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
463875cca76cSMatthew G. Knepley DM dm;
463975cca76cSMatthew G. Knepley Vec u;
464075cca76cSMatthew G. Knepley PetscDS prob;
464175cca76cSMatthew G. Knepley PetscInt Nf, f;
464295cbbfd3SMatthew G. Knepley PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
464395cbbfd3SMatthew G. Knepley void **exactCtx;
464475cca76cSMatthew G. Knepley PetscReal error;
464575cca76cSMatthew G. Knepley
46469566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
46479566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u));
46489566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
46499566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
46509566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46519566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46529566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46539566063dSJacob Faibussowitsch PetscCall(PetscFree2(exactSol, exactCtx));
46549566063dSJacob Faibussowitsch if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
465563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
465675cca76cSMatthew G. Knepley }
4657eafd5ff0SAlex Lindsay if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46582a359c20SBarry Smith if (((PetscObject)snes)->prefix) {
465963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46602a359c20SBarry Smith } else {
466163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46622a359c20SBarry Smith }
4663eafd5ff0SAlex Lindsay } else if (snes->reason <= 0) {
46642a359c20SBarry Smith if (((PetscObject)snes)->prefix) {
466563a3b9bcSJacob 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));
46662a359c20SBarry Smith } else {
466763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46682a359c20SBarry Smith }
46692a359c20SBarry Smith }
467065bf60d2SBarry Smith PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46712a359c20SBarry Smith }
46723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
46732a359c20SBarry Smith }
46742a359c20SBarry Smith
4675c4421ceaSFande Kong /*@C
4676c4421ceaSFande Kong SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4677aaa8cc7dSPierre Jolivet end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4678c4421ceaSFande Kong
4679c3339decSBarry Smith Logically Collective
4680c4421ceaSFande Kong
4681c4421ceaSFande Kong Input Parameters:
4682f6dfbefdSBarry Smith + snes - the `SNES` context
4683420bcc1bSBarry Smith . f - the `SNESConvergedReason` view function
4684420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
468549abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4686420bcc1bSBarry Smith
4687420bcc1bSBarry Smith Calling sequence of `f`:
4688420bcc1bSBarry Smith + snes - the `SNES` context
468949abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4690c4421ceaSFande Kong
4691c4421ceaSFande Kong Options Database Keys:
4692f6dfbefdSBarry Smith + -snes_converged_reason - sets a default `SNESConvergedReasonView()`
4693420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4694420bcc1bSBarry Smith calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4695c4421ceaSFande Kong
4696dc4c0fb0SBarry Smith Level: intermediate
4697dc4c0fb0SBarry Smith
4698f6dfbefdSBarry Smith Note:
4699c4421ceaSFande Kong Several different converged reason view routines may be set by calling
4700f6dfbefdSBarry Smith `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4701c4421ceaSFande Kong order in which they were set.
4702c4421ceaSFande Kong
470349abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
470449abdd8aSBarry Smith `PetscCtxDestroyFn`
4705c4421ceaSFande Kong @*/
SNESConvergedReasonViewSet(SNES snes,PetscErrorCode (* f)(SNES snes,void * vctx),void * vctx,PetscCtxDestroyFn * reasonviewdestroy)470649abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4707d71ae5a4SJacob Faibussowitsch {
4708c4421ceaSFande Kong PetscFunctionBegin;
4709c4421ceaSFande Kong PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4710453a69bbSBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) {
4711453a69bbSBarry Smith PetscBool identical;
4712453a69bbSBarry Smith
4713453a69bbSBarry Smith PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
47143ba16761SJacob Faibussowitsch if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4715c4421ceaSFande Kong }
47165f80ce2aSJacob Faibussowitsch PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4717c4421ceaSFande Kong snes->reasonview[snes->numberreasonviews] = f;
4718c4421ceaSFande Kong snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy;
4719835f2295SStefano Zampini snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
47203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4721c4421ceaSFande Kong }
4722c4421ceaSFande Kong
472391f3e32bSBarry Smith /*@
4724420bcc1bSBarry Smith SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
47250b4b7b1cSBarry Smith All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
47262a359c20SBarry Smith
4727c3339decSBarry Smith Collective
47282a359c20SBarry Smith
47292fe279fdSBarry Smith Input Parameter:
4730f6dfbefdSBarry Smith . snes - the `SNES` object
47312a359c20SBarry Smith
4732f6dfbefdSBarry Smith Level: advanced
47332a359c20SBarry Smith
47341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4735f6dfbefdSBarry Smith `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47362a359c20SBarry Smith @*/
SNESConvergedReasonViewFromOptions(SNES snes)4737d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4738d71ae5a4SJacob Faibussowitsch {
47392a359c20SBarry Smith static PetscBool incall = PETSC_FALSE;
47402a359c20SBarry Smith
47412a359c20SBarry Smith PetscFunctionBegin;
47423ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47432a359c20SBarry Smith incall = PETSC_TRUE;
4744c4421ceaSFande Kong
4745c4421ceaSFande Kong /* All user-provided viewers are called first, if they exist. */
474636d43d94SBarry Smith for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4747c4421ceaSFande Kong
4748c4421ceaSFande Kong /* Call PETSc default routine if users ask for it */
474936d43d94SBarry Smith if (snes->convergedreasonviewer) {
475036d43d94SBarry Smith PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
475136d43d94SBarry Smith PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
475236d43d94SBarry Smith PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47532a359c20SBarry Smith }
47542a359c20SBarry Smith incall = PETSC_FALSE;
47553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47562a359c20SBarry Smith }
47572a359c20SBarry Smith
4758487a658cSBarry Smith /*@
47590b4b7b1cSBarry Smith SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47609b94acceSBarry Smith
4761c3339decSBarry Smith Collective
4762c7afd0dbSLois Curfman McInnes
4763b2002411SLois Curfman McInnes Input Parameters:
4764f6dfbefdSBarry Smith + snes - the `SNES` context
47650b4b7b1cSBarry Smith . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
476685385478SLisandro Dalcin - x - the solution vector.
47679b94acceSBarry Smith
4768dc4c0fb0SBarry Smith Level: beginner
4769dc4c0fb0SBarry Smith
4770f6dfbefdSBarry Smith Note:
4771420bcc1bSBarry Smith The user should initialize the vector, `x`, with the initial guess
4772a9b45538SStefano Zampini for the nonlinear solve prior to calling `SNESSolve()` .
47738ddd3da0SLois Curfman McInnes
47741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4775db781477SPatrick Sanan `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4776a9b45538SStefano Zampini `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47779b94acceSBarry Smith @*/
SNESSolve(SNES snes,Vec b,Vec x)4778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4779d71ae5a4SJacob Faibussowitsch {
4780ace3abfcSBarry Smith PetscBool flg;
4781efd51863SBarry Smith PetscInt grid;
47820298fd71SBarry Smith Vec xcreated = NULL;
4783caa4e7f2SJed Brown DM dm;
4784052efed2SBarry Smith
47853a40ed3dSBarry Smith PetscFunctionBegin;
47860700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4787a69afd8bSBarry Smith if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4788a69afd8bSBarry Smith if (x) PetscCheckSameComm(snes, 1, x, 3);
47890700a824SBarry Smith if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
479085385478SLisandro Dalcin if (b) PetscCheckSameComm(snes, 1, b, 2);
479185385478SLisandro Dalcin
479234b4d3a8SMatthew G. Knepley /* High level operations using the nonlinear solver */
479306fc46c8SMatthew G. Knepley {
479406fc46c8SMatthew G. Knepley PetscViewer viewer;
479506fc46c8SMatthew G. Knepley PetscViewerFormat format;
47967c88af5aSMatthew G. Knepley PetscInt num;
479706fc46c8SMatthew G. Knepley PetscBool flg;
479806fc46c8SMatthew G. Knepley static PetscBool incall = PETSC_FALSE;
479906fc46c8SMatthew G. Knepley
480006fc46c8SMatthew G. Knepley if (!incall) {
480134b4d3a8SMatthew G. Knepley /* Estimate the convergence rate of the discretization */
4802648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
480306fc46c8SMatthew G. Knepley if (flg) {
480406fc46c8SMatthew G. Knepley PetscConvEst conv;
480546079b62SMatthew G. Knepley DM dm;
480646079b62SMatthew G. Knepley PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
480746079b62SMatthew G. Knepley PetscInt Nf;
480806fc46c8SMatthew G. Knepley
480906fc46c8SMatthew G. Knepley incall = PETSC_TRUE;
48109566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
48119566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
48129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &alpha));
48139566063dSJacob Faibussowitsch PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
48149566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
48159566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetFromOptions(conv));
48169566063dSJacob Faibussowitsch PetscCall(PetscConvEstSetUp(conv));
48179566063dSJacob Faibussowitsch PetscCall(PetscConvEstGetConvRate(conv, alpha));
48189566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format));
48199566063dSJacob Faibussowitsch PetscCall(PetscConvEstRateView(conv, alpha, viewer));
48209566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer));
4821648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer));
48229566063dSJacob Faibussowitsch PetscCall(PetscConvEstDestroy(&conv));
48239566063dSJacob Faibussowitsch PetscCall(PetscFree(alpha));
482406fc46c8SMatthew G. Knepley incall = PETSC_FALSE;
482506fc46c8SMatthew G. Knepley }
482634b4d3a8SMatthew G. Knepley /* Adaptively refine the initial grid */
4827b2588ea6SMatthew G. Knepley num = 1;
48289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
482934b4d3a8SMatthew G. Knepley if (flg) {
483034b4d3a8SMatthew G. Knepley DMAdaptor adaptor;
483134b4d3a8SMatthew G. Knepley
483234b4d3a8SMatthew G. Knepley incall = PETSC_TRUE;
48339566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48349566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes));
48359566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48369566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor));
48379566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor));
48389566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48399566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor));
484034b4d3a8SMatthew G. Knepley incall = PETSC_FALSE;
484134b4d3a8SMatthew G. Knepley }
48427c88af5aSMatthew G. Knepley /* Use grid sequencing to adapt */
48437c88af5aSMatthew G. Knepley num = 0;
48449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48457c88af5aSMatthew G. Knepley if (num) {
48467c88af5aSMatthew G. Knepley DMAdaptor adaptor;
4847e03fd340SMatthew G. Knepley const char *prefix;
48487c88af5aSMatthew G. Knepley
48497c88af5aSMatthew G. Knepley incall = PETSC_TRUE;
48509566063dSJacob Faibussowitsch PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4851e03fd340SMatthew G. Knepley PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4852e03fd340SMatthew G. Knepley PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48539566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSolver(adaptor, snes));
48549566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48559566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetFromOptions(adaptor));
48569566063dSJacob Faibussowitsch PetscCall(DMAdaptorSetUp(adaptor));
4857e5148a0bSMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48589566063dSJacob Faibussowitsch PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48599566063dSJacob Faibussowitsch PetscCall(DMAdaptorDestroy(&adaptor));
48607c88af5aSMatthew G. Knepley incall = PETSC_FALSE;
48617c88af5aSMatthew G. Knepley }
486206fc46c8SMatthew G. Knepley }
486306fc46c8SMatthew G. Knepley }
4864ad540459SPierre Jolivet if (!x) x = snes->vec_sol;
4865caa4e7f2SJed Brown if (!x) {
48669566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
48679566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &xcreated));
4868a69afd8bSBarry Smith x = xcreated;
4869a69afd8bSBarry Smith }
48709566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4871f05ece33SBarry Smith
48729566063dSJacob Faibussowitsch for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4873efd51863SBarry Smith for (grid = 0; grid < snes->gridsequence + 1; grid++) {
487485385478SLisandro Dalcin /* set solution vector */
48759566063dSJacob Faibussowitsch if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol));
487785385478SLisandro Dalcin snes->vec_sol = x;
48789566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
4879caa4e7f2SJed Brown
4880caa4e7f2SJed Brown /* set affine vector if provided */
48819566063dSJacob Faibussowitsch if (b) PetscCall(PetscObjectReference((PetscObject)b));
48829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_rhs));
488385385478SLisandro Dalcin snes->vec_rhs = b;
488485385478SLisandro Dalcin
48855f80ce2aSJacob 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");
48865f80ce2aSJacob Faibussowitsch PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4887dd8e379bSPierre Jolivet PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4888aa624791SPierre Jolivet if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48899566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48909566063dSJacob Faibussowitsch PetscCall(SNESSetUp(snes));
48913f149594SLisandro Dalcin
48927eee914bSBarry Smith if (!grid) {
48939927e4dfSBarry Smith if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4894dd568438SSatish Balay }
4895d25893d9SBarry Smith
4896abc0a331SBarry Smith if (snes->conv_hist_reset) snes->conv_hist_len = 0;
489712b1dd1aSStefano Zampini PetscCall(SNESResetCounters(snes));
48982d157150SStefano Zampini snes->reason = SNES_CONVERGED_ITERATING;
48999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4900dbbe0bcdSBarry Smith PetscUseTypeMethod(snes, solve);
49019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
49022d157150SStefano Zampini PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
490376c63389SBarry Smith snes->functiondomainerror = PETSC_FALSE; /* clear the flag if it has been set */
490476c63389SBarry Smith snes->objectivedomainerror = PETSC_FALSE; /* clear the flag if it has been set */
490576c63389SBarry Smith snes->jacobiandomainerror = PETSC_FALSE; /* clear the flag if it has been set */
49063f149594SLisandro Dalcin
490737ec4e1aSPeter Brune if (snes->lagjac_persist) snes->jac_iter += snes->iter;
490837ec4e1aSPeter Brune if (snes->lagpre_persist) snes->pre_iter += snes->iter;
490937ec4e1aSPeter Brune
4910648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
49119566063dSJacob Faibussowitsch if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4912c4421ceaSFande Kong /* Call converged reason views. This may involve user-provided viewers as well */
49139566063dSJacob Faibussowitsch PetscCall(SNESConvergedReasonViewFromOptions(snes));
49145968eb51SBarry Smith
49151b3000acSStefano Zampini if (snes->errorifnotconverged) {
49161b3000acSStefano Zampini if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes));
49171b3000acSStefano Zampini PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
49181b3000acSStefano Zampini }
49199c8e83a9SBarry Smith if (snes->reason < 0) break;
4920efd51863SBarry Smith if (grid < snes->gridsequence) {
4921efd51863SBarry Smith DM fine;
4922efd51863SBarry Smith Vec xnew;
4923efd51863SBarry Smith Mat interp;
4924efd51863SBarry Smith
49259566063dSJacob Faibussowitsch PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
49265f80ce2aSJacob Faibussowitsch PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
49272eace19aSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(fine));
49289566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
49299566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(fine, &xnew));
49309566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, x, xnew));
49319566063dSJacob Faibussowitsch PetscCall(DMInterpolate(snes->dm, interp, fine));
49329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp));
4933efd51863SBarry Smith x = xnew;
4934efd51863SBarry Smith
49359566063dSJacob Faibussowitsch PetscCall(SNESReset(snes));
49369566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes, fine));
49379566063dSJacob Faibussowitsch PetscCall(SNESResetFromOptions(snes));
49389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fine));
49399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4940efd51863SBarry Smith }
4941efd51863SBarry Smith }
49429566063dSJacob Faibussowitsch PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49439566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49449566063dSJacob Faibussowitsch PetscCall(DMMonitor(snes->dm));
49459566063dSJacob Faibussowitsch PetscCall(SNESMonitorPauseFinal_Internal(snes));
49463f7e2da0SPeter Brune
49479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xcreated));
49489566063dSJacob Faibussowitsch PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49509b94acceSBarry Smith }
49519b94acceSBarry Smith
49529b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49539b94acceSBarry Smith
4954cc4c1da9SBarry Smith /*@
49550b4b7b1cSBarry Smith SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49569b94acceSBarry Smith
4957c3339decSBarry Smith Collective
4958fee21e36SBarry Smith
4959c7afd0dbSLois Curfman McInnes Input Parameters:
4960f6dfbefdSBarry Smith + snes - the `SNES` context
4961454a90a3SBarry Smith - type - a known method
4962c7afd0dbSLois Curfman McInnes
4963c7afd0dbSLois Curfman McInnes Options Database Key:
4964454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
496504d7464bSBarry Smith of available methods (for instance, newtonls or newtontr)
4966ae12b187SLois Curfman McInnes
4967dc4c0fb0SBarry Smith Level: intermediate
4968dc4c0fb0SBarry Smith
49699b94acceSBarry Smith Notes:
49700b4b7b1cSBarry Smith See `SNESType` for available methods (for instance)
4971f6dfbefdSBarry Smith + `SNESNEWTONLS` - Newton's method with line search
4972c7afd0dbSLois Curfman McInnes (systems of nonlinear equations)
49734a221d59SStefano Zampini - `SNESNEWTONTR` - Newton's method with trust region
4974c7afd0dbSLois Curfman McInnes (systems of nonlinear equations)
49759b94acceSBarry Smith
4976f6dfbefdSBarry Smith Normally, it is best to use the `SNESSetFromOptions()` command and then
4977f6dfbefdSBarry Smith set the `SNES` solver type from the options database rather than by using
4978ae12b187SLois Curfman McInnes this routine. Using the options database provides the user with
4979ae12b187SLois Curfman McInnes maximum flexibility in evaluating the many nonlinear solvers.
4980f6dfbefdSBarry Smith The `SNESSetType()` routine is provided for those situations where it
4981ae12b187SLois Curfman McInnes is necessary to set the nonlinear solver independently of the command
4982ae12b187SLois Curfman McInnes line or options database. This might be the case, for example, when
4983ae12b187SLois Curfman McInnes the choice of solver changes during the execution of the program,
4984ae12b187SLois Curfman McInnes and the user's application is taking responsibility for choosing the
4985b0a32e0cSBarry Smith appropriate method.
498636851e7fSLois Curfman McInnes
4987420bcc1bSBarry Smith Developer Note:
4988f6dfbefdSBarry Smith `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4989f6dfbefdSBarry Smith the constructor in that list and calls it to create the specific object.
49908f6c3df8SBarry Smith
49911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49929b94acceSBarry Smith @*/
SNESSetType(SNES snes,SNESType type)4993d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4994d71ae5a4SJacob Faibussowitsch {
4995ace3abfcSBarry Smith PetscBool match;
49965f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(SNES);
49973a40ed3dSBarry Smith
49983a40ed3dSBarry Smith PetscFunctionBegin;
49990700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50004f572ea9SToby Isaac PetscAssertPointer(type, 2);
500182bf6240SBarry Smith
50029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
50033ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS);
500492ff6ae8SBarry Smith
50059566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(SNESList, type, &r));
50066adde796SStefano Zampini PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
500775396ef9SLisandro Dalcin /* Destroy the previous private SNES context */
5008dbbe0bcdSBarry Smith PetscTryTypeMethod(snes, destroy);
500943547594SStefano Zampini /* Reinitialize type-specific function pointers in SNESOps structure */
501043547594SStefano Zampini snes->ops->reset = NULL;
50119e5d0892SLisandro Dalcin snes->ops->setup = NULL;
50129e5d0892SLisandro Dalcin snes->ops->solve = NULL;
50139e5d0892SLisandro Dalcin snes->ops->view = NULL;
50149e5d0892SLisandro Dalcin snes->ops->setfromoptions = NULL;
50159e5d0892SLisandro Dalcin snes->ops->destroy = NULL;
50167fe760d5SStefano Zampini
50177fe760d5SStefano Zampini /* It may happen the user has customized the line search before calling SNESSetType */
50189566063dSJacob Faibussowitsch if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
50197fe760d5SStefano Zampini
502075396ef9SLisandro Dalcin /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
502175396ef9SLisandro Dalcin snes->setupcalled = PETSC_FALSE;
5022f5af7f23SKarl Rupp
50239566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
50249566063dSJacob Faibussowitsch PetscCall((*r)(snes));
50253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50269b94acceSBarry Smith }
50279b94acceSBarry Smith
5028cc4c1da9SBarry Smith /*@
5029f6dfbefdSBarry Smith SNESGetType - Gets the `SNES` method type and name (as a string).
50309b94acceSBarry Smith
5031c7afd0dbSLois Curfman McInnes Not Collective
5032c7afd0dbSLois Curfman McInnes
50339b94acceSBarry Smith Input Parameter:
50344b0e389bSBarry Smith . snes - nonlinear solver context
50359b94acceSBarry Smith
50369b94acceSBarry Smith Output Parameter:
5037f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50389b94acceSBarry Smith
503936851e7fSLois Curfman McInnes Level: intermediate
504036851e7fSLois Curfman McInnes
50411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50429b94acceSBarry Smith @*/
SNESGetType(SNES snes,SNESType * type)5043d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5044d71ae5a4SJacob Faibussowitsch {
50453a40ed3dSBarry Smith PetscFunctionBegin;
50460700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50474f572ea9SToby Isaac PetscAssertPointer(type, 2);
50487adad957SLisandro Dalcin *type = ((PetscObject)snes)->type_name;
50493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50509b94acceSBarry Smith }
50519b94acceSBarry Smith
50523cd8a7caSMatthew G. Knepley /*@
5053f6dfbefdSBarry Smith SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50543cd8a7caSMatthew G. Knepley
5055c3339decSBarry Smith Logically Collective
50563cd8a7caSMatthew G. Knepley
50573cd8a7caSMatthew G. Knepley Input Parameters:
5058f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50593cd8a7caSMatthew G. Knepley - u - the solution vector
50603cd8a7caSMatthew G. Knepley
50613cd8a7caSMatthew G. Knepley Level: beginner
50623cd8a7caSMatthew G. Knepley
50631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50643cd8a7caSMatthew G. Knepley @*/
SNESSetSolution(SNES snes,Vec u)5065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5066d71ae5a4SJacob Faibussowitsch {
50673cd8a7caSMatthew G. Knepley DM dm;
50683cd8a7caSMatthew G. Knepley
50693cd8a7caSMatthew G. Knepley PetscFunctionBegin;
50703cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50713cd8a7caSMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)u));
50739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&snes->vec_sol));
50743cd8a7caSMatthew G. Knepley
50753cd8a7caSMatthew G. Knepley snes->vec_sol = u;
50763cd8a7caSMatthew G. Knepley
50779566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
50789566063dSJacob Faibussowitsch PetscCall(DMShellSetGlobalVector(dm, u));
50793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50803cd8a7caSMatthew G. Knepley }
50813cd8a7caSMatthew G. Knepley
508252baeb72SSatish Balay /*@
50839b94acceSBarry Smith SNESGetSolution - Returns the vector where the approximate solution is
5084f6dfbefdSBarry Smith stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50859b94acceSBarry Smith
5086420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel
5087c7afd0dbSLois Curfman McInnes
50889b94acceSBarry Smith Input Parameter:
5089f6dfbefdSBarry Smith . snes - the `SNES` context
50909b94acceSBarry Smith
50919b94acceSBarry Smith Output Parameter:
50929b94acceSBarry Smith . x - the solution
50939b94acceSBarry Smith
509470e92668SMatthew Knepley Level: intermediate
509536851e7fSLois Curfman McInnes
50961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50979b94acceSBarry Smith @*/
SNESGetSolution(SNES snes,Vec * x)5098d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5099d71ae5a4SJacob Faibussowitsch {
51003a40ed3dSBarry Smith PetscFunctionBegin;
51010700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51024f572ea9SToby Isaac PetscAssertPointer(x, 2);
510385385478SLisandro Dalcin *x = snes->vec_sol;
51043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
510570e92668SMatthew Knepley }
510670e92668SMatthew Knepley
510752baeb72SSatish Balay /*@
51089b94acceSBarry Smith SNESGetSolutionUpdate - Returns the vector where the solution update is
51099b94acceSBarry Smith stored.
51109b94acceSBarry Smith
5111420bcc1bSBarry Smith Not Collective, but `x` is parallel if `snes` is parallel
5112c7afd0dbSLois Curfman McInnes
51139b94acceSBarry Smith Input Parameter:
5114f6dfbefdSBarry Smith . snes - the `SNES` context
51159b94acceSBarry Smith
51169b94acceSBarry Smith Output Parameter:
51179b94acceSBarry Smith . x - the solution update
51189b94acceSBarry Smith
511936851e7fSLois Curfman McInnes Level: advanced
512036851e7fSLois Curfman McInnes
51211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
51229b94acceSBarry Smith @*/
SNESGetSolutionUpdate(SNES snes,Vec * x)5123d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5124d71ae5a4SJacob Faibussowitsch {
51253a40ed3dSBarry Smith PetscFunctionBegin;
51260700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51274f572ea9SToby Isaac PetscAssertPointer(x, 2);
512885385478SLisandro Dalcin *x = snes->vec_sol_update;
51293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51309b94acceSBarry Smith }
51319b94acceSBarry Smith
51329b94acceSBarry Smith /*@C
5133f6dfbefdSBarry Smith SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
51349b94acceSBarry Smith
5135420bcc1bSBarry Smith Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5136c7afd0dbSLois Curfman McInnes
51379b94acceSBarry Smith Input Parameter:
5138f6dfbefdSBarry Smith . snes - the `SNES` context
51399b94acceSBarry Smith
5140d8d19677SJose E. Roman Output Parameters:
5141dc4c0fb0SBarry Smith + r - the vector that is used to store residuals (or `NULL` if you don't want it)
51428434afd1SBarry Smith . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn`
5143dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51449b94acceSBarry Smith
514536851e7fSLois Curfman McInnes Level: advanced
514636851e7fSLois Curfman McInnes
5147f6dfbefdSBarry Smith Note:
5148dc4c0fb0SBarry Smith The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
514904edfde5SBarry Smith
51508434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51519b94acceSBarry Smith @*/
SNESGetFunction(SNES snes,Vec * r,SNESFunctionFn ** f,PetscCtxRt ctx)51522a8381b2SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, PetscCtxRt ctx)
5153d71ae5a4SJacob Faibussowitsch {
51546cab3a1bSJed Brown DM dm;
5155a63bb30eSJed Brown
51563a40ed3dSBarry Smith PetscFunctionBegin;
51570700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5158a63bb30eSJed Brown if (r) {
5159a63bb30eSJed Brown if (!snes->vec_func) {
5160a63bb30eSJed Brown if (snes->vec_rhs) {
51619566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5162a63bb30eSJed Brown } else if (snes->vec_sol) {
51639566063dSJacob Faibussowitsch PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5164a63bb30eSJed Brown } else if (snes->dm) {
51659566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5166a63bb30eSJed Brown }
5167a63bb30eSJed Brown }
5168a63bb30eSJed Brown *r = snes->vec_func;
5169a63bb30eSJed Brown }
51709566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
51719566063dSJacob Faibussowitsch PetscCall(DMSNESGetFunction(dm, f, ctx));
51723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51739b94acceSBarry Smith }
51749b94acceSBarry Smith
5175c79ef259SPeter Brune /*@C
517637fdd005SBarry Smith SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5177c79ef259SPeter Brune
5178c79ef259SPeter Brune Input Parameter:
5179f6dfbefdSBarry Smith . snes - the `SNES` context
5180c79ef259SPeter Brune
5181d8d19677SJose E. Roman Output Parameters:
51828434afd1SBarry Smith + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5183dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5184c79ef259SPeter Brune
5185c79ef259SPeter Brune Level: advanced
5186c79ef259SPeter Brune
51878434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5188c79ef259SPeter Brune @*/
SNESGetNGS(SNES snes,SNESNGSFn ** f,PetscCtxRt ctx)51892a8381b2SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, PetscCtxRt ctx)
5190d71ae5a4SJacob Faibussowitsch {
51916cab3a1bSJed Brown DM dm;
51926cab3a1bSJed Brown
5193646217ecSPeter Brune PetscFunctionBegin;
5194646217ecSPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51959566063dSJacob Faibussowitsch PetscCall(SNESGetDM(snes, &dm));
51969566063dSJacob Faibussowitsch PetscCall(DMSNESGetNGS(dm, f, ctx));
51973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5198646217ecSPeter Brune }
5199646217ecSPeter Brune
5200cc4c1da9SBarry Smith /*@
52013c7409f5SSatish Balay SNESSetOptionsPrefix - Sets the prefix used for searching for all
5202f6dfbefdSBarry Smith `SNES` options in the database.
52033c7409f5SSatish Balay
5204c3339decSBarry Smith Logically Collective
5205fee21e36SBarry Smith
5206d8d19677SJose E. Roman Input Parameters:
5207f6dfbefdSBarry Smith + snes - the `SNES` context
5208c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5209c7afd0dbSLois Curfman McInnes
5210dc4c0fb0SBarry Smith Level: advanced
5211dc4c0fb0SBarry Smith
5212f6dfbefdSBarry Smith Note:
5213a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name.
5214c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen.
5215d850072dSLois Curfman McInnes
52161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
52173c7409f5SSatish Balay @*/
SNESSetOptionsPrefix(SNES snes,const char prefix[])5218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5219d71ae5a4SJacob Faibussowitsch {
52203a40ed3dSBarry Smith PetscFunctionBegin;
52210700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
52239566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
522435f5d045SPeter Brune if (snes->linesearch) {
52259566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
522735f5d045SPeter Brune }
52289566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
52293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52303c7409f5SSatish Balay }
52313c7409f5SSatish Balay
5232cc4c1da9SBarry Smith /*@
5233f525115eSLois Curfman McInnes SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5234f6dfbefdSBarry Smith `SNES` options in the database.
52353c7409f5SSatish Balay
5236c3339decSBarry Smith Logically Collective
5237fee21e36SBarry Smith
5238c7afd0dbSLois Curfman McInnes Input Parameters:
5239f6dfbefdSBarry Smith + snes - the `SNES` context
5240c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5241c7afd0dbSLois Curfman McInnes
5242dc4c0fb0SBarry Smith Level: advanced
5243dc4c0fb0SBarry Smith
5244f6dfbefdSBarry Smith Note:
5245a83b1b31SSatish Balay A hyphen (-) must NOT be given at the beginning of the prefix name.
5246c7afd0dbSLois Curfman McInnes The first character of all runtime options is AUTOMATICALLY the hyphen.
5247d850072dSLois Curfman McInnes
52481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52493c7409f5SSatish Balay @*/
SNESAppendOptionsPrefix(SNES snes,const char prefix[])5250d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5251d71ae5a4SJacob Faibussowitsch {
52523a40ed3dSBarry Smith PetscFunctionBegin;
52530700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52549566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52559566063dSJacob Faibussowitsch if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
525635f5d045SPeter Brune if (snes->linesearch) {
52579566063dSJacob Faibussowitsch PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52589566063dSJacob Faibussowitsch PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
525935f5d045SPeter Brune }
52609566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52623c7409f5SSatish Balay }
52633c7409f5SSatish Balay
5264cc4c1da9SBarry Smith /*@
5265f6dfbefdSBarry Smith SNESGetOptionsPrefix - Gets the prefix used for searching for all
5266f6dfbefdSBarry Smith `SNES` options in the database.
52673c7409f5SSatish Balay
5268c7afd0dbSLois Curfman McInnes Not Collective
5269c7afd0dbSLois Curfman McInnes
52703c7409f5SSatish Balay Input Parameter:
5271f6dfbefdSBarry Smith . snes - the `SNES` context
52723c7409f5SSatish Balay
52733c7409f5SSatish Balay Output Parameter:
52743c7409f5SSatish Balay . prefix - pointer to the prefix string used
52753c7409f5SSatish Balay
527636851e7fSLois Curfman McInnes Level: advanced
527736851e7fSLois Curfman McInnes
52781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52793c7409f5SSatish Balay @*/
SNESGetOptionsPrefix(SNES snes,const char * prefix[])5280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5281d71ae5a4SJacob Faibussowitsch {
52823a40ed3dSBarry Smith PetscFunctionBegin;
52830700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52849566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52863c7409f5SSatish Balay }
52873c7409f5SSatish Balay
52883cea93caSBarry Smith /*@C
52891c84c290SBarry Smith SNESRegister - Adds a method to the nonlinear solver package.
52901c84c290SBarry Smith
529120f4b53cSBarry Smith Not Collective
52921c84c290SBarry Smith
52931c84c290SBarry Smith Input Parameters:
529420f4b53cSBarry Smith + sname - name of a new user-defined solver
529520f4b53cSBarry Smith - function - routine to create method context
52961c84c290SBarry Smith
5297dc4c0fb0SBarry Smith Level: advanced
5298dc4c0fb0SBarry Smith
5299f6dfbefdSBarry Smith Note:
5300f6dfbefdSBarry Smith `SNESRegister()` may be called multiple times to add several user-defined solvers.
53011c84c290SBarry Smith
5302e4094ef1SJacob Faibussowitsch Example Usage:
53031c84c290SBarry Smith .vb
5304bdf89e91SBarry Smith SNESRegister("my_solver", MySolverCreate);
53051c84c290SBarry Smith .ve
53061c84c290SBarry Smith
53071c84c290SBarry Smith Then, your solver can be chosen with the procedural interface via
5308b44f4de4SBarry Smith .vb
5309b44f4de4SBarry Smith SNESSetType(snes, "my_solver")
5310b44f4de4SBarry Smith .ve
53111c84c290SBarry Smith or at runtime via the option
5312b44f4de4SBarry Smith .vb
5313b44f4de4SBarry Smith -snes_type my_solver
5314b44f4de4SBarry Smith .ve
53151c84c290SBarry Smith
53161cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
53173cea93caSBarry Smith @*/
SNESRegister(const char sname[],PetscErrorCode (* function)(SNES))5318d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5319d71ae5a4SJacob Faibussowitsch {
5320b2002411SLois Curfman McInnes PetscFunctionBegin;
53219566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage());
53229566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
53233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5324b2002411SLois Curfman McInnes }
5325da9b6338SBarry Smith
SNESTestLocalMin(SNES snes)5326d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5327d71ae5a4SJacob Faibussowitsch {
532877431f27SBarry Smith PetscInt N, i, j;
5329da9b6338SBarry Smith Vec u, uh, fh;
5330da9b6338SBarry Smith PetscScalar value;
5331da9b6338SBarry Smith PetscReal norm;
5332da9b6338SBarry Smith
5333da9b6338SBarry Smith PetscFunctionBegin;
53349566063dSJacob Faibussowitsch PetscCall(SNESGetSolution(snes, &u));
53359566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &uh));
53369566063dSJacob Faibussowitsch PetscCall(VecDuplicate(u, &fh));
5337da9b6338SBarry Smith
5338da9b6338SBarry Smith /* currently only works for sequential */
53399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53409566063dSJacob Faibussowitsch PetscCall(VecGetSize(u, &N));
5341da9b6338SBarry Smith for (i = 0; i < N; i++) {
53429566063dSJacob Faibussowitsch PetscCall(VecCopy(u, uh));
534363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5344da9b6338SBarry Smith for (j = -10; j < 11; j++) {
53458b49ba18SBarry Smith value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53469566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53479566063dSJacob Faibussowitsch PetscCall(SNESComputeFunction(snes, uh, fh));
534876c63389SBarry Smith PetscCall(VecNorm(fh, NORM_2, &norm)); /* does not handle use of SNESSetFunctionDomainError() correctly */
534963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5350da9b6338SBarry Smith value = -value;
53519566063dSJacob Faibussowitsch PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5352da9b6338SBarry Smith }
5353da9b6338SBarry Smith }
53549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&uh));
53559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fh));
53563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5357da9b6338SBarry Smith }
535871f87433Sdalcinl
535971f87433Sdalcinl /*@
536076c63389SBarry Smith SNESGetLineSearch - Returns the line search associated with the `SNES`.
536176c63389SBarry Smith
536276c63389SBarry Smith Not Collective
536376c63389SBarry Smith
536476c63389SBarry Smith Input Parameter:
536576c63389SBarry Smith . snes - iterative context obtained from `SNESCreate()`
536676c63389SBarry Smith
536776c63389SBarry Smith Output Parameter:
536876c63389SBarry Smith . linesearch - linesearch context
536976c63389SBarry Smith
537076c63389SBarry Smith Level: beginner
537176c63389SBarry Smith
537276c63389SBarry Smith Notes:
537376c63389SBarry Smith It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
537476c63389SBarry Smith
537576c63389SBarry Smith You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
537676c63389SBarry Smith
537776c63389SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
537876c63389SBarry Smith @*/
SNESGetLineSearch(SNES snes,SNESLineSearch * linesearch)537976c63389SBarry Smith PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
538076c63389SBarry Smith {
538176c63389SBarry Smith const char *optionsprefix;
538276c63389SBarry Smith
538376c63389SBarry Smith PetscFunctionBegin;
538476c63389SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
538576c63389SBarry Smith PetscAssertPointer(linesearch, 2);
538676c63389SBarry Smith if (!snes->linesearch) {
538776c63389SBarry Smith PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
538876c63389SBarry Smith PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
538976c63389SBarry Smith PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
539076c63389SBarry Smith PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
539176c63389SBarry Smith PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
539276c63389SBarry Smith }
539376c63389SBarry Smith *linesearch = snes->linesearch;
539476c63389SBarry Smith PetscFunctionReturn(PETSC_SUCCESS);
539576c63389SBarry Smith }
539676c63389SBarry Smith
539776c63389SBarry Smith /*@
5398f6dfbefdSBarry Smith SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
539971f87433Sdalcinl computing relative tolerance for linear solvers within an inexact
540071f87433Sdalcinl Newton method.
540171f87433Sdalcinl
5402c3339decSBarry Smith Logically Collective
540371f87433Sdalcinl
540471f87433Sdalcinl Input Parameters:
5405f6dfbefdSBarry Smith + snes - `SNES` context
5406f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
540771f87433Sdalcinl
5408f6dfbefdSBarry Smith Options Database Keys:
540964ba62caSBarry Smith + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
541064ba62caSBarry Smith . -snes_ksp_ew_version ver - version of Eisenstat-Walker method
541164ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
541264ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
541364ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma> - Sets gamma
541464ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha> - Sets alpha
541564ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
541664ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
541764ba62caSBarry Smith
5418dc4c0fb0SBarry Smith Level: advanced
5419dc4c0fb0SBarry Smith
5420f6dfbefdSBarry Smith Note:
5421f6dfbefdSBarry Smith The default is to use a constant relative tolerance for
542271f87433Sdalcinl the inner linear solvers. Alternatively, one can use the
54231d27aa22SBarry Smith Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
542471f87433Sdalcinl is reset at each Newton iteration according progress of the nonlinear
542571f87433Sdalcinl solver.
542671f87433Sdalcinl
54271cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
542871f87433Sdalcinl @*/
SNESKSPSetUseEW(SNES snes,PetscBool flag)5429d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5430d71ae5a4SJacob Faibussowitsch {
543171f87433Sdalcinl PetscFunctionBegin;
54320700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5433acfcf0e5SJed Brown PetscValidLogicalCollectiveBool(snes, flag, 2);
543471f87433Sdalcinl snes->ksp_ewconv = flag;
54353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
543671f87433Sdalcinl }
543771f87433Sdalcinl
543871f87433Sdalcinl /*@
5439f6dfbefdSBarry Smith SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
544071f87433Sdalcinl for computing relative tolerance for linear solvers within an
544171f87433Sdalcinl inexact Newton method.
544271f87433Sdalcinl
544371f87433Sdalcinl Not Collective
544471f87433Sdalcinl
544571f87433Sdalcinl Input Parameter:
5446f6dfbefdSBarry Smith . snes - `SNES` context
544771f87433Sdalcinl
544871f87433Sdalcinl Output Parameter:
5449f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
545071f87433Sdalcinl
545171f87433Sdalcinl Level: advanced
545271f87433Sdalcinl
54531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
545471f87433Sdalcinl @*/
SNESKSPGetUseEW(SNES snes,PetscBool * flag)5455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5456d71ae5a4SJacob Faibussowitsch {
545771f87433Sdalcinl PetscFunctionBegin;
54580700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54594f572ea9SToby Isaac PetscAssertPointer(flag, 2);
546071f87433Sdalcinl *flag = snes->ksp_ewconv;
54613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
546271f87433Sdalcinl }
546371f87433Sdalcinl
546471f87433Sdalcinl /*@
5465fa9f3622SBarry Smith SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
546671f87433Sdalcinl convergence criteria for the linear solvers within an inexact
546771f87433Sdalcinl Newton method.
546871f87433Sdalcinl
5469c3339decSBarry Smith Logically Collective
547071f87433Sdalcinl
547171f87433Sdalcinl Input Parameters:
5472f6dfbefdSBarry Smith + snes - `SNES` context
54730f0abf79SStefano Zampini . version - version 1, 2 (default is 2), 3 or 4
547471f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
547571f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
547671f87433Sdalcinl . gamma - multiplicative factor for version 2 rtol computation
547771f87433Sdalcinl (0 <= gamma2 <= 1)
547871f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2)
547971f87433Sdalcinl . alpha2 - power for safeguard
548071f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
548171f87433Sdalcinl
5482dc4c0fb0SBarry Smith Level: advanced
5483dc4c0fb0SBarry Smith
5484f6dfbefdSBarry Smith Notes:
548571f87433Sdalcinl Version 3 was contributed by Luis Chacon, June 2006.
548671f87433Sdalcinl
548777e5a1f9SBarry Smith Use `PETSC_CURRENT` to retain the default for any of the parameters.
548871f87433Sdalcinl
54891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
549071f87433Sdalcinl @*/
SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold)5491d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5492d71ae5a4SJacob Faibussowitsch {
5493fa9f3622SBarry Smith SNESKSPEW *kctx;
54945fd66863SKarl Rupp
549571f87433Sdalcinl PetscFunctionBegin;
54960700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5497fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx;
54985f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5499c5eb9154SBarry Smith PetscValidLogicalCollectiveInt(snes, version, 2);
5500c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5501c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5502c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, gamma, 5);
5503c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha, 6);
5504c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5505c5eb9154SBarry Smith PetscValidLogicalCollectiveReal(snes, threshold, 8);
550671f87433Sdalcinl
550777e5a1f9SBarry Smith if (version != PETSC_CURRENT) kctx->version = version;
550877e5a1f9SBarry Smith if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
550977e5a1f9SBarry Smith if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
551077e5a1f9SBarry Smith if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
551177e5a1f9SBarry Smith if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
551277e5a1f9SBarry Smith if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
551377e5a1f9SBarry Smith if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
551471f87433Sdalcinl
55150f0abf79SStefano 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);
55160b121fc5SBarry 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);
55170b121fc5SBarry 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);
55180b121fc5SBarry 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);
55190b121fc5SBarry 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);
55200b121fc5SBarry 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);
55213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
552271f87433Sdalcinl }
552371f87433Sdalcinl
552471f87433Sdalcinl /*@
5525fa9f3622SBarry Smith SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
552671f87433Sdalcinl convergence criteria for the linear solvers within an inexact
552771f87433Sdalcinl Newton method.
552871f87433Sdalcinl
552971f87433Sdalcinl Not Collective
553071f87433Sdalcinl
553197bb3fdcSJose E. Roman Input Parameter:
5532f6dfbefdSBarry Smith . snes - `SNES` context
553371f87433Sdalcinl
553471f87433Sdalcinl Output Parameters:
55350f0abf79SStefano Zampini + version - version 1, 2 (default is 2), 3 or 4
553671f87433Sdalcinl . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
553771f87433Sdalcinl . rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5538bf388a1fSBarry Smith . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
553971f87433Sdalcinl . alpha - power for version 2 rtol computation (1 < alpha <= 2)
554071f87433Sdalcinl . alpha2 - power for safeguard
554171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
554271f87433Sdalcinl
554371f87433Sdalcinl Level: advanced
554471f87433Sdalcinl
55451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
554671f87433Sdalcinl @*/
SNESKSPGetParametersEW(SNES snes,PetscInt * version,PetscReal * rtol_0,PetscReal * rtol_max,PetscReal * gamma,PetscReal * alpha,PetscReal * alpha2,PetscReal * threshold)5547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5548d71ae5a4SJacob Faibussowitsch {
5549fa9f3622SBarry Smith SNESKSPEW *kctx;
55505fd66863SKarl Rupp
555171f87433Sdalcinl PetscFunctionBegin;
55520700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5553fa9f3622SBarry Smith kctx = (SNESKSPEW *)snes->kspconvctx;
55545f80ce2aSJacob Faibussowitsch PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
555571f87433Sdalcinl if (version) *version = kctx->version;
555671f87433Sdalcinl if (rtol_0) *rtol_0 = kctx->rtol_0;
555771f87433Sdalcinl if (rtol_max) *rtol_max = kctx->rtol_max;
555871f87433Sdalcinl if (gamma) *gamma = kctx->gamma;
555971f87433Sdalcinl if (alpha) *alpha = kctx->alpha;
556071f87433Sdalcinl if (alpha2) *alpha2 = kctx->alpha2;
556171f87433Sdalcinl if (threshold) *threshold = kctx->threshold;
55623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
556371f87433Sdalcinl }
556471f87433Sdalcinl
KSPPreSolve_SNESEW(KSP ksp,Vec b,Vec x,PetscCtx ctx)55652a8381b2SBarry Smith PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, PetscCtx ctx)
5566d71ae5a4SJacob Faibussowitsch {
55675c0db29aSPierre Jolivet SNES snes = (SNES)ctx;
5568fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
556977e5a1f9SBarry Smith PetscReal rtol = PETSC_CURRENT, stol;
557071f87433Sdalcinl
557171f87433Sdalcinl PetscFunctionBegin;
55723ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
557330058271SDmitry Karpeev if (!snes->iter) {
557430058271SDmitry Karpeev rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55759566063dSJacob Faibussowitsch PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55760f0abf79SStefano Zampini } else {
55770fdf79fbSJacob 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);
557871f87433Sdalcinl if (kctx->version == 1) {
55790f0abf79SStefano Zampini rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
558085ec1a3cSBarry Smith stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
558171f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
558271f87433Sdalcinl } else if (kctx->version == 2) {
558385ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
558485ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
558571f87433Sdalcinl if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
558671f87433Sdalcinl } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
558785ec1a3cSBarry Smith rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
558871f87433Sdalcinl /* safeguard: avoid sharp decrease of rtol */
558985ec1a3cSBarry Smith stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
559071f87433Sdalcinl stol = PetscMax(rtol, stol);
559171f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol);
559271f87433Sdalcinl /* safeguard: avoid oversolving */
559330058271SDmitry Karpeev stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
559471f87433Sdalcinl stol = PetscMax(rtol, stol);
559571f87433Sdalcinl rtol = PetscMin(kctx->rtol_0, stol);
55960fdf79fbSJacob Faibussowitsch } else /* if (kctx->version == 4) */ {
55970fdf79fbSJacob Faibussowitsch /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55980f0abf79SStefano Zampini PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55990f0abf79SStefano Zampini PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
56000f0abf79SStefano Zampini PetscReal rk = ared / pred;
56010f0abf79SStefano Zampini if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
56020f0abf79SStefano Zampini else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
56030f0abf79SStefano Zampini else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
56040f0abf79SStefano Zampini else rtol = kctx->v4_m2 * kctx->rtol_last;
56050f0abf79SStefano Zampini
5606a4598233SStefano 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;
56070f0abf79SStefano Zampini kctx->rtol_last_2 = kctx->rtol_last;
56080f0abf79SStefano Zampini kctx->rk_last_2 = kctx->rk_last;
56090f0abf79SStefano Zampini kctx->rk_last = rk;
56100fdf79fbSJacob Faibussowitsch }
56110f0abf79SStefano Zampini }
56120f0abf79SStefano Zampini /* safeguard: avoid rtol greater than rtol_max */
561371f87433Sdalcinl rtol = PetscMin(rtol, kctx->rtol_max);
561477e5a1f9SBarry Smith PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
561563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
56163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
561771f87433Sdalcinl }
561871f87433Sdalcinl
KSPPostSolve_SNESEW(KSP ksp,Vec b,Vec x,PetscCtx ctx)56192a8381b2SBarry Smith PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, PetscCtx ctx)
5620d71ae5a4SJacob Faibussowitsch {
56215c0db29aSPierre Jolivet SNES snes = (SNES)ctx;
5622fa9f3622SBarry Smith SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
562371f87433Sdalcinl PCSide pcside;
562471f87433Sdalcinl Vec lres;
562571f87433Sdalcinl
562671f87433Sdalcinl PetscFunctionBegin;
56273ba16761SJacob Faibussowitsch if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
56289566063dSJacob Faibussowitsch PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
562971dbe336SPeter Brune kctx->norm_last = snes->norm;
56300f0abf79SStefano Zampini if (kctx->version == 1 || kctx->version == 4) {
56314f00ce20SMatthew G. Knepley PC pc;
56320f0abf79SStefano Zampini PetscBool getRes;
56334f00ce20SMatthew G. Knepley
56349566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc));
56350f0abf79SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
56360f0abf79SStefano Zampini if (!getRes) {
56370f0abf79SStefano Zampini KSPNormType normtype;
56380f0abf79SStefano Zampini
56390f0abf79SStefano Zampini PetscCall(KSPGetNormType(ksp, &normtype));
56400f0abf79SStefano Zampini getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
56410f0abf79SStefano Zampini }
56429566063dSJacob Faibussowitsch PetscCall(KSPGetPCSide(ksp, &pcside));
56430f0abf79SStefano Zampini if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
56449566063dSJacob Faibussowitsch PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
564571f87433Sdalcinl } else {
564671f87433Sdalcinl /* KSP residual is preconditioned residual */
564771f87433Sdalcinl /* compute true linear residual norm */
56480f0abf79SStefano Zampini Mat J;
56490f0abf79SStefano Zampini PetscCall(KSPGetOperators(ksp, &J, NULL));
56509566063dSJacob Faibussowitsch PetscCall(VecDuplicate(b, &lres));
56510f0abf79SStefano Zampini PetscCall(MatMult(J, x, lres));
56529566063dSJacob Faibussowitsch PetscCall(VecAYPX(lres, -1.0, b));
56539566063dSJacob Faibussowitsch PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
56549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lres));
565571f87433Sdalcinl }
565671f87433Sdalcinl }
56573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
565871f87433Sdalcinl }
565971f87433Sdalcinl
5660d4211eb9SBarry Smith /*@
5661f6dfbefdSBarry Smith SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5662d4211eb9SBarry Smith
5663420bcc1bSBarry Smith Not Collective, but if `snes` is parallel, then `ksp` is parallel
5664d4211eb9SBarry Smith
5665d4211eb9SBarry Smith Input Parameter:
5666f6dfbefdSBarry Smith . snes - the `SNES` context
5667d4211eb9SBarry Smith
5668d4211eb9SBarry Smith Output Parameter:
5669f6dfbefdSBarry Smith . ksp - the `KSP` context
5670d4211eb9SBarry Smith
5671dc4c0fb0SBarry Smith Level: beginner
5672dc4c0fb0SBarry Smith
5673d4211eb9SBarry Smith Notes:
5674f6dfbefdSBarry Smith The user can then directly manipulate the `KSP` context to set various
5675d4211eb9SBarry Smith options, etc. Likewise, the user can then extract and manipulate the
5676f6dfbefdSBarry Smith `PC` contexts as well.
5677f6dfbefdSBarry Smith
56780b4b7b1cSBarry Smith Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect.
5679d4211eb9SBarry Smith
56801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5681d4211eb9SBarry Smith @*/
SNESGetKSP(SNES snes,KSP * ksp)5682d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5683d71ae5a4SJacob Faibussowitsch {
568471f87433Sdalcinl PetscFunctionBegin;
5685d4211eb9SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56864f572ea9SToby Isaac PetscAssertPointer(ksp, 2);
5687d4211eb9SBarry Smith
5688d4211eb9SBarry Smith if (!snes->ksp) {
56899566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56909566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5691d4211eb9SBarry Smith
56925c0db29aSPierre Jolivet PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56935c0db29aSPierre Jolivet PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5694a5c2985bSBarry Smith
56959566063dSJacob Faibussowitsch PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5697d4211eb9SBarry Smith }
5698d4211eb9SBarry Smith *ksp = snes->ksp;
56993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
570071f87433Sdalcinl }
57016c699258SBarry Smith
5702af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
57036c699258SBarry Smith /*@
57040b4b7b1cSBarry Smith SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
57056c699258SBarry Smith
5706c3339decSBarry Smith Logically Collective
57076c699258SBarry Smith
57086c699258SBarry Smith Input Parameters:
57092a808120SBarry Smith + snes - the nonlinear solver context
5710420bcc1bSBarry Smith - dm - the `DM`, cannot be `NULL`
5711dc4c0fb0SBarry Smith
5712dc4c0fb0SBarry Smith Level: intermediate
57136c699258SBarry Smith
5714f6dfbefdSBarry Smith Note:
5715f6dfbefdSBarry Smith A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5716f6dfbefdSBarry Smith even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different
5717e03a659cSJed Brown problems using the same function space.
5718e03a659cSJed Brown
5719420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
57206c699258SBarry Smith @*/
SNESSetDM(SNES snes,DM dm)5721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5722d71ae5a4SJacob Faibussowitsch {
5723345fed2cSBarry Smith KSP ksp;
5724942e3340SBarry Smith DMSNES sdm;
57256c699258SBarry Smith
57266c699258SBarry Smith PetscFunctionBegin;
57270700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57282a808120SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
57299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
5730942e3340SBarry Smith if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
573151f4b3c7SToby Isaac if (snes->dm->dmsnes && !dm->dmsnes) {
57329566063dSJacob Faibussowitsch PetscCall(DMCopyDMSNES(snes->dm, dm));
57339566063dSJacob Faibussowitsch PetscCall(DMGetDMSNES(snes->dm, &sdm));
5734f5af7f23SKarl Rupp if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
57356cab3a1bSJed Brown }
57369566063dSJacob Faibussowitsch PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
57379566063dSJacob Faibussowitsch PetscCall(DMDestroy(&snes->dm));
57386cab3a1bSJed Brown }
57396c699258SBarry Smith snes->dm = dm;
5740116d1032SJed Brown snes->dmAuto = PETSC_FALSE;
5741f5af7f23SKarl Rupp
57429566063dSJacob Faibussowitsch PetscCall(SNESGetKSP(snes, &ksp));
57439566063dSJacob Faibussowitsch PetscCall(KSPSetDM(ksp, dm));
5744*bf0c7fc2SBarry Smith PetscCall(KSPSetDMActive(ksp, KSP_DMACTIVE_ALL, PETSC_FALSE));
5745efd4aadfSBarry Smith if (snes->npc) {
57469566063dSJacob Faibussowitsch PetscCall(SNESSetDM(snes->npc, snes->dm));
57479566063dSJacob Faibussowitsch PetscCall(SNESSetNPCSide(snes, snes->npcside));
57482c155ee1SBarry Smith }
57493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57506c699258SBarry Smith }
57516c699258SBarry Smith
57526c699258SBarry Smith /*@
57530b4b7b1cSBarry Smith SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
57546c699258SBarry Smith
57550b4b7b1cSBarry Smith Not Collective but `dm` obtained is parallel on `snes`
57566c699258SBarry Smith
57576c699258SBarry Smith Input Parameter:
5758420bcc1bSBarry Smith . snes - the `SNES` context
57596c699258SBarry Smith
57606c699258SBarry Smith Output Parameter:
5761420bcc1bSBarry Smith . dm - the `DM`
57626c699258SBarry Smith
57636c699258SBarry Smith Level: intermediate
57646c699258SBarry Smith
5765420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
57666c699258SBarry Smith @*/
SNESGetDM(SNES snes,DM * dm)5767d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5768d71ae5a4SJacob Faibussowitsch {
57696c699258SBarry Smith PetscFunctionBegin;
57700700a824SBarry Smith PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57716cab3a1bSJed Brown if (!snes->dm) {
57729566063dSJacob Faibussowitsch PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5773116d1032SJed Brown snes->dmAuto = PETSC_TRUE;
57746cab3a1bSJed Brown }
57756c699258SBarry Smith *dm = snes->dm;
57763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57776c699258SBarry Smith }
57780807856dSBarry Smith
577931823bd8SMatthew G Knepley /*@
5780be95d8f1SBarry Smith SNESSetNPC - Sets the nonlinear preconditioner to be used.
578131823bd8SMatthew G Knepley
5782c3339decSBarry Smith Collective
578331823bd8SMatthew G Knepley
578431823bd8SMatthew G Knepley Input Parameters:
5785f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
578662842358SBarry Smith - npc - the `SNES` nonlinear preconditioner object
578762842358SBarry Smith
578862842358SBarry Smith Options Database Key:
578962842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
579031823bd8SMatthew G Knepley
5791dc4c0fb0SBarry Smith Level: developer
5792dc4c0fb0SBarry Smith
579331823bd8SMatthew G Knepley Notes:
579462842358SBarry Smith This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
579531823bd8SMatthew G Knepley
5796f6dfbefdSBarry Smith Only some `SNESType` can use a nonlinear preconditioner
5797f6dfbefdSBarry Smith
5798420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
579931823bd8SMatthew G Knepley @*/
SNESSetNPC(SNES snes,SNES npc)5800d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5801d71ae5a4SJacob Faibussowitsch {
580231823bd8SMatthew G Knepley PetscFunctionBegin;
580331823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5804f6dfbefdSBarry Smith PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5805f6dfbefdSBarry Smith PetscCheckSameComm(snes, 1, npc, 2);
5806f6dfbefdSBarry Smith PetscCall(PetscObjectReference((PetscObject)npc));
58079566063dSJacob Faibussowitsch PetscCall(SNESDestroy(&snes->npc));
5808f6dfbefdSBarry Smith snes->npc = npc;
58093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
581031823bd8SMatthew G Knepley }
581131823bd8SMatthew G Knepley
581231823bd8SMatthew G Knepley /*@
5813f6dfbefdSBarry Smith SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
581431823bd8SMatthew G Knepley
58150b4b7b1cSBarry Smith Not Collective; but any changes to the obtained the `pc` object must be applied collectively
581631823bd8SMatthew G Knepley
581731823bd8SMatthew G Knepley Input Parameter:
5818f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
581931823bd8SMatthew G Knepley
582031823bd8SMatthew G Knepley Output Parameter:
582162842358SBarry Smith . pc - the `SNES` preconditioner context
582231823bd8SMatthew G Knepley
5823f6dfbefdSBarry Smith Options Database Key:
5824f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5825b5badacbSBarry Smith
58260b4b7b1cSBarry Smith Level: advanced
5827dc4c0fb0SBarry Smith
582895452b02SPatrick Sanan Notes:
58290b4b7b1cSBarry Smith If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
58300b4b7b1cSBarry Smith be used as the nonlinear preconditioner for the current `SNES`.
5831be95d8f1SBarry Smith
5832f6dfbefdSBarry Smith The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
583362842358SBarry Smith `SNES`. These may be overwritten if needed.
583462842358SBarry Smith
583562842358SBarry Smith Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5836951fe5abSBarry Smith
58371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
583831823bd8SMatthew G Knepley @*/
SNESGetNPC(SNES snes,SNES * pc)5839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5840d71ae5a4SJacob Faibussowitsch {
5841a64e098fSPeter Brune const char *optionsprefix;
584231823bd8SMatthew G Knepley
584331823bd8SMatthew G Knepley PetscFunctionBegin;
584431823bd8SMatthew G Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58454f572ea9SToby Isaac PetscAssertPointer(pc, 2);
5846efd4aadfSBarry Smith if (!snes->npc) {
58472a8381b2SBarry Smith PetscCtx ctx;
5848ec785e5bSStefano Zampini
58499566063dSJacob Faibussowitsch PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
58509566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
58519566063dSJacob Faibussowitsch PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58529566063dSJacob Faibussowitsch PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
58539566063dSJacob Faibussowitsch PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
58542a8381b2SBarry Smith if (snes->ops->ctxcompute) {
58552a8381b2SBarry Smith PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->ctxcompute, snes->ops->ctxdestroy));
5856fb87a551SStefano Zampini } else {
5857ec785e5bSStefano Zampini PetscCall(SNESGetApplicationContext(snes, &ctx));
5858ec785e5bSStefano Zampini PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5859fb87a551SStefano Zampini }
58609566063dSJacob Faibussowitsch PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
586131823bd8SMatthew G Knepley }
5862efd4aadfSBarry Smith *pc = snes->npc;
58633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
586431823bd8SMatthew G Knepley }
586531823bd8SMatthew G Knepley
58663ad1a0b9SPatrick Farrell /*@
58670b4b7b1cSBarry Smith SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
58683ad1a0b9SPatrick Farrell
58693ad1a0b9SPatrick Farrell Not Collective
58703ad1a0b9SPatrick Farrell
58713ad1a0b9SPatrick Farrell Input Parameter:
5872f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58733ad1a0b9SPatrick Farrell
58743ad1a0b9SPatrick Farrell Output Parameter:
5875420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58763ad1a0b9SPatrick Farrell
58773ad1a0b9SPatrick Farrell Level: developer
58783ad1a0b9SPatrick Farrell
58791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58803ad1a0b9SPatrick Farrell @*/
SNESHasNPC(SNES snes,PetscBool * has_npc)5881d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5882d71ae5a4SJacob Faibussowitsch {
58833ad1a0b9SPatrick Farrell PetscFunctionBegin;
58843ad1a0b9SPatrick Farrell PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5885835f2295SStefano Zampini PetscAssertPointer(has_npc, 2);
5886835f2295SStefano Zampini *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
58873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
58883ad1a0b9SPatrick Farrell }
58893ad1a0b9SPatrick Farrell
5890c40d0f55SPeter Brune /*@
589162842358SBarry Smith SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5892c40d0f55SPeter Brune
5893c3339decSBarry Smith Logically Collective
5894c40d0f55SPeter Brune
5895c40d0f55SPeter Brune Input Parameter:
5896f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5897c40d0f55SPeter Brune
5898c40d0f55SPeter Brune Output Parameter:
5899c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5900c40d0f55SPeter Brune .vb
59012d547940SBarry Smith PC_LEFT - left preconditioning
59022d547940SBarry Smith PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5903c40d0f55SPeter Brune .ve
5904c40d0f55SPeter Brune
5905f6dfbefdSBarry Smith Options Database Key:
590667b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5907c40d0f55SPeter Brune
5908dc4c0fb0SBarry Smith Level: intermediate
5909dc4c0fb0SBarry Smith
5910f6dfbefdSBarry Smith Note:
5911f6dfbefdSBarry Smith `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
59122d547940SBarry Smith
591362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5914c40d0f55SPeter Brune @*/
SNESSetNPCSide(SNES snes,PCSide side)5915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5916d71ae5a4SJacob Faibussowitsch {
5917c40d0f55SPeter Brune PetscFunctionBegin;
5918c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5919c40d0f55SPeter Brune PetscValidLogicalCollectiveEnum(snes, side, 2);
5920b552625fSStefano Zampini if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
592154c59aa7SJacob Faibussowitsch PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5922efd4aadfSBarry Smith snes->npcside = side;
59233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5924c40d0f55SPeter Brune }
5925c40d0f55SPeter Brune
5926c40d0f55SPeter Brune /*@
592762842358SBarry Smith SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5928c40d0f55SPeter Brune
5929c40d0f55SPeter Brune Not Collective
5930c40d0f55SPeter Brune
5931c40d0f55SPeter Brune Input Parameter:
5932f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5933c40d0f55SPeter Brune
5934c40d0f55SPeter Brune Output Parameter:
5935c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5936c40d0f55SPeter Brune .vb
5937f6dfbefdSBarry Smith `PC_LEFT` - left preconditioning
5938f6dfbefdSBarry Smith `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5939c40d0f55SPeter Brune .ve
5940c40d0f55SPeter Brune
5941c40d0f55SPeter Brune Level: intermediate
5942c40d0f55SPeter Brune
594362842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5944c40d0f55SPeter Brune @*/
SNESGetNPCSide(SNES snes,PCSide * side)5945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5946d71ae5a4SJacob Faibussowitsch {
5947c40d0f55SPeter Brune PetscFunctionBegin;
5948c40d0f55SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59494f572ea9SToby Isaac PetscAssertPointer(side, 2);
5950efd4aadfSBarry Smith *side = snes->npcside;
59513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5952c40d0f55SPeter Brune }
5953c40d0f55SPeter Brune
59549e764e56SPeter Brune /*@
59550b4b7b1cSBarry Smith SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
59569e764e56SPeter Brune
5957c3339decSBarry Smith Collective
59589e764e56SPeter Brune
59599e764e56SPeter Brune Input Parameters:
5960f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
59619e764e56SPeter Brune - linesearch - the linesearch object
59629e764e56SPeter Brune
5963dc4c0fb0SBarry Smith Level: developer
5964dc4c0fb0SBarry Smith
5965f6dfbefdSBarry Smith Note:
5966420bcc1bSBarry Smith This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
59679e764e56SPeter Brune to configure it using the API).
59689e764e56SPeter Brune
5969420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
59709e764e56SPeter Brune @*/
SNESSetLineSearch(SNES snes,SNESLineSearch linesearch)5971d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5972d71ae5a4SJacob Faibussowitsch {
59739e764e56SPeter Brune PetscFunctionBegin;
59749e764e56SPeter Brune PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5975f1c6b773SPeter Brune PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59769e764e56SPeter Brune PetscCheckSameComm(snes, 1, linesearch, 2);
59779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)linesearch));
59789566063dSJacob Faibussowitsch PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5979f5af7f23SKarl Rupp
59809e764e56SPeter Brune snes->linesearch = linesearch;
59813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
59829e764e56SPeter Brune }
5983