Actual source code: pepmon.c
slepc-main 2024-12-17
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: PEP routines related to monitors
12: */
14: #include <slepc/private/pepimpl.h>
15: #include <petscdraw.h>
17: PetscErrorCode PEPMonitorLGCreate(MPI_Comm comm,const char host[],const char label[],const char metric[],PetscInt l,const char *names[],int x,int y,int m,int n,PetscDrawLG *lgctx)
18: {
19: PetscDraw draw;
20: PetscDrawAxis axis;
21: PetscDrawLG lg;
23: PetscFunctionBegin;
24: PetscCall(PetscDrawCreate(comm,host,label,x,y,m,n,&draw));
25: PetscCall(PetscDrawSetFromOptions(draw));
26: PetscCall(PetscDrawLGCreate(draw,l,&lg));
27: if (names) PetscCall(PetscDrawLGSetLegend(lg,names));
28: PetscCall(PetscDrawLGSetFromOptions(lg));
29: PetscCall(PetscDrawLGGetAxis(lg,&axis));
30: PetscCall(PetscDrawAxisSetLabels(axis,"Convergence","Iteration",metric));
31: PetscCall(PetscDrawDestroy(&draw));
32: *lgctx = lg;
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
36: /*
37: Runs the user provided monitor routines, if any.
38: */
39: PetscErrorCode PEPMonitor(PEP pep,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
40: {
41: PetscInt i,n = pep->numbermonitors;
43: PetscFunctionBegin;
44: for (i=0;i<n;i++) PetscCall((*pep->monitor[i])(pep,it,nconv,eigr,eigi,errest,nest,pep->monitorcontext[i]));
45: PetscFunctionReturn(PETSC_SUCCESS);
46: }
48: /*@C
49: PEPMonitorSet - Sets an ADDITIONAL function to be called at every
50: iteration to monitor the error estimates for each requested eigenpair.
52: Logically Collective
54: Input Parameters:
55: + pep - eigensolver context obtained from PEPCreate()
56: . monitor - pointer to function (if this is NULL, it turns off monitoring)
57: . mctx - [optional] context for private data for the
58: monitor routine (use NULL if no context is desired)
59: - monitordestroy - [optional] routine that frees monitor context (may be NULL),
60: see PetscCtxDestroyFn for the calling sequence
62: Calling sequence of monitor:
63: $ PetscErrorCode monitor(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *mctx)
64: + pep - polynomial eigensolver context obtained from PEPCreate()
65: . its - iteration number
66: . nconv - number of converged eigenpairs
67: . eigr - real part of the eigenvalues
68: . eigi - imaginary part of the eigenvalues
69: . errest - relative error estimates for each eigenpair
70: . nest - number of error estimates
71: - mctx - optional monitoring context, as set by PEPMonitorSet()
73: Options Database Keys:
74: + -pep_monitor - print only the first error estimate
75: . -pep_monitor_all - print error estimates at each iteration
76: . -pep_monitor_conv - print the eigenvalue approximations only when
77: convergence has been reached
78: . -pep_monitor draw::draw_lg - sets line graph monitor for the first unconverged
79: approximate eigenvalue
80: . -pep_monitor_all draw::draw_lg - sets line graph monitor for all unconverged
81: approximate eigenvalues
82: . -pep_monitor_conv draw::draw_lg - sets line graph monitor for convergence history
83: - -pep_monitor_cancel - cancels all monitors that have been hardwired into
84: a code by calls to PEPMonitorSet(), but does not cancel those set via
85: the options database.
87: Notes:
88: Several different monitoring routines may be set by calling
89: PEPMonitorSet() multiple times; all will be called in the
90: order in which they were set.
92: Level: intermediate
94: .seealso: PEPMonitorFirst(), PEPMonitorAll(), PEPMonitorCancel()
95: @*/
96: PetscErrorCode PEPMonitorSet(PEP pep,PetscErrorCode (*monitor)(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *mctx),void *mctx,PetscCtxDestroyFn *monitordestroy)
97: {
98: PetscFunctionBegin;
100: PetscCheck(pep->numbermonitors<MAXPEPMONITORS,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Too many PEP monitors set");
101: pep->monitor[pep->numbermonitors] = monitor;
102: pep->monitorcontext[pep->numbermonitors] = (void*)mctx;
103: pep->monitordestroy[pep->numbermonitors++] = monitordestroy;
104: PetscFunctionReturn(PETSC_SUCCESS);
105: }
107: /*@
108: PEPMonitorCancel - Clears all monitors for a PEP object.
110: Logically Collective
112: Input Parameters:
113: . pep - eigensolver context obtained from PEPCreate()
115: Options Database Key:
116: . -pep_monitor_cancel - Cancels all monitors that have been hardwired
117: into a code by calls to PEPMonitorSet(),
118: but does not cancel those set via the options database.
120: Level: intermediate
122: .seealso: PEPMonitorSet()
123: @*/
124: PetscErrorCode PEPMonitorCancel(PEP pep)
125: {
126: PetscInt i;
128: PetscFunctionBegin;
130: for (i=0; i<pep->numbermonitors; i++) {
131: if (pep->monitordestroy[i]) PetscCall((*pep->monitordestroy[i])(&pep->monitorcontext[i]));
132: }
133: pep->numbermonitors = 0;
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@C
138: PEPGetMonitorContext - Gets the monitor context, as set by
139: PEPMonitorSet() for the FIRST monitor only.
141: Not Collective
143: Input Parameter:
144: . pep - eigensolver context obtained from PEPCreate()
146: Output Parameter:
147: . ctx - monitor context
149: Level: intermediate
151: .seealso: PEPMonitorSet(), PEPDefaultMonitor()
152: @*/
153: PetscErrorCode PEPGetMonitorContext(PEP pep,void *ctx)
154: {
155: PetscFunctionBegin;
157: *(void**)ctx = pep->monitorcontext[0];
158: PetscFunctionReturn(PETSC_SUCCESS);
159: }
161: /*
162: Helper function to compute eigenvalue that must be viewed in monitor
163: */
164: static PetscErrorCode PEPMonitorGetTrueEig(PEP pep,PetscScalar *er,PetscScalar *ei)
165: {
166: PetscBool flg,sinv;
168: PetscFunctionBegin;
169: PetscCall(STBackTransform(pep->st,1,er,ei));
170: if (pep->sfactor!=1.0) {
171: PetscCall(STGetTransform(pep->st,&flg));
172: PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
173: if (flg && sinv) {
174: *er /= pep->sfactor; *ei /= pep->sfactor;
175: } else {
176: *er *= pep->sfactor; *ei *= pep->sfactor;
177: }
178: }
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
182: /*@C
183: PEPMonitorFirst - Print the first unconverged approximate value and
184: error estimate at each iteration of the polynomial eigensolver.
186: Collective
188: Input Parameters:
189: + pep - polynomial eigensolver context
190: . its - iteration number
191: . nconv - number of converged eigenpairs so far
192: . eigr - real part of the eigenvalues
193: . eigi - imaginary part of the eigenvalues
194: . errest - error estimates
195: . nest - number of error estimates to display
196: - vf - viewer and format for monitoring
198: Options Database Key:
199: . -pep_monitor - activates PEPMonitorFirst()
201: Level: intermediate
203: .seealso: PEPMonitorSet(), PEPMonitorAll(), PEPMonitorConverged()
204: @*/
205: PetscErrorCode PEPMonitorFirst(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
206: {
207: PetscScalar er,ei;
208: PetscViewer viewer = vf->viewer;
210: PetscFunctionBegin;
213: if (its==1 && ((PetscObject)pep)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer," Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)pep)->prefix));
214: if (nconv<nest) {
215: PetscCall(PetscViewerPushFormat(viewer,vf->format));
216: PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)pep)->tablevel));
217: PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " PEP nconv=%" PetscInt_FMT " first unconverged value (error)",its,nconv));
218: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
219: er = eigr[nconv]; ei = eigi[nconv];
220: PetscCall(PEPMonitorGetTrueEig(pep,&er,&ei));
221: #if defined(PETSC_USE_COMPLEX)
222: PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
223: #else
224: PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
225: if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
226: #endif
227: PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[nconv]));
228: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
229: PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)pep)->tablevel));
230: PetscCall(PetscViewerPopFormat(viewer));
231: }
232: PetscFunctionReturn(PETSC_SUCCESS);
233: }
235: /*@C
236: PEPMonitorAll - Print the current approximate values and
237: error estimates at each iteration of the polynomial eigensolver.
239: Collective
241: Input Parameters:
242: + pep - polynomial eigensolver context
243: . its - iteration number
244: . nconv - number of converged eigenpairs so far
245: . eigr - real part of the eigenvalues
246: . eigi - imaginary part of the eigenvalues
247: . errest - error estimates
248: . nest - number of error estimates to display
249: - vf - viewer and format for monitoring
251: Options Database Key:
252: . -pep_monitor_all - activates PEPMonitorAll()
254: Level: intermediate
256: .seealso: PEPMonitorSet(), PEPMonitorFirst(), PEPMonitorConverged()
257: @*/
258: PetscErrorCode PEPMonitorAll(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
259: {
260: PetscInt i;
261: PetscScalar er,ei;
262: PetscViewer viewer = vf->viewer;
264: PetscFunctionBegin;
267: PetscCall(PetscViewerPushFormat(viewer,vf->format));
268: PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)pep)->tablevel));
269: if (its==1 && ((PetscObject)pep)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer," Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)pep)->prefix));
270: PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " PEP nconv=%" PetscInt_FMT " Values (Errors)",its,nconv));
271: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
272: for (i=0;i<nest;i++) {
273: er = eigr[i]; ei = eigi[i];
274: PetscCall(PEPMonitorGetTrueEig(pep,&er,&ei));
275: #if defined(PETSC_USE_COMPLEX)
276: PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
277: #else
278: PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
279: if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
280: #endif
281: PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)",(double)errest[i]));
282: }
283: PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
284: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
285: PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)pep)->tablevel));
286: PetscCall(PetscViewerPopFormat(viewer));
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /*@C
291: PEPMonitorConverged - Print the approximate values and
292: error estimates as they converge.
294: Collective
296: Input Parameters:
297: + pep - polynomial eigensolver context
298: . its - iteration number
299: . nconv - number of converged eigenpairs so far
300: . eigr - real part of the eigenvalues
301: . eigi - imaginary part of the eigenvalues
302: . errest - error estimates
303: . nest - number of error estimates to display
304: - vf - viewer and format for monitoring
306: Options Database Key:
307: . -pep_monitor_conv - activates PEPMonitorConverged()
309: Level: intermediate
311: .seealso: PEPMonitorSet(), PEPMonitorFirst(), PEPMonitorAll()
312: @*/
313: PetscErrorCode PEPMonitorConverged(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
314: {
315: PetscInt i;
316: PetscScalar er,ei;
317: PetscViewer viewer = vf->viewer;
318: SlepcConvMon ctx;
320: PetscFunctionBegin;
323: ctx = (SlepcConvMon)vf->data;
324: if (its==1 && ((PetscObject)pep)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer," Convergence history for %s solve.\n",((PetscObject)pep)->prefix));
325: if (its==1) ctx->oldnconv = 0;
326: if (ctx->oldnconv!=nconv) {
327: PetscCall(PetscViewerPushFormat(viewer,vf->format));
328: PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)pep)->tablevel));
329: for (i=ctx->oldnconv;i<nconv;i++) {
330: PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " PEP converged value (error) #%" PetscInt_FMT,its,i));
331: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
332: er = eigr[i]; ei = eigi[i];
333: PetscCall(PEPMonitorGetTrueEig(pep,&er,&ei));
334: #if defined(PETSC_USE_COMPLEX)
335: PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
336: #else
337: PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
338: if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
339: #endif
340: PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[i]));
341: PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
342: }
343: PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)pep)->tablevel));
344: PetscCall(PetscViewerPopFormat(viewer));
345: ctx->oldnconv = nconv;
346: }
347: PetscFunctionReturn(PETSC_SUCCESS);
348: }
350: PetscErrorCode PEPMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
351: {
352: SlepcConvMon mctx;
354: PetscFunctionBegin;
355: PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
356: PetscCall(PetscNew(&mctx));
357: mctx->ctx = ctx;
358: (*vf)->data = (void*)mctx;
359: PetscFunctionReturn(PETSC_SUCCESS);
360: }
362: PetscErrorCode PEPMonitorConvergedDestroy(PetscViewerAndFormat **vf)
363: {
364: PetscFunctionBegin;
365: if (!*vf) PetscFunctionReturn(PETSC_SUCCESS);
366: PetscCall(PetscFree((*vf)->data));
367: PetscCall(PetscViewerDestroy(&(*vf)->viewer));
368: PetscCall(PetscDrawLGDestroy(&(*vf)->lg));
369: PetscCall(PetscFree(*vf));
370: PetscFunctionReturn(PETSC_SUCCESS);
371: }
373: /*@C
374: PEPMonitorFirstDrawLG - Plots the error estimate of the first unconverged
375: approximation at each iteration of the polynomial eigensolver.
377: Collective
379: Input Parameters:
380: + pep - polynomial eigensolver context
381: . its - iteration number
382: . nconv - number of converged eigenpairs so far
383: . eigr - real part of the eigenvalues
384: . eigi - imaginary part of the eigenvalues
385: . errest - error estimates
386: . nest - number of error estimates to display
387: - vf - viewer and format for monitoring
389: Options Database Key:
390: . -pep_monitor draw::draw_lg - activates PEPMonitorFirstDrawLG()
392: Level: intermediate
394: .seealso: PEPMonitorSet()
395: @*/
396: PetscErrorCode PEPMonitorFirstDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
397: {
398: PetscViewer viewer = vf->viewer;
399: PetscDrawLG lg = vf->lg;
400: PetscReal x,y;
402: PetscFunctionBegin;
406: PetscCall(PetscViewerPushFormat(viewer,vf->format));
407: if (its==1) {
408: PetscCall(PetscDrawLGReset(lg));
409: PetscCall(PetscDrawLGSetDimension(lg,1));
410: PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(pep->tol)-2,0.0));
411: }
412: if (nconv<nest) {
413: x = (PetscReal)its;
414: if (errest[nconv] > 0.0) y = PetscLog10Real(errest[nconv]);
415: else y = 0.0;
416: PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
417: if (its <= 20 || !(its % 5) || pep->reason) {
418: PetscCall(PetscDrawLGDraw(lg));
419: PetscCall(PetscDrawLGSave(lg));
420: }
421: }
422: PetscCall(PetscViewerPopFormat(viewer));
423: PetscFunctionReturn(PETSC_SUCCESS);
424: }
426: /*@C
427: PEPMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.
429: Collective
431: Input Parameters:
432: + viewer - the viewer
433: . format - the viewer format
434: - ctx - an optional user context
436: Output Parameter:
437: . vf - the viewer and format context
439: Level: intermediate
441: .seealso: PEPMonitorSet()
442: @*/
443: PetscErrorCode PEPMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
444: {
445: PetscFunctionBegin;
446: PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
447: (*vf)->data = ctx;
448: PetscCall(PEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
449: PetscFunctionReturn(PETSC_SUCCESS);
450: }
452: /*@C
453: PEPMonitorAllDrawLG - Plots the error estimate of all unconverged
454: approximations at each iteration of the polynomial eigensolver.
456: Collective
458: Input Parameters:
459: + pep - polynomial eigensolver context
460: . its - iteration number
461: . nconv - number of converged eigenpairs so far
462: . eigr - real part of the eigenvalues
463: . eigi - imaginary part of the eigenvalues
464: . errest - error estimates
465: . nest - number of error estimates to display
466: - vf - viewer and format for monitoring
468: Options Database Key:
469: . -pep_monitor_all draw::draw_lg - activates PEPMonitorAllDrawLG()
471: Level: intermediate
473: .seealso: PEPMonitorSet()
474: @*/
475: PetscErrorCode PEPMonitorAllDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
476: {
477: PetscViewer viewer = vf->viewer;
478: PetscDrawLG lg = vf->lg;
479: PetscInt i,n = PetscMin(pep->nev,255);
480: PetscReal *x,*y;
482: PetscFunctionBegin;
486: PetscCall(PetscViewerPushFormat(viewer,vf->format));
487: if (its==1) {
488: PetscCall(PetscDrawLGReset(lg));
489: PetscCall(PetscDrawLGSetDimension(lg,n));
490: PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(pep->tol)-2,0.0));
491: }
492: PetscCall(PetscMalloc2(n,&x,n,&y));
493: for (i=0;i<n;i++) {
494: x[i] = (PetscReal)its;
495: if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
496: else y[i] = 0.0;
497: }
498: PetscCall(PetscDrawLGAddPoint(lg,x,y));
499: if (its <= 20 || !(its % 5) || pep->reason) {
500: PetscCall(PetscDrawLGDraw(lg));
501: PetscCall(PetscDrawLGSave(lg));
502: }
503: PetscCall(PetscFree2(x,y));
504: PetscCall(PetscViewerPopFormat(viewer));
505: PetscFunctionReturn(PETSC_SUCCESS);
506: }
508: /*@C
509: PEPMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.
511: Collective
513: Input Parameters:
514: + viewer - the viewer
515: . format - the viewer format
516: - ctx - an optional user context
518: Output Parameter:
519: . vf - the viewer and format context
521: Level: intermediate
523: .seealso: PEPMonitorSet()
524: @*/
525: PetscErrorCode PEPMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
526: {
527: PetscFunctionBegin;
528: PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
529: (*vf)->data = ctx;
530: PetscCall(PEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
534: /*@C
535: PEPMonitorConvergedDrawLG - Plots the number of converged eigenvalues
536: at each iteration of the polynomial eigensolver.
538: Collective
540: Input Parameters:
541: + pep - polynomial eigensolver context
542: . its - iteration number
543: . nconv - number of converged eigenpairs so far
544: . eigr - real part of the eigenvalues
545: . eigi - imaginary part of the eigenvalues
546: . errest - error estimates
547: . nest - number of error estimates to display
548: - vf - viewer and format for monitoring
550: Options Database Key:
551: . -pep_monitor_conv draw::draw_lg - activates PEPMonitorConvergedDrawLG()
553: Level: intermediate
555: .seealso: PEPMonitorSet()
556: @*/
557: PetscErrorCode PEPMonitorConvergedDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
558: {
559: PetscViewer viewer = vf->viewer;
560: PetscDrawLG lg = vf->lg;
561: PetscReal x,y;
563: PetscFunctionBegin;
567: PetscCall(PetscViewerPushFormat(viewer,vf->format));
568: if (its==1) {
569: PetscCall(PetscDrawLGReset(lg));
570: PetscCall(PetscDrawLGSetDimension(lg,1));
571: PetscCall(PetscDrawLGSetLimits(lg,1,1,0,pep->nev));
572: }
573: x = (PetscReal)its;
574: y = (PetscReal)pep->nconv;
575: PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
576: if (its <= 20 || !(its % 5) || pep->reason) {
577: PetscCall(PetscDrawLGDraw(lg));
578: PetscCall(PetscDrawLGSave(lg));
579: }
580: PetscCall(PetscViewerPopFormat(viewer));
581: PetscFunctionReturn(PETSC_SUCCESS);
582: }
584: /*@C
585: PEPMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.
587: Collective
589: Input Parameters:
590: + viewer - the viewer
591: . format - the viewer format
592: - ctx - an optional user context
594: Output Parameter:
595: . vf - the viewer and format context
597: Level: intermediate
599: .seealso: PEPMonitorSet()
600: @*/
601: PetscErrorCode PEPMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
602: {
603: SlepcConvMon mctx;
605: PetscFunctionBegin;
606: PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
607: PetscCall(PetscNew(&mctx));
608: mctx->ctx = ctx;
609: (*vf)->data = (void*)mctx;
610: PetscCall(PEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
611: PetscFunctionReturn(PETSC_SUCCESS);
612: }