Actual source code: qepmon.c

  1: /*
  2:       QEP 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/qepimpl.h>      /*I "slepcqep.h" I*/

 28: /*
 29:    Runs the user provided monitor routines, if any.
 30: */
 31: PetscErrorCode QEPMonitor(QEP qep,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
 32: {
 34:   PetscInt       i,n = qep->numbermonitors;

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

 45: /*@C
 46:    QEPMonitorSet - Sets an ADDITIONAL function to be called at every 
 47:    iteration to monitor the error estimates for each requested eigenpair.
 48:       
 49:    Logically Collective on QEP

 51:    Input Parameters:
 52: +  qep     - eigensolver context obtained from QEPCreate()
 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)
 56: -  monitordestroy - [optional] routine that frees monitor context
 57:           (may be PETSC_NULL)

 59:    Calling Sequence of monitor:
 60: $     monitor (QEP qep, int its, int nconv, PetscScalar *eigr, PetscScalar *eigi, PetscReal* errest, int nest, void *mctx)

 62: +  qep    - quadratic eigensolver context obtained from QEPCreate()
 63: .  its    - iteration number
 64: .  nconv  - number of converged eigenpairs
 65: .  eigr   - real part of the eigenvalues
 66: .  eigi   - imaginary part of the eigenvalues
 67: .  errest - relative error estimates for each eigenpair
 68: .  nest   - number of error estimates
 69: -  mctx   - optional monitoring context, as set by QEPMonitorSet()

 71:    Options Database Keys:
 72: +    -qep_monitor          - print only the first error estimate
 73: .    -qep_monitor_all      - print error estimates at each iteration
 74: .    -qep_monitor_conv     - print the eigenvalue approximations only when
 75:       convergence has been reached
 76: .    -qep_monitor_draw     - sets line graph monitor for the first unconverged
 77:       approximate eigenvalue
 78: .    -qep_monitor_draw_all - sets line graph monitor for all unconverged
 79:       approximate eigenvalue
 80: -    -qep_monitor_cancel   - cancels all monitors that have been hardwired into
 81:       a code by calls to QEPMonitorSet(), but does not cancel those set via
 82:       the options database.

 84:    Notes:  
 85:    Several different monitoring routines may be set by calling
 86:    QEPMonitorSet() multiple times; all will be called in the 
 87:    order in which they were set.

 89:    Level: intermediate

 91: .seealso: QEPMonitorFirst(), QEPMonitorAll(), QEPMonitorLG(), QEPMonitorLGAll(), QEPMonitorCancel()
 92: @*/
 93: PetscErrorCode QEPMonitorSet(QEP qep,PetscErrorCode (*monitor)(QEP,PetscInt,PetscInt,PetscScalar*,PetscScalar*,PetscReal*,PetscInt,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
 94: {
 97:   if (qep->numbermonitors >= MAXQEPMONITORS) {
 98:     SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many QEP monitors set");
 99:   }
100:   qep->monitor[qep->numbermonitors]           = monitor;
101:   qep->monitorcontext[qep->numbermonitors]    = (void*)mctx;
102:   qep->monitordestroy[qep->numbermonitors++]  = monitordestroy;
103:   return(0);
104: }

108: /*@
109:    QEPMonitorCancel - Clears all monitors for a QEP object.

111:    Logically Collective on QEP

113:    Input Parameters:
114: .  qep - eigensolver context obtained from QEPCreate()

116:    Options Database Key:
117: .    -qep_monitor_cancel - Cancels all monitors that have been hardwired 
118:       into a code by calls to QEPMonitorSet(),
119:       but does not cancel those set via the options database.

121:    Level: intermediate

123: .seealso: QEPMonitorSet()
124: @*/
125: PetscErrorCode QEPMonitorCancel(QEP qep)
126: {
128:   PetscInt       i;

132:   for (i=0; i<qep->numbermonitors; i++) {
133:     if (qep->monitordestroy[i]) {
134:       (*qep->monitordestroy[i])(&qep->monitorcontext[i]);
135:     }
136:   }
137:   qep->numbermonitors = 0;
138:   return(0);
139: }

143: /*@C
144:    QEPGetMonitorContext - Gets the monitor context, as set by 
145:    QEPMonitorSet() for the FIRST monitor only.

147:    Not Collective

149:    Input Parameter:
150: .  qep - eigensolver context obtained from QEPCreate()

152:    Output Parameter:
153: .  ctx - monitor context

155:    Level: intermediate

157: .seealso: QEPMonitorSet(), QEPDefaultMonitor()
158: @*/
159: PetscErrorCode QEPGetMonitorContext(QEP qep,void **ctx)
160: {
163:   *ctx =      (qep->monitorcontext[0]);
164:   return(0);
165: }

169: /*@C
170:    QEPMonitorAll - Print the current approximate values and 
171:    error estimates at each iteration of the quadratic eigensolver.

173:    Collective on QEP

175:    Input Parameters:
176: +  qep    - quadratic eigensolver context
177: .  its    - iteration number
178: .  nconv  - number of converged eigenpairs so far
179: .  eigr   - real part of the eigenvalues
180: .  eigi   - imaginary part of the eigenvalues
181: .  errest - error estimates
182: .  nest   - number of error estimates to display
183: -  dummy  - unused monitor context 

185:    Level: intermediate

187: .seealso: QEPMonitorSet(), QEPMonitorFirst(), QEPMonitorConverged()
188: @*/
189: PetscErrorCode QEPMonitorAll(QEP qep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *dummy)
190: {
192:   PetscInt       i;
193:   PetscViewer    viewer = dummy? (PetscViewer)dummy: PETSC_VIEWER_STDOUT_(((PetscObject)qep)->comm);

196:   if (its) {
197:     PetscViewerASCIIAddTab(viewer,((PetscObject)qep)->tablevel);
198:     PetscViewerASCIIPrintf(viewer,"%3D QEP nconv=%D Values (Errors)",its,nconv);
199:     for (i=0;i<nest;i++) {
200: #if defined(PETSC_USE_COMPLEX)
201:       PetscViewerASCIIPrintf(viewer," %G%+Gi",PetscRealPart(eigr[i]),PetscImaginaryPart(eigr[i]));
202: #else
203:       PetscViewerASCIIPrintf(viewer," %G",eigr[i]);
204:       if (eigi[i]!=0.0) { PetscViewerASCIIPrintf(viewer,"%+Gi",eigi[i]); }
205: #endif
206:       PetscViewerASCIIPrintf(viewer," (%10.8e)",(double)errest[i]);
207:     }
208:     PetscViewerASCIIPrintf(viewer,"\n");
209:     PetscViewerASCIISubtractTab(viewer,((PetscObject)qep)->tablevel);
210:   }
211:   return(0);
212: }

216: /*@C
217:    QEPMonitorFirst - Print the first unconverged approximate value and 
218:    error estimate at each iteration of the quadratic eigensolver.

220:    Collective on QEP

222:    Input Parameters:
223: +  qep    - quadratic eigensolver context
224: .  its    - iteration number
225: .  nconv  - number of converged eigenpairs so far
226: .  eigr   - real part of the eigenvalues
227: .  eigi   - imaginary part of the eigenvalues
228: .  errest - error estimates
229: .  nest   - number of error estimates to display
230: -  dummy  - unused monitor context 

232:    Level: intermediate

234: .seealso: QEPMonitorSet(), QEPMonitorAll(), QEPMonitorConverged()
235: @*/
236: PetscErrorCode QEPMonitorFirst(QEP qep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *dummy)
237: {
239:   PetscViewer    viewer = dummy? (PetscViewer)dummy: PETSC_VIEWER_STDOUT_(((PetscObject)qep)->comm);

242:   if (its && nconv<nest) {
243:     PetscViewerASCIIAddTab(viewer,((PetscObject)qep)->tablevel);
244:     PetscViewerASCIIPrintf(viewer,"%3D QEP nconv=%D first unconverged value (error)",its,nconv);
245: #if defined(PETSC_USE_COMPLEX)
246:     PetscViewerASCIIPrintf(viewer," %G%+Gi",PetscRealPart(eigr[nconv]),PetscImaginaryPart(eigr[nconv]));
247: #else
248:     PetscViewerASCIIPrintf(viewer," %G",eigr[nconv]);
249:     if (eigi[nconv]!=0.0) { PetscViewerASCIIPrintf(viewer,"%+Gi",eigi[nconv]); }
250: #endif
251:     PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[nconv]);
252:     PetscViewerASCIISubtractTab(viewer,((PetscObject)qep)->tablevel);
253:   }
254:   return(0);
255: }

259: /*@C
260:    QEPMonitorConverged - Print the approximate values and 
261:    error estimates as they converge.

263:    Collective on QEP

265:    Input Parameters:
266: +  qep    - quadratic eigensolver context
267: .  its    - iteration number
268: .  nconv  - number of converged eigenpairs so far
269: .  eigr   - real part of the eigenvalues
270: .  eigi   - imaginary part of the eigenvalues
271: .  errest - error estimates
272: .  nest   - number of error estimates to display
273: -  dummy  - unused monitor context 

275:    Level: intermediate

277: .seealso: QEPMonitorSet(), QEPMonitorFirst(), QEPMonitorAll()
278: @*/
279: PetscErrorCode QEPMonitorConverged(QEP qep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *dummy)
280: {
281:   PetscErrorCode   ierr;
282:   PetscInt         i;
283:   SlepcConvMonitor ctx = (SlepcConvMonitor)dummy;

286:   if (!its) {
287:     ctx->oldnconv = 0;
288:   } else {
289:     for (i=ctx->oldnconv;i<nconv;i++) {
290:       PetscViewerASCIIAddTab(ctx->viewer,((PetscObject)qep)->tablevel);
291:       PetscViewerASCIIPrintf(ctx->viewer,"%3D QEP converged value (error) #%D",its,i);
292: #if defined(PETSC_USE_COMPLEX)
293:       PetscViewerASCIIPrintf(ctx->viewer," %G%+Gi",PetscRealPart(eigr[i]),PetscImaginaryPart(eigr[i]));
294: #else
295:       PetscViewerASCIIPrintf(ctx->viewer," %G",eigr[i]);
296:       if (eigi[i]!=0.0) { PetscViewerASCIIPrintf(ctx->viewer,"%+Gi",eigi[i]); }
297: #endif
298:       PetscViewerASCIIPrintf(ctx->viewer," (%10.8e)\n",(double)errest[i]);
299:       PetscViewerASCIISubtractTab(ctx->viewer,((PetscObject)qep)->tablevel);
300:     }
301:     ctx->oldnconv = nconv;
302:   }
303:   return(0);
304: }

308: PetscErrorCode QEPMonitorLG(QEP qep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *monctx)
309: {
310:   PetscViewer    viewer = (PetscViewer) monctx;
311:   PetscDraw      draw;
312:   PetscDrawLG    lg;
314:   PetscReal      x,y;

317:   if (!viewer) { viewer = PETSC_VIEWER_DRAW_(((PetscObject)qep)->comm); }
318:   PetscViewerDrawGetDraw(viewer,0,&draw);
319:   PetscViewerDrawGetDrawLG(viewer,0,&lg);
320:   if (!its) {
321:     PetscDrawSetTitle(draw,"Error estimates");
322:     PetscDrawSetDoubleBuffer(draw);
323:     PetscDrawLGSetDimension(lg,1);
324:     PetscDrawLGReset(lg);
325:     PetscDrawLGSetLimits(lg,0,1.0,log10(qep->tol)-2,0.0);
326:   }

328:   x = (PetscReal) its;
329:   if (errest[nconv] > 0.0) y = log10(errest[nconv]); else y = 0.0;
330:   PetscDrawLGAddPoint(lg,&x,&y);

332:   PetscDrawLGDraw(lg);
333:   return(0);
334: }

338: PetscErrorCode QEPMonitorLGAll(QEP qep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *monctx)
339: {
340:   PetscViewer    viewer = (PetscViewer) monctx;
341:   PetscDraw      draw;
342:   PetscDrawLG    lg;
344:   PetscReal      *x,*y;
345:   PetscInt       i,n = PetscMin(qep->nev,255);

348:   if (!viewer) { viewer = PETSC_VIEWER_DRAW_(((PetscObject)qep)->comm); }
349:   PetscViewerDrawGetDraw(viewer,0,&draw);
350:   PetscViewerDrawGetDrawLG(viewer,0,&lg);
351:   if (!its) {
352:     PetscDrawSetTitle(draw,"Error estimates");
353:     PetscDrawSetDoubleBuffer(draw);
354:     PetscDrawLGSetDimension(lg,n);
355:     PetscDrawLGReset(lg);
356:     PetscDrawLGSetLimits(lg,0,1.0,log10(qep->tol)-2,0.0);
357:   }

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

368:   PetscDrawLGDraw(lg);
369:   PetscFree(x);
370:   PetscFree(y);
371:   return(0);
372: }