Actual source code: svdmon.c

  1: /*
  2:       SVD routines related to monitors.

  4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  6:    Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain

  8:    This file is part of SLEPc.
  9:       
 10:    SLEPc is free software: you can redistribute it and/or modify it under  the
 11:    terms of version 3 of the GNU Lesser General Public License as published by
 12:    the Free Software Foundation.

 14:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY 
 15:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS 
 16:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for 
 17:    more details.

 19:    You  should have received a copy of the GNU Lesser General  Public  License
 20:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
 21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 22: */

 24: #include <private/svdimpl.h>   /*I "slepcsvd.h" I*/

 28: /*
 29:    Runs the user provided monitor routines, if any.
 30: */
 31: PetscErrorCode SVDMonitor(SVD svd,PetscInt it,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest)
 32: {
 34:   PetscInt       i,n = svd->numbermonitors;

 37:   for (i=0;i<n;i++) {
 38:     (*svd->monitor[i])(svd,it,nconv,sigma,errest,nest,svd->monitorcontext[i]);
 39:   }
 40:   return(0);
 41: }

 45: /*@C
 46:    SVDMonitorSet - Sets an ADDITIONAL function to be called at every 
 47:    iteration to monitor the error estimates for each requested singular triplet.
 48:       
 49:    Collective on SVD

 51:    Input Parameters:
 52: +  svd     - singular value solver context obtained from SVDCreate()
 53: .  monitor - pointer to function (if this is PETSC_NULL, it turns off monitoring)
 54: -  mctx    - [optional] context for private data for the
 55:              monitor routine (use PETSC_NULL if no context is desired)

 57:    Calling Sequence of monitor:
 58: $     monitor (SVD svd, PetscInt its, PetscInt nconv, PetscReal *sigma, PetscReal* errest, PetscInt nest, void *mctx)

 60: +  svd    - singular value solver context obtained from SVDCreate()
 61: .  its    - iteration number
 62: .  nconv  - number of converged singular triplets
 63: .  sigma  - singular values
 64: .  errest - relative error estimates for each singular triplet
 65: .  nest   - number of error estimates
 66: -  mctx   - optional monitoring context, as set by SVDMonitorSet()

 68:    Options Database Keys:
 69: +    -svd_monitor          - print only the first error estimate
 70: .    -svd_monitor_all      - print error estimates at each iteration
 71: .    -svd_monitor_conv     - print the singular value approximations only when
 72:       convergence has been reached
 73: .    -svd_monitor_draw     - sets line graph monitor for the first unconverged
 74:       approximate singular value
 75: .    -svd_monitor_draw_all - sets line graph monitor for all unconverged
 76:       approximate singular value
 77: -    -svd_monitor_cancel   - cancels all monitors that have been hardwired into
 78:       a code by calls to SVDMonitorSet(), but does not cancel those set via
 79:       the options database.

 81:    Notes:  
 82:    Several different monitoring routines may be set by calling
 83:    SVDMonitorSet() multiple times; all will be called in the 
 84:    order in which they were set.

 86:    Level: intermediate

 88: .seealso: SVDMonitorFirst(), SVDMonitorAll(), SVDMonitorLG(), SVDMonitorLGAll(), SVDMonitorCancel()
 89: @*/
 90: PetscErrorCode SVDMonitorSet(SVD svd,PetscErrorCode (*monitor)(SVD,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscInt,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
 91: {
 94:   if (svd->numbermonitors >= MAXSVDMONITORS) {
 95:     SETERRQ(((PetscObject)svd)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many SVD monitors set");
 96:   }
 97:   svd->monitor[svd->numbermonitors]           = monitor;
 98:   svd->monitorcontext[svd->numbermonitors]    = (void*)mctx;
 99:   svd->monitordestroy[svd->numbermonitors++]  = monitordestroy;
100:   return(0);
101: }

105: /*@
106:    SVDMonitorCancel - Clears all monitors for an SVD object.

108:    Collective on SVD

110:    Input Parameters:
111: .  svd - singular value solver context obtained from SVDCreate()

113:    Options Database Key:
114: .    -svd_monitor_cancel - Cancels all monitors that have been hardwired 
115:       into a code by calls to SVDMonitorSet(),
116:       but does not cancel those set via the options database.

118:    Level: intermediate

120: .seealso: SVDMonitorSet()
121: @*/
122: PetscErrorCode SVDMonitorCancel(SVD svd)
123: {
125:   PetscInt       i;

129:   for (i=0; i<svd->numbermonitors; i++) {
130:     if (svd->monitordestroy[i]) {
131:       (*svd->monitordestroy[i])(&svd->monitorcontext[i]);
132:     }
133:   }
134:   svd->numbermonitors = 0;
135:   return(0);
136: }

140: /*@C
141:    SVDGetMonitorContext - Gets the monitor context, as set by 
142:    SVDMonitorSet() for the FIRST monitor only.

144:    Not Collective

146:    Input Parameter:
147: .  svd - singular value solver context obtained from SVDCreate()

149:    Output Parameter:
150: .  ctx - monitor context

152:    Level: intermediate

154: .seealso: SVDMonitorSet()
155: @*/
156: PetscErrorCode SVDGetMonitorContext(SVD svd,void **ctx)
157: {
160:   *ctx = (svd->monitorcontext[0]);
161:   return(0);
162: }

166: /*@C
167:    SVDMonitorAll - Print the current approximate values and 
168:    error estimates at each iteration of the singular value solver.

170:    Collective on SVD

172:    Input Parameters:
173: +  svd    - singular value solver context
174: .  its    - iteration number
175: .  nconv  - number of converged singular triplets so far
176: .  sigma  - singular values
177: .  errest - error estimates
178: .  nest   - number of error estimates to display
179: -  dummy  - unused monitor context 

181:    Level: intermediate

183: .seealso: SVDMonitorSet(), SVDMonitorFirst(), SVDMonitorConverged()
184: @*/
185: PetscErrorCode SVDMonitorAll(SVD svd,PetscInt its,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest,void *dummy)
186: {
188:   PetscInt       i;
189:   PetscViewer    viewer = dummy? (PetscViewer)dummy: PETSC_VIEWER_STDOUT_(((PetscObject)svd)->comm);

192:   if (its) {
193:     PetscViewerASCIIAddTab(viewer,((PetscObject)svd)->tablevel);
194:     PetscViewerASCIIPrintf(viewer,"%3D SVD nconv=%D Values (Errors)",its,nconv);
195:     for (i=0;i<nest;i++) {
196:       PetscViewerASCIIPrintf(viewer," %G (%10.8e)",sigma[i],(double)errest[i]);
197:     }
198:     PetscViewerASCIIPrintf(viewer,"\n");
199:     PetscViewerASCIISubtractTab(viewer,((PetscObject)svd)->tablevel);
200:   }
201:   return(0);
202: }

206: /*@C
207:    SVDMonitorFirst - Print the first unconverged approximate values and 
208:    error estimates at each iteration of the singular value solver.

210:    Collective on SVD

212:    Input Parameters:
213: +  svd    - singular value solver context
214: .  its    - iteration number
215: .  nconv  - number of converged singular triplets so far
216: .  sigma  - singular values
217: .  errest - error estimates
218: .  nest   - number of error estimates to display
219: -  dummy  - unused monitor context 

221:    Level: intermediate

223: .seealso: SVDMonitorSet(), SVDMonitorAll(), SVDMonitorConverged()
224: @*/
225: PetscErrorCode SVDMonitorFirst(SVD svd,PetscInt its,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest,void *dummy)
226: {
228:   PetscViewer    viewer = dummy? (PetscViewer)dummy: PETSC_VIEWER_STDOUT_(((PetscObject)svd)->comm);

231:   if (its && nconv<nest) {
232:     PetscViewerASCIIAddTab(viewer,((PetscObject)svd)->tablevel);
233:     PetscViewerASCIIPrintf(viewer,"%3D SVD nconv=%D first unconverged value (error)",its,nconv);
234:     PetscViewerASCIIPrintf(viewer," %G (%10.8e)\n",sigma[nconv],(double)errest[nconv]);
235:     PetscViewerASCIISubtractTab(viewer,((PetscObject)svd)->tablevel);
236:   }
237:   return(0);
238: }

242: /*@C
243:    SVDMonitorConverged - Print the approximate values and error estimates as they converge.

245:    Collective on SVD

247:    Input Parameters:
248: +  svd    - singular value solver context
249: .  its    - iteration number
250: .  nconv  - number of converged singular triplets so far
251: .  sigma  - singular values
252: .  errest - error estimates
253: .  nest   - number of error estimates to display
254: -  dummy  - unused monitor context 

256:    Level: intermediate

258: .seealso: SVDMonitorSet(), SVDMonitorFirst(), SVDMonitorAll()
259: @*/
260: PetscErrorCode SVDMonitorConverged(SVD svd,PetscInt its,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest,void *dummy)
261: {
262:   PetscErrorCode   ierr;
263:   PetscInt         i;
264:   SlepcConvMonitor ctx = (SlepcConvMonitor) dummy;

267:   if (!its) {
268:     ctx->oldnconv = 0;
269:   } else {
270:     for (i=ctx->oldnconv;i<nconv;i++) {
271:       PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)svd)->tablevel);
272:       PetscViewerASCIIPrintf(ctx->viewer,"%3D SVD converged value (error) #%D",its,i);
273:       PetscViewerASCIIPrintf(ctx->viewer," %G (%10.8e)\n",sigma[i],(double)errest[i]);
274:       PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)svd)->tablevel);
275:     }
276:     ctx->oldnconv = nconv;
277:   }
278:   return(0);
279: }

