xref: /petsc/src/snes/impls/gs/snesgs.c (revision 66976f2f44dcc61d86a452a70219fb23b45d00f0)
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 
6c3339decSBarry Smith   Logically Collective
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 @*/
25d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNGSSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit)
26d71ae5a4SJacob Faibussowitsch {
27be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
28b6266c6eSPeter Brune 
29b6266c6eSPeter Brune   PetscFunctionBegin;
30b6266c6eSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31b6266c6eSPeter Brune 
3213bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
3308401ef6SPierre Jolivet     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
34b6266c6eSPeter Brune     gs->abstol = abstol;
35b6266c6eSPeter Brune   }
3613bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
370b121fc5SBarry 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);
38b6266c6eSPeter Brune     gs->rtol = rtol;
39b6266c6eSPeter Brune   }
4013bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
4108401ef6SPierre Jolivet     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
42b6266c6eSPeter Brune     gs->stol = stol;
43b6266c6eSPeter Brune   }
44b6266c6eSPeter Brune   if (maxit != PETSC_DEFAULT) {
4563a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
46b6266c6eSPeter Brune     gs->max_its = maxit;
47b6266c6eSPeter Brune   }
483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49b6266c6eSPeter Brune }
50b6266c6eSPeter Brune 
51b6266c6eSPeter Brune /*@
52f6dfbefdSBarry Smith   SNESNGSGetTolerances - Gets various parameters used in convergence tests for nonlinear Gauss-Seidel `SNESNCG`
53b6266c6eSPeter Brune 
54b6266c6eSPeter Brune   Not Collective
55b6266c6eSPeter Brune 
56b6266c6eSPeter Brune   Input Parameters:
57f6dfbefdSBarry Smith + snes  - the `SNES` context
58b6266c6eSPeter Brune . atol  - absolute convergence tolerance
59b6266c6eSPeter Brune . rtol  - relative convergence tolerance
60b6266c6eSPeter Brune . stol  - convergence tolerance in terms of the norm
61b6266c6eSPeter Brune            of the change in the solution between steps
62b6266c6eSPeter Brune - maxit - maximum number of iterations
63b6266c6eSPeter Brune 
642fe279fdSBarry Smith   Level: intermediate
652fe279fdSBarry Smith 
66f6dfbefdSBarry Smith   Note:
670298fd71SBarry Smith   The user can specify NULL for any parameter that is not needed.
68b6266c6eSPeter Brune 
69f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetTolerances()`
70b6266c6eSPeter Brune @*/
71d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNGSGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit)
72d71ae5a4SJacob Faibussowitsch {
73be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
74b6266c6eSPeter Brune 
75b6266c6eSPeter Brune   PetscFunctionBegin;
76b6266c6eSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
77b6266c6eSPeter Brune   if (atol) *atol = gs->abstol;
78b6266c6eSPeter Brune   if (rtol) *rtol = gs->rtol;
79b6266c6eSPeter Brune   if (stol) *stol = gs->stol;
80b6266c6eSPeter Brune   if (maxit) *maxit = gs->max_its;
813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82b6266c6eSPeter Brune }
836cd56b8bSPeter Brune 
846cd56b8bSPeter Brune /*@
85f6dfbefdSBarry Smith   SNESNGSSetSweeps - Sets the number of sweeps of nonlinear GS to use in `SNESNCG`
866cd56b8bSPeter Brune 
876cd56b8bSPeter Brune   Input Parameters:
88f6dfbefdSBarry Smith + snes   - the `SNES` context
89f6dfbefdSBarry Smith - sweeps - the number of sweeps of nonlinear GS to perform.
90f6dfbefdSBarry Smith 
91f6dfbefdSBarry Smith   Options Database Key:
92f6dfbefdSBarry Smith . -snes_ngs_sweeps <n> - Number of sweeps of nonlinear GS to apply
936cd56b8bSPeter Brune 
946cd56b8bSPeter Brune   Level: intermediate
956cd56b8bSPeter Brune 
96f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetNGS()`, `SNESGetNGS()`, `SNESSetNPC()`, `SNESNGSGetSweeps()`
976cd56b8bSPeter Brune @*/
98d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNGSSetSweeps(SNES snes, PetscInt sweeps)
99d71ae5a4SJacob Faibussowitsch {
100be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
1016cd56b8bSPeter Brune 
1026cd56b8bSPeter Brune   PetscFunctionBegin;
1036cd56b8bSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1046cd56b8bSPeter Brune   gs->sweeps = sweeps;
1053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1066cd56b8bSPeter Brune }
1076cd56b8bSPeter Brune 
1086cd56b8bSPeter Brune /*@
109f6dfbefdSBarry Smith   SNESNGSGetSweeps - Gets the number of sweeps nonlinear GS will use in `SNESNCG`
1106cd56b8bSPeter Brune 
1112fe279fdSBarry Smith   Input Parameter:
112f6dfbefdSBarry Smith . snes - the `SNES` context
1136cd56b8bSPeter Brune 
1142fe279fdSBarry Smith   Output Parameter:
115f6dfbefdSBarry Smith . sweeps - the number of sweeps of nonlinear GS to perform.
1166cd56b8bSPeter Brune 
1176cd56b8bSPeter Brune   Level: intermediate
1186cd56b8bSPeter Brune 
119f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESSetNGS()`, `SNESGetNGS()`, `SNESSetNPC()`, `SNESNGSSetSweeps()`
1206cd56b8bSPeter Brune @*/
121d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESNGSGetSweeps(SNES snes, PetscInt *sweeps)
122d71ae5a4SJacob Faibussowitsch {
123be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
1246cd56b8bSPeter Brune 
1256cd56b8bSPeter Brune   PetscFunctionBegin;
1266cd56b8bSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1276cd56b8bSPeter Brune   *sweeps = gs->sweeps;
1283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1296cd56b8bSPeter Brune }
1306cd56b8bSPeter Brune 
131*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESReset_NGS(SNES snes)
132d71ae5a4SJacob Faibussowitsch {
1338a86d3c5SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
1348a86d3c5SBarry Smith 
1353542a6bcSPeter Brune   PetscFunctionBegin;
1369566063dSJacob Faibussowitsch   PetscCall(ISColoringDestroy(&gs->coloring));
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1383542a6bcSPeter Brune }
1393542a6bcSPeter Brune 
140*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESDestroy_NGS(SNES snes)
141d71ae5a4SJacob Faibussowitsch {
1423542a6bcSPeter Brune   PetscFunctionBegin;
1439566063dSJacob Faibussowitsch   PetscCall(SNESReset_NGS(snes));
1449566063dSJacob Faibussowitsch   PetscCall(PetscFree(snes->data));
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1463542a6bcSPeter Brune }
1473542a6bcSPeter Brune 
148*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESSetUp_NGS(SNES snes)
149d71ae5a4SJacob Faibussowitsch {
150ef107cf5SPeter Brune   PetscErrorCode (*f)(SNES, Vec, Vec, void *);
151ef107cf5SPeter Brune 
1523542a6bcSPeter Brune   PetscFunctionBegin;
1539566063dSJacob Faibussowitsch   PetscCall(SNESGetNGS(snes, &f, NULL));
15448a46eb9SPierre Jolivet   if (!f) PetscCall(SNESSetNGS(snes, SNESComputeNGSDefaultSecant, NULL));
1553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1563542a6bcSPeter Brune }
1573542a6bcSPeter Brune 
158*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESSetFromOptions_NGS(SNES snes, PetscOptionItems *PetscOptionsObject)
159d71ae5a4SJacob Faibussowitsch {
160be95d8f1SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
161b6266c6eSPeter Brune   PetscInt  sweeps, max_its = PETSC_DEFAULT;
162b6266c6eSPeter Brune   PetscReal rtol = PETSC_DEFAULT, atol = PETSC_DEFAULT, stol = PETSC_DEFAULT;
163b6266c6eSPeter Brune   PetscBool flg, flg1, flg2, flg3;
1643542a6bcSPeter Brune 
1653542a6bcSPeter Brune   PetscFunctionBegin;
166d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SNES GS options");
1676cd56b8bSPeter Brune   /* GS Options */
1689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ngs_sweeps", "Number of sweeps of GS to apply", "SNESComputeGS", gs->sweeps, &sweeps, &flg));
1691baa6e33SBarry Smith   if (flg) PetscCall(SNESNGSSetSweeps(snes, sweeps));
1709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_atol", "Absolute residual tolerance for GS iteration", "SNESComputeGS", gs->abstol, &atol, &flg));
1719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_rtol", "Relative residual tolerance for GS iteration", "SNESComputeGS", gs->rtol, &rtol, &flg1));
1729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_stol", "Absolute update tolerance for GS iteration", "SNESComputeGS", gs->stol, &stol, &flg2));
1739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ngs_max_it", "Maximum number of sweeps of GS to apply", "SNESComputeGS", gs->max_its, &max_its, &flg3));
17448a46eb9SPierre Jolivet   if (flg || flg1 || flg2 || flg3) PetscCall(SNESNGSSetTolerances(snes, atol, rtol, stol, max_its));
175ef107cf5SPeter Brune   flg = PETSC_FALSE;
1769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ngs_secant", "Use finite difference secant approximation with coloring", "", flg, &flg, NULL));
177ef107cf5SPeter Brune   if (flg) {
1789566063dSJacob Faibussowitsch     PetscCall(SNESSetNGS(snes, SNESComputeNGSDefaultSecant, NULL));
1799566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference secant approximation with coloring\n"));
180ef107cf5SPeter Brune   }
1819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ngs_secant_h", "Differencing parameter for secant search", "", gs->h, &gs->h, NULL));
1829566063dSJacob 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));
183ef107cf5SPeter Brune 
184d0609cedSBarry Smith   PetscOptionsHeadEnd();
1853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1863542a6bcSPeter Brune }
1873542a6bcSPeter Brune 
188*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESView_NGS(SNES snes, PetscViewer viewer)
189d71ae5a4SJacob Faibussowitsch {
19098272f38SBarry Smith   PetscErrorCode (*f)(SNES, Vec, Vec, void *);
19198272f38SBarry Smith   SNES_NGS *gs = (SNES_NGS *)snes->data;
19298272f38SBarry Smith   PetscBool iascii;
19398272f38SBarry Smith 
1943542a6bcSPeter Brune   PetscFunctionBegin;
1959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19698272f38SBarry Smith   if (iascii) {
1979566063dSJacob Faibussowitsch     PetscCall(DMSNESGetNGS(snes->dm, &f, NULL));
19848a46eb9SPierre Jolivet     if (f == SNESComputeNGSDefaultSecant) PetscCall(PetscViewerASCIIPrintf(viewer, "  Use finite difference secant approximation with coloring with h = %g \n", (double)gs->h));
19998272f38SBarry Smith   }
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2013542a6bcSPeter Brune }
2023542a6bcSPeter Brune 
203*66976f2fSJacob Faibussowitsch static PetscErrorCode SNESSolve_NGS(SNES snes)
204d71ae5a4SJacob Faibussowitsch {
2053542a6bcSPeter Brune   Vec              F;
2063542a6bcSPeter Brune   Vec              X;
2073542a6bcSPeter Brune   Vec              B;
2083542a6bcSPeter Brune   PetscInt         i;
20906e07b1aSPeter Brune   PetscReal        fnorm;
210365a6726SPeter Brune   SNESNormSchedule normschedule;
2113542a6bcSPeter Brune 
2123542a6bcSPeter Brune   PetscFunctionBegin;
213c579b300SPatrick Farrell 
2140b121fc5SBarry 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);
215c579b300SPatrick Farrell 
2169566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(SNESCitation, &SNEScite));
2173542a6bcSPeter Brune   X = snes->vec_sol;
2183542a6bcSPeter Brune   F = snes->vec_func;
2193542a6bcSPeter Brune   B = snes->vec_rhs;
2203542a6bcSPeter Brune 
2219566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
222534ebe21SPeter Brune   snes->iter = 0;
223534ebe21SPeter Brune   snes->norm = 0.;
2249566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
225526b802eSJed Brown   snes->reason = SNES_CONVERGED_ITERATING;
226534ebe21SPeter Brune 
2279566063dSJacob Faibussowitsch   PetscCall(SNESGetNormSchedule(snes, &normschedule));
228365a6726SPeter Brune   if (normschedule == SNES_NORM_ALWAYS || normschedule == SNES_NORM_INITIAL_ONLY || normschedule == SNES_NORM_INITIAL_FINAL_ONLY) {
2293542a6bcSPeter Brune     /* compute the initial function and preconditioned update delX */
230e4ed7901SPeter Brune     if (!snes->vec_func_init_set) {
2319566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, X, F));
2321aa26658SKarl Rupp     } else snes->vec_func_init_set = PETSC_FALSE;
233e4ed7901SPeter Brune 
2349566063dSJacob Faibussowitsch     PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F||  */
235422a814eSBarry Smith     SNESCheckFunctionNorm(snes, fnorm);
2369566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
237e4ed7901SPeter Brune     snes->iter = 0;
2383542a6bcSPeter Brune     snes->norm = fnorm;
2399566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2409566063dSJacob Faibussowitsch     PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0));
2413542a6bcSPeter Brune 
2423542a6bcSPeter Brune     /* test convergence */
243d76a863bSStefano Zampini     PetscCall(SNESConverged(snes, 0, 0.0, 0.0, fnorm));
2442d157150SStefano Zampini     PetscCall(SNESMonitor(snes, 0, snes->norm));
2453ba16761SJacob Faibussowitsch     if (snes->reason) PetscFunctionReturn(PETSC_SUCCESS);
246534ebe21SPeter Brune   } else {
2479566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2489566063dSJacob Faibussowitsch     PetscCall(SNESLogConvergenceHistory(snes, snes->norm, 0));
249534ebe21SPeter Brune   }
250534ebe21SPeter Brune 
2513542a6bcSPeter Brune   /* Call general purpose update function */
252dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, update, snes->iter);
253534ebe21SPeter Brune 
2543542a6bcSPeter Brune   for (i = 0; i < snes->max_its; i++) {
2559566063dSJacob Faibussowitsch     PetscCall(SNESComputeNGS(snes, B, X));
2564b32a720SPeter Brune     /* only compute norms if requested or about to exit due to maximum iterations */
257365a6726SPeter Brune     if (normschedule == SNES_NORM_ALWAYS || ((i == snes->max_its - 1) && (normschedule == SNES_NORM_INITIAL_FINAL_ONLY || normschedule == SNES_NORM_FINAL_ONLY))) {
2589566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, X, F));
2599566063dSJacob Faibussowitsch       PetscCall(VecNorm(F, NORM_2, &fnorm)); /* fnorm <- ||F||  */
260422a814eSBarry Smith       SNESCheckFunctionNorm(snes, fnorm);
2612d157150SStefano Zampini     }
2623542a6bcSPeter Brune     /* Monitor convergence */
2639566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
2643542a6bcSPeter Brune     snes->iter = i + 1;
2653542a6bcSPeter Brune     snes->norm = fnorm;
2669566063dSJacob Faibussowitsch     PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
2672d157150SStefano Zampini     PetscCall(SNESLogConvergenceHistory(snes, snes->norm, snes->iter));
2683542a6bcSPeter Brune     /* Test for convergence */
2692d157150SStefano Zampini     PetscCall(SNESConverged(snes, snes->iter, 0.0, 0.0, fnorm));
2702d157150SStefano Zampini     PetscCall(SNESMonitor(snes, snes->iter, snes->norm));
2713ba16761SJacob Faibussowitsch     if (snes->reason) PetscFunctionReturn(PETSC_SUCCESS);
2723542a6bcSPeter Brune     /* Call general purpose update function */
273dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, update, snes->iter);
2743542a6bcSPeter Brune   }
2753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2763542a6bcSPeter Brune }
2773542a6bcSPeter Brune 
2783542a6bcSPeter Brune /*MC
279f6dfbefdSBarry Smith   SNESNGS - Either calls the user-provided solution routine provided with `SNESSetNGS()` or does a finite difference secant approximation
28098272f38SBarry Smith             using coloring.
2813542a6bcSPeter Brune 
2823542a6bcSPeter Brune    Level: advanced
2833542a6bcSPeter Brune 
284f6dfbefdSBarry Smith   Options Database Keys:
285f6dfbefdSBarry Smith +   -snes_ngs_sweeps <n> - Number of sweeps of nonlinear GS to apply
286f6dfbefdSBarry Smith .    -snes_ngs_atol <atol> - Absolute residual tolerance for nonlinear GS iteration
287f6dfbefdSBarry Smith .    -snes_ngs_rtol <rtol> - Relative residual tolerance for nonlinear GS iteration
288f6dfbefdSBarry Smith .    -snes_ngs_stol <stol> - Absolute update tolerance for nonlinear GS iteration
289f6dfbefdSBarry Smith .    -snes_ngs_max_it <maxit> - Maximum number of sweeps of nonlinea GS to apply
29098272f38SBarry Smith .    -snes_ngs_secant - Use pointwise secant local Jacobian approximation with coloring instead of user provided Gauss-Seidel routine, this is
291f6dfbefdSBarry Smith                         used by default if no user provided Gauss-Seidel routine is available. Requires either that a `DM` that can compute a coloring
29298272f38SBarry Smith                         is available or a Jacobian sparse matrix is provided (from which to get the coloring).
29378e24b28SBarry Smith .    -snes_ngs_secant_h <h> - Differencing parameter for secant approximation
29478e24b28SBarry Smith .    -snes_ngs_secant_mat_coloring - Use the graph coloring of the Jacobian for the secant GS even if a DM is available.
295a5b23f4aSJose E. Roman -    -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - how often the residual norms are computed
29698272f38SBarry Smith 
2973542a6bcSPeter Brune   Notes:
298f6dfbefdSBarry Smith   the Gauss-Seidel smoother is inherited through composition.  If a solver has been created with `SNESGetNPC()`, it will have
2993542a6bcSPeter Brune   its parent's Gauss-Seidel routine associated with it.
3003542a6bcSPeter Brune 
301f6dfbefdSBarry Smith   By default this routine computes the solution norm at each iteration, this can be time consuming, you can turn this off with `SNESSetNormSchedule()`
302f6dfbefdSBarry Smith   or -snes_norm_schedule none
303f6dfbefdSBarry Smith 
3044f02bc6aSBarry Smith    References:
305606c0280SSatish Balay .  * - Peter R. Brune, Matthew G. Knepley, Barry F. Smith, and Xuemin Tu, "Composing Scalable Nonlinear Algebraic Solvers",
3064f02bc6aSBarry Smith    SIAM Review, 57(4), 2015
3074f02bc6aSBarry Smith 
308f6dfbefdSBarry Smith .seealso: `SNESNCG`, `SNESCreate()`, `SNES`, `SNESSetType()`, `SNESSetNGS()`, `SNESType`, `SNESNGSSetSweeps()`, `SNESNGSSetTolerances()`,
309db781477SPatrick Sanan           `SNESSetNormSchedule()`
3103542a6bcSPeter Brune M*/
3113542a6bcSPeter Brune 
312d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode SNESCreate_NGS(SNES snes)
313d71ae5a4SJacob Faibussowitsch {
314be95d8f1SBarry Smith   SNES_NGS *gs;
3153542a6bcSPeter Brune 
3163542a6bcSPeter Brune   PetscFunctionBegin;
317be95d8f1SBarry Smith   snes->ops->destroy        = SNESDestroy_NGS;
318be95d8f1SBarry Smith   snes->ops->setup          = SNESSetUp_NGS;
319be95d8f1SBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_NGS;
320be95d8f1SBarry Smith   snes->ops->view           = SNESView_NGS;
321be95d8f1SBarry Smith   snes->ops->solve          = SNESSolve_NGS;
322be95d8f1SBarry Smith   snes->ops->reset          = SNESReset_NGS;
3233542a6bcSPeter Brune 
3243542a6bcSPeter Brune   snes->usesksp = PETSC_FALSE;
325efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
3263542a6bcSPeter Brune 
3274fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
3284fc747eaSLawrence Mitchell 
32988976e71SPeter Brune   if (!snes->tolerancesset) {
3300e444f03SPeter Brune     snes->max_its   = 10000;
3310e444f03SPeter Brune     snes->max_funcs = 10000;
33288976e71SPeter Brune   }
3330e444f03SPeter Brune 
3344dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&gs));
3356cd56b8bSPeter Brune 
3366cd56b8bSPeter Brune   gs->sweeps  = 1;
337b6266c6eSPeter Brune   gs->rtol    = 1e-5;
33878e24b28SBarry Smith   gs->abstol  = PETSC_MACHINE_EPSILON;
33978e24b28SBarry Smith   gs->stol    = 1000 * PETSC_MACHINE_EPSILON;
340b6266c6eSPeter Brune   gs->max_its = 50;
34178e24b28SBarry Smith   gs->h       = PETSC_SQRT_MACHINE_EPSILON;
3426cd56b8bSPeter Brune 
3433542a6bcSPeter Brune   snes->data = (void *)gs;
3443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3453542a6bcSPeter Brune }
346