xref: /petsc/src/snes/impls/gs/snesgs.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
1737a7e12SPeter Brune #include <../src/snes/impls/gs/gsimpl.h> /*I "petscsnes.h"  I*/
26cd56b8bSPeter Brune 
3b6266c6eSPeter Brune /*@
4f6dfbefdSBarry Smith    SNESNGSSetTolerances - Sets various parameters used in convergence tests for nonlinear Gauss-Seidel `SNESNCG`
5b6266c6eSPeter Brune 
6f6dfbefdSBarry Smith    Logically Collective on snes
7b6266c6eSPeter Brune 
8b6266c6eSPeter Brune    Input Parameters:
9f6dfbefdSBarry Smith +  snes - the `SNES` context
10b6266c6eSPeter Brune .  abstol - absolute convergence tolerance
11b6266c6eSPeter Brune .  rtol - relative convergence tolerance
12b6266c6eSPeter Brune .  stol -  convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
13b6266c6eSPeter Brune -  maxit - maximum number of iterations
14b6266c6eSPeter Brune 
15b6266c6eSPeter Brune    Options Database Keys:
16be95d8f1SBarry Smith +    -snes_ngs_atol <abstol> - Sets abstol
17be95d8f1SBarry Smith .    -snes_ngs_rtol <rtol> - Sets rtol
18be95d8f1SBarry Smith .    -snes_ngs_stol <stol> - Sets stol
19b6266c6eSPeter Brune -    -snes_max_it <maxit> - Sets maxit
20b6266c6eSPeter Brune 
21b6266c6eSPeter Brune    Level: intermediate
22b6266c6eSPeter Brune 
23f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetTrustRegionTolerance()`
24b6266c6eSPeter Brune @*/
259371c9d4SSatish Balay PetscErrorCode SNESNGSSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit) {
26be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
27b6266c6eSPeter Brune 
28b6266c6eSPeter Brune   PetscFunctionBegin;
29b6266c6eSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30b6266c6eSPeter Brune 
31b6266c6eSPeter Brune   if (abstol != PETSC_DEFAULT) {
3208401ef6SPierre Jolivet     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
33b6266c6eSPeter Brune     gs->abstol = abstol;
34b6266c6eSPeter Brune   }
35b6266c6eSPeter Brune   if (rtol != PETSC_DEFAULT) {
360b121fc5SBarry Smith     PetscCheck(rtol >= 0.0 && rtol < 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative and less than 1.0", (double)rtol);
37b6266c6eSPeter Brune     gs->rtol = rtol;
38b6266c6eSPeter Brune   }
39b6266c6eSPeter Brune   if (stol != PETSC_DEFAULT) {
4008401ef6SPierre Jolivet     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
41b6266c6eSPeter Brune     gs->stol = stol;
42b6266c6eSPeter Brune   }
43b6266c6eSPeter Brune   if (maxit != PETSC_DEFAULT) {
4463a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
45b6266c6eSPeter Brune     gs->max_its = maxit;
46b6266c6eSPeter Brune   }
47b6266c6eSPeter Brune   PetscFunctionReturn(0);
48b6266c6eSPeter Brune }
49b6266c6eSPeter Brune 
50b6266c6eSPeter Brune /*@
51f6dfbefdSBarry Smith    SNESNGSGetTolerances - Gets various parameters used in convergence tests for nonlinear Gauss-Seidel `SNESNCG`
52b6266c6eSPeter Brune 
53b6266c6eSPeter Brune    Not Collective
54b6266c6eSPeter Brune 
55b6266c6eSPeter Brune    Input Parameters:
56f6dfbefdSBarry Smith +  snes - the `SNES` context
57b6266c6eSPeter Brune .  atol - absolute convergence tolerance
58b6266c6eSPeter Brune .  rtol - relative convergence tolerance
59b6266c6eSPeter Brune .  stol -  convergence tolerance in terms of the norm
60b6266c6eSPeter Brune            of the change in the solution between steps
61b6266c6eSPeter Brune -  maxit - maximum number of iterations
62b6266c6eSPeter Brune 
63f6dfbefdSBarry Smith    Note:
640298fd71SBarry Smith    The user can specify NULL for any parameter that is not needed.
65b6266c6eSPeter Brune 
66b6266c6eSPeter Brune    Level: intermediate
67b6266c6eSPeter Brune 
68f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetTolerances()`
69b6266c6eSPeter Brune @*/
709371c9d4SSatish Balay PetscErrorCode SNESNGSGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit) {
71be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
72b6266c6eSPeter Brune 
73b6266c6eSPeter Brune   PetscFunctionBegin;
74b6266c6eSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
75b6266c6eSPeter Brune   if (atol) *atol = gs->abstol;
76b6266c6eSPeter Brune   if (rtol) *rtol = gs->rtol;
77b6266c6eSPeter Brune   if (stol) *stol = gs->stol;
78b6266c6eSPeter Brune   if (maxit) *maxit = gs->max_its;
79b6266c6eSPeter Brune   PetscFunctionReturn(0);
80b6266c6eSPeter Brune }
816cd56b8bSPeter Brune 
826cd56b8bSPeter Brune /*@
83f6dfbefdSBarry Smith    SNESNGSSetSweeps - Sets the number of sweeps of nonlinear GS to use in `SNESNCG`
846cd56b8bSPeter Brune 
856cd56b8bSPeter Brune    Input Parameters:
86f6dfbefdSBarry Smith +  snes   - the `SNES` context
87f6dfbefdSBarry Smith -  sweeps  - the number of sweeps of nonlinear GS to perform.
88f6dfbefdSBarry Smith 
89f6dfbefdSBarry Smith   Options Database Key:
90f6dfbefdSBarry Smith .   -snes_ngs_sweeps <n> - Number of sweeps of nonlinear GS to apply
916cd56b8bSPeter Brune 
926cd56b8bSPeter Brune    Level: intermediate
936cd56b8bSPeter Brune 
94f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetNGS()`, `SNESGetNGS()`, `SNESSetNPC()`, `SNESNGSGetSweeps()`
956cd56b8bSPeter Brune @*/
966cd56b8bSPeter Brune 
979371c9d4SSatish Balay PetscErrorCode SNESNGSSetSweeps(SNES snes, PetscInt sweeps) {
98be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
996cd56b8bSPeter Brune 
1006cd56b8bSPeter Brune   PetscFunctionBegin;
1016cd56b8bSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1026cd56b8bSPeter Brune   gs->sweeps = sweeps;
1036cd56b8bSPeter Brune   PetscFunctionReturn(0);
1046cd56b8bSPeter Brune }
1056cd56b8bSPeter Brune 
1066cd56b8bSPeter Brune /*@
107f6dfbefdSBarry Smith    SNESNGSGetSweeps - Gets the number of sweeps nonlinear GS will use in `SNESNCG`
1086cd56b8bSPeter Brune 
1096cd56b8bSPeter Brune    Input Parameters:
110f6dfbefdSBarry Smith .  snes   - the `SNES` context
1116cd56b8bSPeter Brune 
1126cd56b8bSPeter Brune    Output Parameters:
113f6dfbefdSBarry Smith .  sweeps  - the number of sweeps of nonlinear GS to perform.
1146cd56b8bSPeter Brune 
1156cd56b8bSPeter Brune    Level: intermediate
1166cd56b8bSPeter Brune 
117f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetNGS()`, `SNESGetNGS()`, `SNESSetNPC()`, `SNESNGSSetSweeps()`
1186cd56b8bSPeter Brune @*/
1199371c9d4SSatish Balay PetscErrorCode SNESNGSGetSweeps(SNES snes, PetscInt *sweeps) {
120be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
1216cd56b8bSPeter Brune 
1226cd56b8bSPeter Brune   PetscFunctionBegin;
1236cd56b8bSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1246cd56b8bSPeter Brune   *sweeps = gs->sweeps;
1256cd56b8bSPeter Brune   PetscFunctionReturn(0);
1266cd56b8bSPeter Brune }
1276cd56b8bSPeter Brune 
1289371c9d4SSatish Balay PetscErrorCode SNESReset_NGS(SNES snes) {
1298a86d3c5SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
1308a86d3c5SBarry Smith 
1313542a6bcSPeter Brune   PetscFunctionBegin;
1329566063dSJacob Faibussowitsch   PetscCall(ISColoringDestroy(&gs->coloring));
1333542a6bcSPeter Brune   PetscFunctionReturn(0);
1343542a6bcSPeter Brune }
1353542a6bcSPeter Brune 
1369371c9d4SSatish Balay PetscErrorCode SNESDestroy_NGS(SNES snes) {
1373542a6bcSPeter Brune   PetscFunctionBegin;
1389566063dSJacob Faibussowitsch   PetscCall(SNESReset_NGS(snes));
1399566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
1403542a6bcSPeter Brune   PetscFunctionReturn(0);
1413542a6bcSPeter Brune }
1423542a6bcSPeter Brune 
1439371c9d4SSatish Balay PetscErrorCode SNESSetUp_NGS(SNES snes) {
144ef107cf5SPeter Brune   PetscErrorCode (*f)(SNES, Vec, Vec, void *);
145ef107cf5SPeter Brune 
1463542a6bcSPeter Brune   PetscFunctionBegin;
1479566063dSJacob Faibussowitsch   PetscCall(SNESGetNGS(snes, &f, NULL));
14848a46eb9SPierre Jolivet   if (!f) PetscCall(SNESSetNGS(snes, SNESComputeNGSDefaultSecant, NULL));
1493542a6bcSPeter Brune   PetscFunctionReturn(0);
1503542a6bcSPeter Brune }
1513542a6bcSPeter Brune 
1529371c9d4SSatish Balay PetscErrorCode SNESSetFromOptions_NGS(SNES snes, PetscOptionItems *PetscOptionsObject) {
153be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
154b6266c6eSPeter Brune   PetscInt  sweeps, max_its = PETSC_DEFAULT;
155b6266c6eSPeter Brune   PetscReal rtol = PETSC_DEFAULT, atol = PETSC_DEFAULT, stol = PETSC_DEFAULT;
156b6266c6eSPeter Brune   PetscBool flg, flg1, flg2, flg3;
1573542a6bcSPeter Brune 
1583542a6bcSPeter Brune   PetscFunctionBegin;
159d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SNES GS options");
1606cd56b8bSPeter Brune   /* GS Options */
1619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ngs_sweeps", "Number of sweeps of GS to apply", "SNESComputeGS", gs->sweeps, &sweeps, &flg));
1621baa6e33SBarry Smith   if (flg) PetscCall(SNESNGSSetSweeps(snes, sweeps));
1639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_atol", "Absolute residual tolerance for GS iteration", "SNESComputeGS", gs->abstol, &atol, &flg));
1649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_rtol", "Relative residual tolerance for GS iteration", "SNESComputeGS", gs->rtol, &rtol, &flg1));
1659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_stol", "Absolute update tolerance for GS iteration", "SNESComputeGS", gs->stol, &stol, &flg2));
1669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ngs_max_it", "Maximum number of sweeps of GS to apply", "SNESComputeGS", gs->max_its, &max_its, &flg3));
16748a46eb9SPierre Jolivet   if (flg || flg1 || flg2 || flg3) PetscCall(SNESNGSSetTolerances(snes, atol, rtol, stol, max_its));
168ef107cf5SPeter Brune   flg = PETSC_FALSE;
1699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ngs_secant", "Use finite difference secant approximation with coloring", "", flg, &flg, NULL));
170ef107cf5SPeter Brune   if (flg) {
1719566063dSJacob Faibussowitsch     PetscCall(SNESSetNGS(snes, SNESComputeNGSDefaultSecant, NULL));
1729566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference secant approximation with coloring\n"));
173ef107cf5SPeter Brune   }
1749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_secant_h", "Differencing parameter for secant search", "", gs->h, &gs->h, NULL));
1759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ngs_secant_mat_coloring", "Use the graph coloring of the Jacobian for the secant GS", "", gs->secant_mat, &gs->secant_mat, &flg));
176ef107cf5SPeter Brune 
177d0609cedSBarry Smith   PetscOptionsHeadEnd();
1783542a6bcSPeter Brune   PetscFunctionReturn(0);
1793542a6bcSPeter Brune }
1803542a6bcSPeter Brune 
1819371c9d4SSatish Balay PetscErrorCode SNESView_NGS(SNES snes, PetscViewer viewer) {
18298272f38SBarry Smith   PetscErrorCode (*f)(SNES, Vec, Vec, void *);
18398272f38SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
18498272f38SBarry Smith   PetscBool iascii;
18598272f38SBarry Smith 
1863542a6bcSPeter Brune   PetscFunctionBegin;
1879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18898272f38SBarry Smith   if (iascii) {
1899566063dSJacob Faibussowitsch     PetscCall(DMSNESGetNGS(snes->dm, &f, NULL));
19048a46eb9SPierre Jolivet     if (f == SNESComputeNGSDefaultSecant) PetscCall(PetscViewerASCIIPrintf(viewer, "  Use finite difference secant approximation with coloring with h = %g \n", (double)gs->h));
19198272f38SBarry Smith   }
1923542a6bcSPeter Brune   PetscFunctionReturn(0);
1933542a6bcSPeter Brune }
1943542a6bcSPeter Brune 
1959371c9d4SSatish Balay PetscErrorCode SNESSolve_NGS(SNES snes) {
1963542a6bcSPeter Brune   Vec              F;
1973542a6bcSPeter Brune   Vec              X;
1983542a6bcSPeter Brune   Vec              B;
1993542a6bcSPeter Brune   PetscInt         i;
20006e07b1aSPeter Brune   PetscReal        fnorm;
201365a6726SPeter Brune   SNESNormSchedule normschedule;
2023542a6bcSPeter Brune 
2033542a6bcSPeter Brune   PetscFunctionBegin;
204c579b300SPatrick Farrell 
2050b121fc5SBarry Smith   PetscCheck(!snes->xl && !snes->xu && !snes->ops->computevariablebounds, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name);
206c579b300SPatrick Farrell 
2079566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(SNESCitation, &SNEScite));
2083542a6bcSPeter Brune   X = snes->vec_sol;
2093542a6bcSPeter Brune   F = snes->vec_func;
2103542a6bcSPeter Brune   B = snes->vec_rhs;
2113542a6bcSPeter Brune 
2129566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
213534ebe21SPeter Brune   snes->iter = 0;
214534ebe21SPeter Brune   snes->norm = 0.;
2159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
216526b802eSJed Brown   snes->reason = SNES_CONVERGED_ITERATING;
217534ebe21SPeter Brune 
2189566063dSJacob Faibussowitsch   PetscCall(SNESGetNormSchedule(snes, &normschedule));
219365a6726SPeter Brune   if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY) {
2203542a6bcSPeter Brune     /* compute the initial function and preconditioned update delX */
221e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
2229566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, X, F));
2231aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
224e4ed7901SPeter Brune 
2259566063dSJacob Faibussowitsch     PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F||  */
226422a814eSBarry Smith     SNESCheckFunctionNorm(snes, fnorm);
2279566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
228e4ed7901SPeter Brune     snes->iter = 0;
2293542a6bcSPeter Brune     snes->norm = fnorm;
2309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2319566063dSJacob Faibussowitsch     PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0));
2329566063dSJacob Faibussowitsch     PetscCall(SNESMonitor(snes, 0, snes->norm));
2333542a6bcSPeter Brune 
2343542a6bcSPeter Brune     /* test convergence */
235dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, converged, 0, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP);
2363542a6bcSPeter Brune     if (snes->reason) PetscFunctionReturn(0);
237534ebe21SPeter Brune   } else {
2389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2399566063dSJacob Faibussowitsch     PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0));
240534ebe21SPeter Brune   }
241534ebe21SPeter Brune 
2423542a6bcSPeter Brune   /* Call general purpose update function */
243dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, update, snes->iter);
244534ebe21SPeter Brune 
2453542a6bcSPeter Brune   for (i = 0; i < snes->max_its; i++) {
2469566063dSJacob Faibussowitsch     PetscCall(SNESComputeNGS(snes, B, X));
2474b32a720SPeter Brune     /* only compute norms if requested or about to exit due to maximum iterations */
248365a6726SPeter Brune     if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) {
2499566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, X, F));
2509566063dSJacob Faibussowitsch       PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F||  */
251422a814eSBarry Smith       SNESCheckFunctionNorm(snes, fnorm);
2523542a6bcSPeter Brune       /* Monitor convergence */
2539566063dSJacob Faibussowitsch       PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
2543542a6bcSPeter Brune       snes->iter = i + 1;
2553542a6bcSPeter Brune       snes->norm = fnorm;
2569566063dSJacob Faibussowitsch       PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2579566063dSJacob Faibussowitsch       PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0));
2589566063dSJacob Faibussowitsch       PetscCall(SNESMonitor(snes, snes->iter, snes->norm));
259ac4a6415SMatthew G. Knepley     }
2603542a6bcSPeter Brune     /* Test for convergence */
261dbbe0bcdSBarry Smith     if (normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, snes->iter, 0.0, 0.0, fnorm, &snes->reason, snes->cnvP);
2623542a6bcSPeter Brune     if (snes->reason) PetscFunctionReturn(0);
2633542a6bcSPeter Brune     /* Call general purpose update function */
264dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, update, snes->iter);
2653542a6bcSPeter Brune   }
266365a6726SPeter Brune   if (normschedule == SNES_NORM_ALWAYS) {
267534ebe21SPeter Brune     if (i == snes->max_its) {
26863a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
269534ebe21SPeter Brune       if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
270534ebe21SPeter Brune     }
2711aa26658SKarl Rupp   } else if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; /* GS is meant to be used as a preconditioner */
2723542a6bcSPeter Brune   PetscFunctionReturn(0);
2733542a6bcSPeter Brune }
2743542a6bcSPeter Brune 
2753542a6bcSPeter Brune /*MC
276f6dfbefdSBarry Smith   SNESNGS - Either calls the user-provided solution routine provided with `SNESSetNGS()` or does a finite difference secant approximation
27798272f38SBarry Smith             using coloring.
2783542a6bcSPeter Brune 
2793542a6bcSPeter Brune    Level: advanced
2803542a6bcSPeter Brune 
281f6dfbefdSBarry Smith   Options Database Keys:
282f6dfbefdSBarry Smith +   -snes_ngs_sweeps <n> - Number of sweeps of nonlinear GS to apply
283f6dfbefdSBarry Smith .    -snes_ngs_atol <atol> - Absolute residual tolerance for nonlinear GS iteration
284f6dfbefdSBarry Smith .    -snes_ngs_rtol <rtol> - Relative residual tolerance for nonlinear GS iteration
285f6dfbefdSBarry Smith .    -snes_ngs_stol <stol> - Absolute update tolerance for nonlinear GS iteration
286f6dfbefdSBarry Smith .    -snes_ngs_max_it <maxit> - Maximum number of sweeps of nonlinea GS to apply
28798272f38SBarry Smith .    -snes_ngs_secant - Use pointwise secant local Jacobian approximation with coloring instead of user provided Gauss-Seidel routine, this is
288f6dfbefdSBarry Smith                         used by default if no user provided Gauss-Seidel routine is available. Requires either that a `DM` that can compute a coloring
28998272f38SBarry Smith                         is available or a Jacobian sparse matrix is provided (from which to get the coloring).
29078e24b28SBarry Smith .    -snes_ngs_secant_h <h> - Differencing parameter for secant approximation
29178e24b28SBarry Smith .    -snes_ngs_secant_mat_coloring - Use the graph coloring of the Jacobian for the secant GS even if a DM is available.
292a5b23f4aSJose E. Roman -    -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - how often the residual norms are computed
29398272f38SBarry Smith 
2943542a6bcSPeter Brune   Notes:
295f6dfbefdSBarry Smith   the Gauss-Seidel smoother is inherited through composition.  If a solver has been created with `SNESGetNPC()`, it will have
2963542a6bcSPeter Brune   its parent's Gauss-Seidel routine associated with it.
2973542a6bcSPeter Brune 
298f6dfbefdSBarry Smith   By default this routine computes the solution norm at each iteration, this can be time consuming, you can turn this off with `SNESSetNormSchedule()`
299f6dfbefdSBarry Smith   or -snes_norm_schedule none
300f6dfbefdSBarry Smith 
3014f02bc6aSBarry Smith    References:
302606c0280SSatish Balay .  * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
3034f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
3044f02bc6aSBarry Smith 
305f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESSetNGS()`, `SNESType`, `SNESNGSSetSweeps()`, `SNESNGSSetTolerances()`,
306db781477SPatrick Sanan           `SNESSetNormSchedule()`
3073542a6bcSPeter Brune M*/
3083542a6bcSPeter Brune 
3099371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode SNESCreate_NGS(SNES snes) {
310be95d8f1SBarry Smith   SNES_NGS *gs;
3113542a6bcSPeter Brune 
3123542a6bcSPeter Brune   PetscFunctionBegin;
313be95d8f1SBarry Smith   snes->ops->destroy        = SNESDestroy_NGS;
314be95d8f1SBarry Smith   snes->ops->setup          = SNESSetUp_NGS;
315be95d8f1SBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_NGS;
316be95d8f1SBarry Smith   snes->ops->view           = SNESView_NGS;
317be95d8f1SBarry Smith   snes->ops->solve          = SNESSolve_NGS;
318be95d8f1SBarry Smith   snes->ops->reset          = SNESReset_NGS;
3193542a6bcSPeter Brune 
3203542a6bcSPeter Brune   snes->usesksp = PETSC_FALSE;
321efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
3223542a6bcSPeter Brune 
3234fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
3244fc747eaSLawrence Mitchell 
32588976e71SPeter Brune   if (!snes->tolerancesset) {
3260e444f03SPeter Brune     snes->max_its   = 10000;
3270e444f03SPeter Brune     snes->max_funcs = 10000;
32888976e71SPeter Brune   }
3290e444f03SPeter Brune 
330*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&gs));
3316cd56b8bSPeter Brune 
3326cd56b8bSPeter Brune   gs->sweeps  = 1;
333b6266c6eSPeter Brune   gs->rtol    = 1e-5;
33478e24b28SBarry Smith   gs->abstol  = PETSC_MACHINE_EPSILON;
33578e24b28SBarry Smith   gs->stol    = 1000 * PETSC_MACHINE_EPSILON;
336b6266c6eSPeter Brune   gs->max_its = 50;
33778e24b28SBarry Smith   gs->h       = PETSC_SQRT_MACHINE_EPSILON;
3386cd56b8bSPeter Brune 
3393542a6bcSPeter Brune   snes->data = (void *)gs;
3403542a6bcSPeter Brune   PetscFunctionReturn(0);
3413542a6bcSPeter Brune }
342