xref: /petsc/src/snes/interface/snesut.c (revision 3a7fca6b988f1faea172e46abdf950477dbfaf76)
1*3a7fca6bSBarry Smith /*$Id: snesut.c,v 1.64 2001/04/10 19:36:48 bsmith Exp bsmith $*/
2e7e93795SLois Curfman McInnes 
3e090d566SSatish Balay #include "src/snes/snesimpl.h"       /*I   "petscsnes.h"   I*/
4e7e93795SLois Curfman McInnes 
54a2ae208SSatish Balay #undef __FUNCT__
64a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewMonitor"
73f1db9ecSBarry Smith /*@C
836851e7fSLois Curfman McInnes    SNESVecViewMonitor - Monitors progress of the SNES solvers by calling
936851e7fSLois Curfman McInnes    VecView() for the approximate solution at each iteration.
103f1db9ecSBarry Smith 
113f1db9ecSBarry Smith    Collective on SNES
123f1db9ecSBarry Smith 
133f1db9ecSBarry Smith    Input Parameters:
143f1db9ecSBarry Smith +  snes - the SNES context
153f1db9ecSBarry Smith .  its - iteration number
163f1db9ecSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
173f1db9ecSBarry Smith -  dummy - either a viewer or PETSC_NULL
183f1db9ecSBarry Smith 
1936851e7fSLois Curfman McInnes    Level: intermediate
203f1db9ecSBarry Smith 
2136851e7fSLois Curfman McInnes .keywords: SNES, nonlinear, vector, monitor, view
223f1db9ecSBarry Smith 
2336851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
243f1db9ecSBarry Smith @*/
25329f5518SBarry Smith int SNESVecViewMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
263f1db9ecSBarry Smith {
273f1db9ecSBarry Smith   int         ierr;
283f1db9ecSBarry Smith   Vec         x;
29b0a32e0cSBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
303f1db9ecSBarry Smith 
313f1db9ecSBarry Smith   PetscFunctionBegin;
323f1db9ecSBarry Smith   ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr);
333f1db9ecSBarry Smith   if (!viewer) {
343f1db9ecSBarry Smith     MPI_Comm comm;
353f1db9ecSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
36b0a32e0cSBarry Smith     viewer = PETSC_VIEWER_DRAW_(comm);
373f1db9ecSBarry Smith   }
383f1db9ecSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
393f1db9ecSBarry Smith 
403f1db9ecSBarry Smith   PetscFunctionReturn(0);
413f1db9ecSBarry Smith }
423f1db9ecSBarry Smith 
434a2ae208SSatish Balay #undef __FUNCT__
444a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewUpdateMonitor"
45d132466eSBarry Smith /*@C
467c922b88SBarry Smith    SNESVecViewUpdateMonitor - Monitors progress of the SNES solvers by calling
47d132466eSBarry Smith    VecView() for the UPDATE to the solution at each iteration.
48d132466eSBarry Smith 
49d132466eSBarry Smith    Collective on SNES
50d132466eSBarry Smith 
51d132466eSBarry Smith    Input Parameters:
52d132466eSBarry Smith +  snes - the SNES context
53d132466eSBarry Smith .  its - iteration number
54d132466eSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
55d132466eSBarry Smith -  dummy - either a viewer or PETSC_NULL
56d132466eSBarry Smith 
57d132466eSBarry Smith    Level: intermediate
58d132466eSBarry Smith 
59d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view
60d132466eSBarry Smith 
61d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
62d132466eSBarry Smith @*/
63329f5518SBarry Smith int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
64d132466eSBarry Smith {
65d132466eSBarry Smith   int         ierr;
66d132466eSBarry Smith   Vec         x;
67b0a32e0cSBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
68d132466eSBarry Smith 
69d132466eSBarry Smith   PetscFunctionBegin;
70d132466eSBarry Smith   ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr);
71d132466eSBarry Smith   if (!viewer) {
72d132466eSBarry Smith     MPI_Comm comm;
73d132466eSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
74b0a32e0cSBarry Smith     viewer = PETSC_VIEWER_DRAW_(comm);
75d132466eSBarry Smith   }
76d132466eSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
77d132466eSBarry Smith 
78d132466eSBarry Smith   PetscFunctionReturn(0);
79d132466eSBarry Smith }
80d132466eSBarry Smith 
814a2ae208SSatish Balay #undef __FUNCT__
824a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultMonitor"
834b828684SBarry Smith /*@C
84f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
85e7e93795SLois Curfman McInnes 
86c7afd0dbSLois Curfman McInnes    Collective on SNES
87c7afd0dbSLois Curfman McInnes 
88e7e93795SLois Curfman McInnes    Input Parameters:
89c7afd0dbSLois Curfman McInnes +  snes - the SNES context
90e7e93795SLois Curfman McInnes .  its - iteration number
91e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
92c7afd0dbSLois Curfman McInnes -  dummy - unused context
93fee21e36SBarry Smith 
94e7e93795SLois Curfman McInnes    Notes:
95e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
96e7e93795SLois Curfman McInnes    residual norm at each iteration.
97e7e93795SLois Curfman McInnes 
98e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
99e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
100e7e93795SLois Curfman McInnes 
10136851e7fSLois Curfman McInnes    Level: intermediate
10236851e7fSLois Curfman McInnes 
103e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
104e7e93795SLois Curfman McInnes 
10536851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor()
106e7e93795SLois Curfman McInnes @*/
107329f5518SBarry Smith int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
108e7e93795SLois Curfman McInnes {
109d132466eSBarry Smith   int         ierr;
110b0a32e0cSBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
111d132466eSBarry Smith 
1123a40ed3dSBarry Smith   PetscFunctionBegin;
113b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm);
1147c922b88SBarry Smith 
11576be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
116a0e26f09SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
11776be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
118a0e26f09SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function value %14.12e, Gradient norm %14.12e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
11929bbc08cSBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class");
1203a40ed3dSBarry Smith   PetscFunctionReturn(0);
121e7e93795SLois Curfman McInnes }
1223f1db9ecSBarry Smith 
123*3a7fca6bSBarry Smith #undef __FUNCT__
124*3a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitor"
125*3a7fca6bSBarry Smith /*@C
126*3a7fca6bSBarry Smith    SNESRatioMonitor - Monitoring progress of the SNES solvers, prints ratio
127*3a7fca6bSBarry Smith       of residual norm at each iteration to previous
128*3a7fca6bSBarry Smith 
129*3a7fca6bSBarry Smith    Collective on SNES
130*3a7fca6bSBarry Smith 
131*3a7fca6bSBarry Smith    Input Parameters:
132*3a7fca6bSBarry Smith +  snes - the SNES context
133*3a7fca6bSBarry Smith .  its - iteration number
134*3a7fca6bSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
135*3a7fca6bSBarry Smith -  dummy - unused context
136*3a7fca6bSBarry Smith 
137*3a7fca6bSBarry Smith    Level: intermediate
138*3a7fca6bSBarry Smith 
139*3a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm
140*3a7fca6bSBarry Smith 
141*3a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor()
142*3a7fca6bSBarry Smith @*/
143*3a7fca6bSBarry Smith int SNESRatioMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
144*3a7fca6bSBarry Smith {
145*3a7fca6bSBarry Smith   int         ierr,len;
146*3a7fca6bSBarry Smith   double      *history;
147*3a7fca6bSBarry Smith   PetscViewer viewer;
148*3a7fca6bSBarry Smith 
149*3a7fca6bSBarry Smith   PetscFunctionBegin;
150*3a7fca6bSBarry Smith   viewer = PETSC_VIEWER_STDOUT_(snes->comm);
151*3a7fca6bSBarry Smith 
152*3a7fca6bSBarry Smith   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr);
153*3a7fca6bSBarry Smith   if (its == 0 || !history || its > len) {
154*3a7fca6bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
155*3a7fca6bSBarry Smith   } else {
156*3a7fca6bSBarry Smith     double ratio = fgnorm/history[its-1];
157*3a7fca6bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e %g \n",its,fgnorm,ratio);CHKERRQ(ierr);
158*3a7fca6bSBarry Smith   }
159*3a7fca6bSBarry Smith   PetscFunctionReturn(0);
160*3a7fca6bSBarry Smith }
161*3a7fca6bSBarry Smith 
162*3a7fca6bSBarry Smith /*
163*3a7fca6bSBarry Smith    If the we set the history monitor space then we must destroy it
164*3a7fca6bSBarry Smith */
165*3a7fca6bSBarry Smith #undef __FUNCT__
166*3a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitorDestroy"
167*3a7fca6bSBarry Smith int SNESRatioMonitorDestroy(void *history)
168*3a7fca6bSBarry Smith {
169*3a7fca6bSBarry Smith   int         ierr;
170*3a7fca6bSBarry Smith 
171*3a7fca6bSBarry Smith   PetscFunctionBegin;
172*3a7fca6bSBarry Smith   ierr = PetscFree(history);CHKERRQ(ierr);
173*3a7fca6bSBarry Smith   PetscFunctionReturn(0);
174*3a7fca6bSBarry Smith }
175*3a7fca6bSBarry Smith 
176*3a7fca6bSBarry Smith #undef __FUNCT__
177*3a7fca6bSBarry Smith #define __FUNCT__ "SNESSetRatioMonitor"
178*3a7fca6bSBarry Smith /*@C
179*3a7fca6bSBarry Smith    SNESSetRatioMonitor - Sets SNES to use a monitor that prints the
180*3a7fca6bSBarry Smith      ratio of the function norm at each iteration
181*3a7fca6bSBarry Smith 
182*3a7fca6bSBarry Smith    Collective on SNES
183*3a7fca6bSBarry Smith 
184*3a7fca6bSBarry Smith    Input Parameters:
185*3a7fca6bSBarry Smith .   snes - the SNES context
186*3a7fca6bSBarry Smith 
187*3a7fca6bSBarry Smith    Level: intermediate
188*3a7fca6bSBarry Smith 
189*3a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm
190*3a7fca6bSBarry Smith 
191*3a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor()
192*3a7fca6bSBarry Smith @*/
193*3a7fca6bSBarry Smith int SNESSetRatioMonitor(SNES snes)
194*3a7fca6bSBarry Smith {
195*3a7fca6bSBarry Smith   int         ierr;
196*3a7fca6bSBarry Smith   double      *history;
197*3a7fca6bSBarry Smith 
198*3a7fca6bSBarry Smith   PetscFunctionBegin;
199*3a7fca6bSBarry Smith 
200*3a7fca6bSBarry Smith   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
201*3a7fca6bSBarry Smith   if (!history) {
202*3a7fca6bSBarry Smith     ierr = PetscMalloc(100*sizeof(double),&history);CHKERRQ(ierr);
203*3a7fca6bSBarry Smith     ierr = SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);CHKERRQ(ierr);
204*3a7fca6bSBarry Smith     ierr = SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);CHKERRQ(ierr);
205*3a7fca6bSBarry Smith   } else {
206*3a7fca6bSBarry Smith     ierr = SNESSetMonitor(snes,SNESRatioMonitor,0,0);CHKERRQ(ierr);
207*3a7fca6bSBarry Smith   }
208*3a7fca6bSBarry Smith   PetscFunctionReturn(0);
209*3a7fca6bSBarry Smith }
210*3a7fca6bSBarry Smith 
211e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
2124a2ae208SSatish Balay #undef __FUNCT__
2134a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultSMonitor"
214be1f7002SBarry Smith /*
215be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
216be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
217be1f7002SBarry Smith   This is because the later digits are meaningless and are often
218be1f7002SBarry Smith   different on different machines; by using this routine different
219be1f7002SBarry Smith   machines will usually generate the same output.
220be1f7002SBarry Smith */
221329f5518SBarry Smith int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
222e7e93795SLois Curfman McInnes {
223d132466eSBarry Smith   int ierr;
224d132466eSBarry Smith 
2253a40ed3dSBarry Smith   PetscFunctionBegin;
226e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
2278f240d10SBarry Smith     if (fgnorm > 1.e-9) {
228a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
2293a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
230a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
2313a40ed3dSBarry Smith     } else {
232a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
233e7e93795SLois Curfman McInnes     }
234e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
2358f240d10SBarry Smith     if (fgnorm > 1.e-9) {
236a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
2373a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
238a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
2393a40ed3dSBarry Smith     } else {
240a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr);
241e7e93795SLois Curfman McInnes     }
24229bbc08cSBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class");
2433a40ed3dSBarry Smith   PetscFunctionReturn(0);
244e7e93795SLois Curfman McInnes }
245e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
2464a2ae208SSatish Balay #undef __FUNCT__
2474a2ae208SSatish Balay #define __FUNCT__ "SNESConverged_EQ_LS"
2484b828684SBarry Smith /*@C
249f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
250f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
251e7e93795SLois Curfman McInnes 
252c7afd0dbSLois Curfman McInnes    Collective on SNES
253c7afd0dbSLois Curfman McInnes 
254e7e93795SLois Curfman McInnes    Input Parameters:
255c7afd0dbSLois Curfman McInnes +  snes - the SNES context
256e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
257e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
258e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
259c7afd0dbSLois Curfman McInnes -  dummy - unused context
260e7e93795SLois Curfman McInnes 
261184914b5SBarry Smith    Output Parameter:
262184914b5SBarry Smith .   reason  - one of
263184914b5SBarry Smith $  SNES_CONVERGED_FNORM_ABS       - (fnorm < atol),
264184914b5SBarry Smith $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
265184914b5SBarry Smith $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
266184914b5SBarry Smith $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
267184914b5SBarry Smith $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
268184914b5SBarry Smith $  SNES_CONVERGED_ITERATING       - (otherwise),
269e7e93795SLois Curfman McInnes 
270e7e93795SLois Curfman McInnes    where
271c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
272c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
273c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
274c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
275c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
276c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
277fee21e36SBarry Smith 
27836851e7fSLois Curfman McInnes    Level: intermediate
27936851e7fSLois Curfman McInnes 
280e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
281e7e93795SLois Curfman McInnes 
282e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
283e7e93795SLois Curfman McInnes @*/
284329f5518SBarry Smith int SNESConverged_EQ_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
285e7e93795SLois Curfman McInnes {
2863a40ed3dSBarry Smith   PetscFunctionBegin;
287d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
28829bbc08cSBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,"For SNES_NONLINEAR_EQUATIONS only");
289d252947aSBarry Smith   }
290184914b5SBarry Smith 
291d252947aSBarry Smith   if (fnorm != fnorm) {
292b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
293184914b5SBarry Smith     *reason = SNES_DIVERGED_FNORM_NAN;
294184914b5SBarry Smith   } else if (fnorm <= snes->ttol) {
295b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
296184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_RELATIVE;
297184914b5SBarry Smith   } else if (fnorm < snes->atol) {
298b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
299184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_ABS;
300184914b5SBarry Smith   } else if (pnorm < snes->xtol*(xnorm)) {
301b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
302184914b5SBarry Smith     *reason = SNES_CONVERGED_PNORM_RELATIVE;
303184914b5SBarry Smith   } else if (snes->nfuncs > snes->max_funcs) {
304b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs);
305184914b5SBarry Smith     *reason = SNES_DIVERGED_FUNCTION_COUNT ;
306184914b5SBarry Smith   } else {
307184914b5SBarry Smith     *reason = SNES_CONVERGED_ITERATING;
308e7e93795SLois Curfman McInnes   }
3093a40ed3dSBarry Smith   PetscFunctionReturn(0);
310e7e93795SLois Curfman McInnes }
311e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
3124a2ae208SSatish Balay #undef __FUNCT__
3134a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW"
314e7e93795SLois Curfman McInnes /*@
315f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
316e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
317e7e93795SLois Curfman McInnes 
318c7afd0dbSLois Curfman McInnes    Collective on SNES
319c7afd0dbSLois Curfman McInnes 
320e7e93795SLois Curfman McInnes    Input Parameter:
321e7e93795SLois Curfman McInnes .  snes - SNES context
322e7e93795SLois Curfman McInnes 
323e7e93795SLois Curfman McInnes    Notes:
324e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
325e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
326e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
327e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
328e7e93795SLois Curfman McInnes    solver.
329e7e93795SLois Curfman McInnes 
33036851e7fSLois Curfman McInnes    Level: advanced
33136851e7fSLois Curfman McInnes 
332e7e93795SLois Curfman McInnes    Reference:
333e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
334e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
335e7e93795SLois Curfman McInnes 
336e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
337e7e93795SLois Curfman McInnes @*/
338e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
339e7e93795SLois Curfman McInnes {
3403a40ed3dSBarry Smith   PetscFunctionBegin;
341186905e3SBarry Smith   snes->ksp_ewconv = PETSC_TRUE;
3423a40ed3dSBarry Smith   PetscFunctionReturn(0);
343e7e93795SLois Curfman McInnes }
344e7e93795SLois Curfman McInnes 
3454a2ae208SSatish Balay #undef __FUNCT__
3464a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetParametersEW"
347e7e93795SLois Curfman McInnes /*@
348e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
349e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
350e7e93795SLois Curfman McInnes    Newton method.
351e7e93795SLois Curfman McInnes 
352c7afd0dbSLois Curfman McInnes    Collective on SNES
353c7afd0dbSLois Curfman McInnes 
354e7e93795SLois Curfman McInnes    Input Parameters:
355c7afd0dbSLois Curfman McInnes +    snes - SNES context
356e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
357c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
358c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
359c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
360e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
361e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
362c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
363c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
364fee21e36SBarry Smith 
365e7e93795SLois Curfman McInnes    Note:
366e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
367e7e93795SLois Curfman McInnes 
36836851e7fSLois Curfman McInnes    Level: advanced
36936851e7fSLois Curfman McInnes 
370e7e93795SLois Curfman McInnes    Reference:
371e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
372e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
373e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
374e7e93795SLois Curfman McInnes 
375e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
376e7e93795SLois Curfman McInnes 
377e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
378e7e93795SLois Curfman McInnes @*/
379329f5518SBarry Smith int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0,
380329f5518SBarry Smith                              PetscReal rtol_max,PetscReal gamma2,PetscReal alpha,
381329f5518SBarry Smith                              PetscReal alpha2,PetscReal threshold)
382e7e93795SLois Curfman McInnes {
383e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
3843a40ed3dSBarry Smith 
3853a40ed3dSBarry Smith   PetscFunctionBegin;
38629bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
387e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version   = version;
388e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
389e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
390e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
391e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
392e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
393e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
394a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
39529bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
396a8c6a408SBarry Smith   }
397a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
39829bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max < 1.0\n",kctx->rtol_max);
399a8c6a408SBarry Smith   }
400a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
40129bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold < 1.0\n",kctx->threshold);
402a8c6a408SBarry Smith   }
403a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
40429bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= alpha <= 1.0\n",kctx->gamma);
405a8c6a408SBarry Smith   }
406a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
40729bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha <= 2.0\n",kctx->alpha);
408a8c6a408SBarry Smith   }
409a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
41029bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %d",kctx->version);
411a8c6a408SBarry Smith   }
4123a40ed3dSBarry Smith   PetscFunctionReturn(0);
413e7e93795SLois Curfman McInnes }
414e7e93795SLois Curfman McInnes 
4154a2ae208SSatish Balay #undef __FUNCT__
4164a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
417e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
418e7e93795SLois Curfman McInnes {
419e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
420329f5518SBarry Smith   PetscReal           rtol = 0.0,stol;
421e7e93795SLois Curfman McInnes   int                 ierr;
4223a40ed3dSBarry Smith 
4233a40ed3dSBarry Smith   PetscFunctionBegin;
42429bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
425c38d4ed2SBarry Smith   if (!snes->iter) { /* first time in, so use the original user rtol */
426e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
427e7e93795SLois Curfman McInnes   } else {
428e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
429e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
430e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
431e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
4320452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
433e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
434e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
435e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
4360452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
43729bbc08cSBarry Smith     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %d",kctx->version);
438e7e93795SLois Curfman McInnes   }
4390452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
440e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
441b0a32e0cSBarry Smith   PetscLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol);
4423131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
443e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
4443a40ed3dSBarry Smith   PetscFunctionReturn(0);
445e7e93795SLois Curfman McInnes }
446e7e93795SLois Curfman McInnes 
4474a2ae208SSatish Balay #undef __FUNCT__
4484a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_Converged_Private"
449329f5518SBarry Smith int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
450e7e93795SLois Curfman McInnes {
451e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
452e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
4533acb151aSSatish Balay   int                 ierr;
454e7e93795SLois Curfman McInnes 
4553a40ed3dSBarry Smith   PetscFunctionBegin;
45629bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set");
457184914b5SBarry Smith   if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);}
458211a6b7eSSatish Balay   ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr);
459e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
460211a6b7eSSatish Balay   if (*reason) {
461b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
4623a40ed3dSBarry Smith   }
463211a6b7eSSatish Balay   PetscFunctionReturn(0);
464e7e93795SLois Curfman McInnes }
465e7e93795SLois Curfman McInnes 
466e7e93795SLois Curfman McInnes 
467