283: PetscErrorCode SVDMonitorLG(SVD svd,PetscInt its,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest,void *monctx)
284: {
285:   PetscViewer    viewer = (PetscViewer) monctx;
286:   PetscDraw      draw,draw1;
287:   PetscDrawLG    lg,lg1;
289:   PetscReal      x,y,p;

292:   if (!viewer) { viewer = PETSC_VIEWER_DRAW_(((PetscObject)svd)->comm); }
293:   PetscViewerDrawGetDraw(viewer,0,&draw);
294:   PetscViewerDrawGetDrawLG(viewer,0,&lg);
295:   PetscViewerDrawGetDraw(viewer,1,&draw1);
296:   PetscViewerDrawGetDrawLG(viewer,1,&lg1);

298:   if (!its) {
299:     PetscDrawSetTitle(draw,"Error estimates");
300:     PetscDrawSetDoubleBuffer(draw);
301:     PetscDrawLGSetDimension(lg,1);
302:     PetscDrawLGReset(lg);
303:     PetscDrawLGSetLimits(lg,0,1.0,log10(svd->tol)-2,0.0);

305:     PetscDrawSetTitle(draw1,"Approximate singular values");
306:     PetscDrawSetDoubleBuffer(draw1);
307:     PetscDrawLGSetDimension(lg1,1);
308:     PetscDrawLGReset(lg1);
309:     PetscDrawLGSetLimits(lg1,0,1.0,1.e20,-1.e20);
310:   }

312:   x = (PetscReal) its;
313:   if (errest[nconv] > 0.0) y = log10(errest[nconv]); else y = 0.0;
314:   PetscDrawLGAddPoint(lg,&x,&y);

316:   PetscDrawLGAddPoint(lg1,&x,svd->sigma);
317:   PetscDrawGetPause(draw1,&p);
318:   PetscDrawSetPause(draw1,0);
319:   PetscDrawLGDraw(lg1);
320:   PetscDrawSetPause(draw1,p);
321: 
322:   PetscDrawLGDraw(lg);
323:   return(0);
324: }

