xref: /petsc/src/snes/interface/snesut.c (revision 5ed2d596fd9914de76abbaed56c65f4792ae57ae)
173f4d377SMatthew Knepley /*$Id: snesut.c,v 1.66 2001/08/06 21:17:07 bsmith Exp $*/
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__
44*5ed2d596SBarry Smith #define __FUNCT__ "SNESVecViewResidualMonitor"
45*5ed2d596SBarry Smith /*@C
46*5ed2d596SBarry Smith    SNESVecViewResidualMonitor - Monitors progress of the SNES solvers by calling
47*5ed2d596SBarry Smith    VecView() for the residual at each iteration.
48*5ed2d596SBarry Smith 
49*5ed2d596SBarry Smith    Collective on SNES
50*5ed2d596SBarry Smith 
51*5ed2d596SBarry Smith    Input Parameters:
52*5ed2d596SBarry Smith +  snes - the SNES context
53*5ed2d596SBarry Smith .  its - iteration number
54*5ed2d596SBarry Smith .  fgnorm - 2-norm of residual (or gradient)
55*5ed2d596SBarry Smith -  dummy - either a viewer or PETSC_NULL
56*5ed2d596SBarry Smith 
57*5ed2d596SBarry Smith    Level: intermediate
58*5ed2d596SBarry Smith 
59*5ed2d596SBarry Smith .keywords: SNES, nonlinear, vector, monitor, view
60*5ed2d596SBarry Smith 
61*5ed2d596SBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
62*5ed2d596SBarry Smith @*/
63*5ed2d596SBarry Smith int SNESVecViewResidualMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
64*5ed2d596SBarry Smith {
65*5ed2d596SBarry Smith   int         ierr;
66*5ed2d596SBarry Smith   Vec         x;
67*5ed2d596SBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
68*5ed2d596SBarry Smith 
69*5ed2d596SBarry Smith   PetscFunctionBegin;
70*5ed2d596SBarry Smith   ierr = SNESGetFunction(snes,&x,0,0);CHKERRQ(ierr);
71*5ed2d596SBarry Smith   if (!viewer) {
72*5ed2d596SBarry Smith     MPI_Comm comm;
73*5ed2d596SBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
74*5ed2d596SBarry Smith     viewer = PETSC_VIEWER_DRAW_(comm);
75*5ed2d596SBarry Smith   }
76*5ed2d596SBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
77*5ed2d596SBarry Smith 
78*5ed2d596SBarry Smith   PetscFunctionReturn(0);
79*5ed2d596SBarry Smith }
80*5ed2d596SBarry Smith 
81*5ed2d596SBarry Smith #undef __FUNCT__
824a2ae208SSatish Balay #define __FUNCT__ "SNESVecViewUpdateMonitor"
83d132466eSBarry Smith /*@C
847c922b88SBarry Smith    SNESVecViewUpdateMonitor - Monitors progress of the SNES solvers by calling
85d132466eSBarry Smith    VecView() for the UPDATE to the solution at each iteration.
86d132466eSBarry Smith 
87d132466eSBarry Smith    Collective on SNES
88d132466eSBarry Smith 
89d132466eSBarry Smith    Input Parameters:
90d132466eSBarry Smith +  snes - the SNES context
91d132466eSBarry Smith .  its - iteration number
92d132466eSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
93d132466eSBarry Smith -  dummy - either a viewer or PETSC_NULL
94d132466eSBarry Smith 
95d132466eSBarry Smith    Level: intermediate
96d132466eSBarry Smith 
97d132466eSBarry Smith .keywords: SNES, nonlinear, vector, monitor, view
98d132466eSBarry Smith 
99d132466eSBarry Smith .seealso: SNESSetMonitor(), SNESDefaultMonitor(), VecView()
100d132466eSBarry Smith @*/
101329f5518SBarry Smith int SNESVecViewUpdateMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
102d132466eSBarry Smith {
103d132466eSBarry Smith   int         ierr;
104d132466eSBarry Smith   Vec         x;
105b0a32e0cSBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
106d132466eSBarry Smith 
107d132466eSBarry Smith   PetscFunctionBegin;
108d132466eSBarry Smith   ierr = SNESGetSolutionUpdate(snes,&x);CHKERRQ(ierr);
109d132466eSBarry Smith   if (!viewer) {
110d132466eSBarry Smith     MPI_Comm comm;
111d132466eSBarry Smith     ierr   = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
112b0a32e0cSBarry Smith     viewer = PETSC_VIEWER_DRAW_(comm);
113d132466eSBarry Smith   }
114d132466eSBarry Smith   ierr = VecView(x,viewer);CHKERRQ(ierr);
115d132466eSBarry Smith 
116d132466eSBarry Smith   PetscFunctionReturn(0);
117d132466eSBarry Smith }
118d132466eSBarry Smith 
1194a2ae208SSatish Balay #undef __FUNCT__
1204a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultMonitor"
1214b828684SBarry Smith /*@C
122f525115eSLois Curfman McInnes    SNESDefaultMonitor - Monitoring progress of the SNES solvers (default).
123e7e93795SLois Curfman McInnes 
124c7afd0dbSLois Curfman McInnes    Collective on SNES
125c7afd0dbSLois Curfman McInnes 
126e7e93795SLois Curfman McInnes    Input Parameters:
127c7afd0dbSLois Curfman McInnes +  snes - the SNES context
128e7e93795SLois Curfman McInnes .  its - iteration number
129e7e93795SLois Curfman McInnes .  fgnorm - 2-norm of residual (or gradient)
130c7afd0dbSLois Curfman McInnes -  dummy - unused context
131fee21e36SBarry Smith 
132e7e93795SLois Curfman McInnes    Notes:
133e7e93795SLois Curfman McInnes    For SNES_NONLINEAR_EQUATIONS methods the routine prints the
134e7e93795SLois Curfman McInnes    residual norm at each iteration.
135e7e93795SLois Curfman McInnes 
136e7e93795SLois Curfman McInnes    For SNES_UNCONSTRAINED_MINIMIZATION methods the routine prints the
137e7e93795SLois Curfman McInnes    function value and gradient norm at each iteration.
138e7e93795SLois Curfman McInnes 
13936851e7fSLois Curfman McInnes    Level: intermediate
14036851e7fSLois Curfman McInnes 
141e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, monitor, norm
142e7e93795SLois Curfman McInnes 
14336851e7fSLois Curfman McInnes .seealso: SNESSetMonitor(), SNESVecViewMonitor()
144e7e93795SLois Curfman McInnes @*/
145329f5518SBarry Smith int SNESDefaultMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
146e7e93795SLois Curfman McInnes {
147d132466eSBarry Smith   int         ierr;
148b0a32e0cSBarry Smith   PetscViewer viewer = (PetscViewer) dummy;
149d132466eSBarry Smith 
1503a40ed3dSBarry Smith   PetscFunctionBegin;
151b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(snes->comm);
1527c922b88SBarry Smith 
15376be9ce4SBarry Smith   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
154a0e26f09SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
15576be9ce4SBarry Smith   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
156a0e26f09SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function value %14.12e, Gradient norm %14.12e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
15729bbc08cSBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class");
1583a40ed3dSBarry Smith   PetscFunctionReturn(0);
159e7e93795SLois Curfman McInnes }
1603f1db9ecSBarry Smith 
1613a7fca6bSBarry Smith #undef __FUNCT__
1623a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitor"
1633a7fca6bSBarry Smith /*@C
1643a7fca6bSBarry Smith    SNESRatioMonitor - Monitoring progress of the SNES solvers, prints ratio
1653a7fca6bSBarry Smith       of residual norm at each iteration to previous
1663a7fca6bSBarry Smith 
1673a7fca6bSBarry Smith    Collective on SNES
1683a7fca6bSBarry Smith 
1693a7fca6bSBarry Smith    Input Parameters:
1703a7fca6bSBarry Smith +  snes - the SNES context
1713a7fca6bSBarry Smith .  its - iteration number
1723a7fca6bSBarry Smith .  fgnorm - 2-norm of residual (or gradient)
1733a7fca6bSBarry Smith -  dummy - unused context
1743a7fca6bSBarry Smith 
1753a7fca6bSBarry Smith    Level: intermediate
1763a7fca6bSBarry Smith 
1773a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm
1783a7fca6bSBarry Smith 
1793a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor()
1803a7fca6bSBarry Smith @*/
1813a7fca6bSBarry Smith int SNESRatioMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
1823a7fca6bSBarry Smith {
1833a7fca6bSBarry Smith   int         ierr,len;
18487828ca2SBarry Smith   PetscReal   *history;
1853a7fca6bSBarry Smith   PetscViewer viewer;
1863a7fca6bSBarry Smith 
1873a7fca6bSBarry Smith   PetscFunctionBegin;
1883a7fca6bSBarry Smith   viewer = PETSC_VIEWER_STDOUT_(snes->comm);
1893a7fca6bSBarry Smith 
1903a7fca6bSBarry Smith   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,&len);CHKERRQ(ierr);
1913a7fca6bSBarry Smith   if (its == 0 || !history || its > len) {
1923a7fca6bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e \n",its,fgnorm);CHKERRQ(ierr);
1933a7fca6bSBarry Smith   } else {
19487828ca2SBarry Smith     PetscReal ratio = fgnorm/history[its-1];
1953a7fca6bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%3d SNES Function norm %14.12e %g \n",its,fgnorm,ratio);CHKERRQ(ierr);
1963a7fca6bSBarry Smith   }
1973a7fca6bSBarry Smith   PetscFunctionReturn(0);
1983a7fca6bSBarry Smith }
1993a7fca6bSBarry Smith 
2003a7fca6bSBarry Smith /*
2013a7fca6bSBarry Smith    If the we set the history monitor space then we must destroy it
2023a7fca6bSBarry Smith */
2033a7fca6bSBarry Smith #undef __FUNCT__
2043a7fca6bSBarry Smith #define __FUNCT__ "SNESRatioMonitorDestroy"
2053a7fca6bSBarry Smith int SNESRatioMonitorDestroy(void *history)
2063a7fca6bSBarry Smith {
2073a7fca6bSBarry Smith   int         ierr;
2083a7fca6bSBarry Smith 
2093a7fca6bSBarry Smith   PetscFunctionBegin;
2103a7fca6bSBarry Smith   ierr = PetscFree(history);CHKERRQ(ierr);
2113a7fca6bSBarry Smith   PetscFunctionReturn(0);
2123a7fca6bSBarry Smith }
2133a7fca6bSBarry Smith 
2143a7fca6bSBarry Smith #undef __FUNCT__
2153a7fca6bSBarry Smith #define __FUNCT__ "SNESSetRatioMonitor"
2163a7fca6bSBarry Smith /*@C
2173a7fca6bSBarry Smith    SNESSetRatioMonitor - Sets SNES to use a monitor that prints the
2183a7fca6bSBarry Smith      ratio of the function norm at each iteration
2193a7fca6bSBarry Smith 
2203a7fca6bSBarry Smith    Collective on SNES
2213a7fca6bSBarry Smith 
2223a7fca6bSBarry Smith    Input Parameters:
2233a7fca6bSBarry Smith .   snes - the SNES context
2243a7fca6bSBarry Smith 
2253a7fca6bSBarry Smith    Level: intermediate
2263a7fca6bSBarry Smith 
2273a7fca6bSBarry Smith .keywords: SNES, nonlinear, monitor, norm
2283a7fca6bSBarry Smith 
2293a7fca6bSBarry Smith .seealso: SNESSetMonitor(), SNESVecViewMonitor(), SNESDefaultMonitor()
2303a7fca6bSBarry Smith @*/
2313a7fca6bSBarry Smith int SNESSetRatioMonitor(SNES snes)
2323a7fca6bSBarry Smith {
2333a7fca6bSBarry Smith   int       ierr;
23487828ca2SBarry Smith   PetscReal *history;
2353a7fca6bSBarry Smith 
2363a7fca6bSBarry Smith   PetscFunctionBegin;
2373a7fca6bSBarry Smith 
2383a7fca6bSBarry Smith   ierr = SNESGetConvergenceHistory(snes,&history,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2393a7fca6bSBarry Smith   if (!history) {
2403a7fca6bSBarry Smith     ierr = PetscMalloc(100*sizeof(double),&history);CHKERRQ(ierr);
2413a7fca6bSBarry Smith     ierr = SNESSetConvergenceHistory(snes,history,0,100,PETSC_TRUE);CHKERRQ(ierr);
2423a7fca6bSBarry Smith     ierr = SNESSetMonitor(snes,SNESRatioMonitor,history,SNESRatioMonitorDestroy);CHKERRQ(ierr);
2433a7fca6bSBarry Smith   } else {
2443a7fca6bSBarry Smith     ierr = SNESSetMonitor(snes,SNESRatioMonitor,0,0);CHKERRQ(ierr);
2453a7fca6bSBarry Smith   }
2463a7fca6bSBarry Smith   PetscFunctionReturn(0);
2473a7fca6bSBarry Smith }
2483a7fca6bSBarry Smith 
249e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
2504a2ae208SSatish Balay #undef __FUNCT__
2514a2ae208SSatish Balay #define __FUNCT__ "SNESDefaultSMonitor"
252be1f7002SBarry Smith /*
253be1f7002SBarry Smith      Default (short) SNES Monitor, same as SNESDefaultMonitor() except
254be1f7002SBarry Smith   it prints fewer digits of the residual as the residual gets smaller.
255be1f7002SBarry Smith   This is because the later digits are meaningless and are often
256be1f7002SBarry Smith   different on different machines; by using this routine different
257be1f7002SBarry Smith   machines will usually generate the same output.
258be1f7002SBarry Smith */
259329f5518SBarry Smith int SNESDefaultSMonitor(SNES snes,int its,PetscReal fgnorm,void *dummy)
260e7e93795SLois Curfman McInnes {
261d132466eSBarry Smith   int ierr;
262d132466eSBarry Smith 
2633a40ed3dSBarry Smith   PetscFunctionBegin;
264e7e93795SLois Curfman McInnes   if (snes->method_class == SNES_NONLINEAR_EQUATIONS) {
2658f240d10SBarry Smith     if (fgnorm > 1.e-9) {
266a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %g \n",its,fgnorm);CHKERRQ(ierr);
2673a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11){
268a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm %5.3e \n",its,fgnorm);CHKERRQ(ierr);
2693a40ed3dSBarry Smith     } else {
270a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function norm < 1.e-11\n",its);CHKERRQ(ierr);
271e7e93795SLois Curfman McInnes     }
272e7e93795SLois Curfman McInnes   } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) {
2738f240d10SBarry Smith     if (fgnorm > 1.e-9) {
274a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %g \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
2753a40ed3dSBarry Smith     } else if (fgnorm > 1.e-11) {
276a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm %5.3e \n",its,snes->fc,fgnorm);CHKERRQ(ierr);
2773a40ed3dSBarry Smith     } else {
278a0e26f09SSatish Balay       ierr = PetscPrintf(snes->comm,"%3d SNES Function value %g, Gradient norm < 1.e-11\n",its,snes->fc);CHKERRQ(ierr);
279e7e93795SLois Curfman McInnes     }
28029bbc08cSBarry Smith   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown method class");
2813a40ed3dSBarry Smith   PetscFunctionReturn(0);
282e7e93795SLois Curfman McInnes }
283e7e93795SLois Curfman McInnes /* ---------------------------------------------------------------- */
2844a2ae208SSatish Balay #undef __FUNCT__
2854a2ae208SSatish Balay #define __FUNCT__ "SNESConverged_EQ_LS"
2864b828684SBarry Smith /*@C
287f525115eSLois Curfman McInnes    SNESConverged_EQ_LS - Monitors the convergence of the solvers for
288f525115eSLois Curfman McInnes    systems of nonlinear equations (default).
289e7e93795SLois Curfman McInnes 
290c7afd0dbSLois Curfman McInnes    Collective on SNES
291c7afd0dbSLois Curfman McInnes 
292e7e93795SLois Curfman McInnes    Input Parameters:
293c7afd0dbSLois Curfman McInnes +  snes - the SNES context
294e7e93795SLois Curfman McInnes .  xnorm - 2-norm of current iterate
295e7e93795SLois Curfman McInnes .  pnorm - 2-norm of current step
296e7e93795SLois Curfman McInnes .  fnorm - 2-norm of function
297c7afd0dbSLois Curfman McInnes -  dummy - unused context
298e7e93795SLois Curfman McInnes 
299184914b5SBarry Smith    Output Parameter:
300184914b5SBarry Smith .   reason  - one of
301184914b5SBarry Smith $  SNES_CONVERGED_FNORM_ABS       - (fnorm < atol),
3023304466cSBarry Smith $  SNES_CONVERGED_PNORM_RELATIVE  - (pnorm < xtol*xnorm),
303184914b5SBarry Smith $  SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
304184914b5SBarry Smith $  SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
305184914b5SBarry Smith $  SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
306184914b5SBarry Smith $  SNES_CONVERGED_ITERATING       - (otherwise),
307e7e93795SLois Curfman McInnes 
308e7e93795SLois Curfman McInnes    where
309c7afd0dbSLois Curfman McInnes +    maxf - maximum number of function evaluations,
310c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
311c7afd0dbSLois Curfman McInnes .    nfct - number of function evaluations,
312c7afd0dbSLois Curfman McInnes .    atol - absolute function norm tolerance,
313c7afd0dbSLois Curfman McInnes             set with SNESSetTolerances()
314c7afd0dbSLois Curfman McInnes -    rtol - relative function norm tolerance, set with SNESSetTolerances()
315fee21e36SBarry Smith 
31636851e7fSLois Curfman McInnes    Level: intermediate
31736851e7fSLois Curfman McInnes 
318e7e93795SLois Curfman McInnes .keywords: SNES, nonlinear, default, converged, convergence
319e7e93795SLois Curfman McInnes 
320e7e93795SLois Curfman McInnes .seealso: SNESSetConvergenceTest(), SNESEisenstatWalkerConverged()
321e7e93795SLois Curfman McInnes @*/
322329f5518SBarry Smith int SNESConverged_EQ_LS(SNES snes,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
323e7e93795SLois Curfman McInnes {
3243a40ed3dSBarry Smith   PetscFunctionBegin;
325d252947aSBarry Smith   if (snes->method_class != SNES_NONLINEAR_EQUATIONS) {
32629bbc08cSBarry Smith      SETERRQ(PETSC_ERR_ARG_WRONG,"For SNES_NONLINEAR_EQUATIONS only");
327d252947aSBarry Smith   }
328184914b5SBarry Smith 
329d252947aSBarry Smith   if (fnorm != fnorm) {
330b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Failed to converged, function norm is NaN\n");
331184914b5SBarry Smith     *reason = SNES_DIVERGED_FNORM_NAN;
332184914b5SBarry Smith   } else if (fnorm <= snes->ttol) {
333b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g (relative tolerance)\n",fnorm,snes->ttol);
334184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_RELATIVE;
335184914b5SBarry Smith   } else if (fnorm < snes->atol) {
336b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to function norm %g < %g\n",fnorm,snes->atol);
337184914b5SBarry Smith     *reason = SNES_CONVERGED_FNORM_ABS;
3383304466cSBarry Smith   } else if (pnorm < snes->xtol*xnorm) {
339b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Converged due to small update length: %g < %g * %g\n",pnorm,snes->xtol,xnorm);
340184914b5SBarry Smith     *reason = SNES_CONVERGED_PNORM_RELATIVE;
341184914b5SBarry Smith   } else if (snes->nfuncs > snes->max_funcs) {
342b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNESConverged_EQ_LS:Exceeded maximum number of function evaluations: %d > %d\n",snes->nfuncs,snes->max_funcs);
343184914b5SBarry Smith     *reason = SNES_DIVERGED_FUNCTION_COUNT ;
344184914b5SBarry Smith   } else {
345184914b5SBarry Smith     *reason = SNES_CONVERGED_ITERATING;
346e7e93795SLois Curfman McInnes   }
3473a40ed3dSBarry Smith   PetscFunctionReturn(0);
348e7e93795SLois Curfman McInnes }
349e7e93795SLois Curfman McInnes /* ------------------------------------------------------------ */
3504a2ae208SSatish Balay #undef __FUNCT__
3514a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetConvergenceTestEW"
352e7e93795SLois Curfman McInnes /*@
353f525115eSLois Curfman McInnes    SNES_KSP_SetConvergenceTestEW - Sets alternative convergence test
354e7e93795SLois Curfman McInnes    for the linear solvers within an inexact Newton method.
355e7e93795SLois Curfman McInnes 
356c7afd0dbSLois Curfman McInnes    Collective on SNES
357c7afd0dbSLois Curfman McInnes 
358e7e93795SLois Curfman McInnes    Input Parameter:
359e7e93795SLois Curfman McInnes .  snes - SNES context
360e7e93795SLois Curfman McInnes 
361e7e93795SLois Curfman McInnes    Notes:
362e7e93795SLois Curfman McInnes    Currently, the default is to use a constant relative tolerance for
363e7e93795SLois Curfman McInnes    the inner linear solvers.  Alternatively, one can use the
364e7e93795SLois Curfman McInnes    Eisenstat-Walker method, where the relative convergence tolerance
365e7e93795SLois Curfman McInnes    is reset at each Newton iteration according progress of the nonlinear
366e7e93795SLois Curfman McInnes    solver.
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
372e30ad881SLois Curfman McInnes    inexact Newton method", SISC 17 (1), pp.16-32, 1996.
373e7e93795SLois Curfman McInnes 
374e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton
375e7e93795SLois Curfman McInnes @*/
376e7e93795SLois Curfman McInnes int SNES_KSP_SetConvergenceTestEW(SNES snes)
377e7e93795SLois Curfman McInnes {
3783a40ed3dSBarry Smith   PetscFunctionBegin;
379186905e3SBarry Smith   snes->ksp_ewconv = PETSC_TRUE;
3803a40ed3dSBarry Smith   PetscFunctionReturn(0);
381e7e93795SLois Curfman McInnes }
382e7e93795SLois Curfman McInnes 
3834a2ae208SSatish Balay #undef __FUNCT__
3844a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_SetParametersEW"
385e7e93795SLois Curfman McInnes /*@
386e7e93795SLois Curfman McInnes    SNES_KSP_SetParametersEW - Sets parameters for Eisenstat-Walker
387e7e93795SLois Curfman McInnes    convergence criteria for the linear solvers within an inexact
388e7e93795SLois Curfman McInnes    Newton method.
389e7e93795SLois Curfman McInnes 
390c7afd0dbSLois Curfman McInnes    Collective on SNES
391c7afd0dbSLois Curfman McInnes 
392e7e93795SLois Curfman McInnes    Input Parameters:
393c7afd0dbSLois Curfman McInnes +    snes - SNES context
394e7e93795SLois Curfman McInnes .    version - version 1 or 2 (default is 2)
395c7afd0dbSLois Curfman McInnes .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
396c7afd0dbSLois Curfman McInnes .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
397c7afd0dbSLois Curfman McInnes .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
398e7e93795SLois Curfman McInnes .    alpha2 - power for safeguard
399e7e93795SLois Curfman McInnes .    gamma2 - multiplicative factor for version 2 rtol computation
400c7afd0dbSLois Curfman McInnes               (0 <= gamma2 <= 1)
401c7afd0dbSLois Curfman McInnes -    threshold - threshold for imposing safeguard (0 < threshold < 1)
402fee21e36SBarry Smith 
403e7e93795SLois Curfman McInnes    Note:
404e7e93795SLois Curfman McInnes    Use PETSC_DEFAULT to retain the default for any of the parameters.
405e7e93795SLois Curfman McInnes 
40636851e7fSLois Curfman McInnes    Level: advanced
40736851e7fSLois Curfman McInnes 
408e7e93795SLois Curfman McInnes    Reference:
409e7e93795SLois Curfman McInnes    S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an
410e7e93795SLois Curfman McInnes    inexact Newton method", Utah State University Math. Stat. Dept. Res.
411e7e93795SLois Curfman McInnes    Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput.
412e7e93795SLois Curfman McInnes 
413e7e93795SLois Curfman McInnes .keywords: SNES, KSP, Eisenstat, Walker, set, parameters
414e7e93795SLois Curfman McInnes 
415e7e93795SLois Curfman McInnes .seealso: SNES_KSP_SetConvergenceTestEW()
416e7e93795SLois Curfman McInnes @*/
417329f5518SBarry Smith int SNES_KSP_SetParametersEW(SNES snes,int version,PetscReal rtol_0,
418329f5518SBarry Smith                              PetscReal rtol_max,PetscReal gamma2,PetscReal alpha,
419329f5518SBarry Smith                              PetscReal alpha2,PetscReal threshold)
420e7e93795SLois Curfman McInnes {
421e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
4223a40ed3dSBarry Smith 
4233a40ed3dSBarry Smith   PetscFunctionBegin;
42429bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing");
425e7e93795SLois Curfman McInnes   if (version != PETSC_DEFAULT)   kctx->version   = version;
426e7e93795SLois Curfman McInnes   if (rtol_0 != PETSC_DEFAULT)    kctx->rtol_0    = rtol_0;
427e7e93795SLois Curfman McInnes   if (rtol_max != PETSC_DEFAULT)  kctx->rtol_max  = rtol_max;
428e7e93795SLois Curfman McInnes   if (gamma2 != PETSC_DEFAULT)    kctx->gamma     = gamma2;
429e7e93795SLois Curfman McInnes   if (alpha != PETSC_DEFAULT)     kctx->alpha     = alpha;
430e7e93795SLois Curfman McInnes   if (alpha2 != PETSC_DEFAULT)    kctx->alpha2    = alpha2;
431e7e93795SLois Curfman McInnes   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
432a8c6a408SBarry Smith   if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) {
43329bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",kctx->rtol_0);
434a8c6a408SBarry Smith   }
435a8c6a408SBarry Smith   if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) {
436091e6287SMatthew Knepley     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%g) < 1.0\n",kctx->rtol_max);
437a8c6a408SBarry Smith   }
438a8c6a408SBarry Smith   if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) {
439091e6287SMatthew Knepley     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",kctx->threshold);
440a8c6a408SBarry Smith   }
441a8c6a408SBarry Smith   if (kctx->gamma < 0.0 || kctx->gamma > 1.0) {
442091e6287SMatthew Knepley     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",kctx->gamma);
443a8c6a408SBarry Smith   }
444a8c6a408SBarry Smith   if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) {
445091e6287SMatthew Knepley     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",kctx->alpha);
446a8c6a408SBarry Smith   }
447a8c6a408SBarry Smith   if (kctx->version != 1 && kctx->version !=2) {
44829bbc08cSBarry Smith     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 and 2 are supported: %d",kctx->version);
449a8c6a408SBarry Smith   }
4503a40ed3dSBarry Smith   PetscFunctionReturn(0);
451e7e93795SLois Curfman McInnes }
452e7e93795SLois Curfman McInnes 
4534a2ae208SSatish Balay #undef __FUNCT__
4544a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_ComputeRelativeTolerance_Private"
455e7e93795SLois Curfman McInnes int SNES_KSP_EW_ComputeRelativeTolerance_Private(SNES snes,KSP ksp)
456e7e93795SLois Curfman McInnes {
457e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
458329f5518SBarry Smith   PetscReal           rtol = 0.0,stol;
459e7e93795SLois Curfman McInnes   int                 ierr;
4603a40ed3dSBarry Smith 
4613a40ed3dSBarry Smith   PetscFunctionBegin;
46229bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context exists");
463c38d4ed2SBarry Smith   if (!snes->iter) { /* first time in, so use the original user rtol */
464e7e93795SLois Curfman McInnes     rtol = kctx->rtol_0;
465e7e93795SLois Curfman McInnes   } else {
466e7e93795SLois Curfman McInnes     if (kctx->version == 1) {
467e7e93795SLois Curfman McInnes       rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last;
468e7e93795SLois Curfman McInnes       if (rtol < 0.0) rtol = -rtol;
469e7e93795SLois Curfman McInnes       stol = pow(kctx->rtol_last,kctx->alpha2);
4700452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
471e7e93795SLois Curfman McInnes     } else if (kctx->version == 2) {
472e7e93795SLois Curfman McInnes       rtol = kctx->gamma * pow(snes->norm/kctx->norm_last,kctx->alpha);
473e7e93795SLois Curfman McInnes       stol = kctx->gamma * pow(kctx->rtol_last,kctx->alpha);
4740452661fSBarry Smith       if (stol > kctx->threshold) rtol = PetscMax(rtol,stol);
47529bbc08cSBarry Smith     } else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1 or 2 are supported: %d",kctx->version);
476e7e93795SLois Curfman McInnes   }
4770452661fSBarry Smith   rtol = PetscMin(rtol,kctx->rtol_max);
478e7e93795SLois Curfman McInnes   kctx->rtol_last = rtol;
479b0a32e0cSBarry Smith   PetscLogInfo(snes,"SNES_KSP_EW_ComputeRelativeTolerance_Private: iter %d, Eisenstat-Walker (version %d) KSP rtol = %g\n",snes->iter,kctx->version,rtol);
4803131a8b6SLois Curfman McInnes   ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr);
481e7e93795SLois Curfman McInnes   kctx->norm_last = snes->norm;
4823a40ed3dSBarry Smith   PetscFunctionReturn(0);
483e7e93795SLois Curfman McInnes }
484e7e93795SLois Curfman McInnes 
4854a2ae208SSatish Balay #undef __FUNCT__
4864a2ae208SSatish Balay #define __FUNCT__ "SNES_KSP_EW_Converged_Private"
487329f5518SBarry Smith int SNES_KSP_EW_Converged_Private(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
488e7e93795SLois Curfman McInnes {
489e7e93795SLois Curfman McInnes   SNES                snes = (SNES)ctx;
490e7e93795SLois Curfman McInnes   SNES_KSP_EW_ConvCtx *kctx = (SNES_KSP_EW_ConvCtx*)snes->kspconvctx;
4913acb151aSSatish Balay   int                 ierr;
492e7e93795SLois Curfman McInnes 
4933a40ed3dSBarry Smith   PetscFunctionBegin;
49429bbc08cSBarry Smith   if (!kctx) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context set");
495184914b5SBarry Smith   if (n == 0) {ierr = SNES_KSP_EW_ComputeRelativeTolerance_Private(snes,ksp);CHKERRQ(ierr);}
496211a6b7eSSatish Balay   ierr = KSPDefaultConverged(ksp,n,rnorm,reason,ctx);CHKERRQ(ierr);
497e7e93795SLois Curfman McInnes   kctx->lresid_last = rnorm;
498211a6b7eSSatish Balay   if (*reason) {
499b0a32e0cSBarry Smith     PetscLogInfo(snes,"SNES_KSP_EW_Converged_Private: KSP iterations=%d, rnorm=%g\n",n,rnorm);
5003a40ed3dSBarry Smith   }
501211a6b7eSSatish Balay   PetscFunctionReturn(0);
502e7e93795SLois Curfman McInnes }
503e7e93795SLois Curfman McInnes 
504e7e93795SLois Curfman McInnes 
505