328: PetscErrorCode SVDMonitorLGAll(SVD svd,PetscInt its,PetscInt nconv,PetscReal *sigma,PetscReal *errest,PetscInt nest,void *monctx)
329: {
330:   PetscViewer    viewer = (PetscViewer) monctx;
331:   PetscDraw      draw,draw1;
332:   PetscDrawLG    lg,lg1;
334:   PetscReal      *x,*y,p;
335:   PetscInt       i,n = PetscMin(svd->nsv,255);

338:   if (!viewer) { viewer = PETSC_VIEWER_DRAW_(((PetscObject)svd)->comm); }
339:   PetscViewerDrawGetDraw(viewer,0,&draw);
340:   PetscViewerDrawGetDrawLG(viewer,0,&lg);
341:   PetscViewerDrawGetDraw(viewer,1,&draw1);
342:   PetscViewerDrawGetDrawLG(viewer,1,&lg1);

344:   if (!its) {
345:     PetscDrawSetTitle(draw,"Error estimates");
346:     PetscDrawSetDoubleBuffer(draw);
347:     PetscDrawLGSetDimension(lg,n);
348:     PetscDrawLGReset(lg);
349:     PetscDrawLGSetLimits(lg,0,1.0,log10(svd->tol)-2,0.0);

351:     PetscDrawSetTitle(draw1,"Approximate singular values");
352:     PetscDrawSetDoubleBuffer(draw1);
353:     PetscDrawLGSetDimension(lg1,n);
354:     PetscDrawLGReset(lg1);
355:     PetscDrawLGSetLimits(lg1,0,1.0,1.e20,-1.e20);
356:   }

358:   PetscMalloc(sizeof(PetscReal)*n,&x);
359:   PetscMalloc(sizeof(PetscReal)*n,&y);
360:   for (i=0;i<n;i++) {
361:     x[i] = (PetscReal) its;
362:     if (i < nest && errest[i] > 0.0) y[i] = log10(errest[i]);
363:     else y[i] = 0.0;
364:   }
365:   PetscDrawLGAddPoint(lg,x,y);

367:   PetscDrawLGAddPoint(lg1,x,svd->sigma);
368:   PetscDrawGetPause(draw1,&p);
369:   PetscDrawSetPause(draw1,0);
370:   PetscDrawLGDraw(lg1);
371:   PetscDrawSetPause(draw1,p);
372: 
373:   PetscDrawLGDraw(lg);
374:   PetscFree(x);
375:   PetscFree(y);
376:   return(0);
377: }