xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 0baf8eba40dbc839082666f9f7396a225d6f663c)
1 #include <../src/sys/classes/viewer/impls/draw/vdraw.h> /*I "petscdraw.h" I*/
2 #include <petscviewer.h>                                /*I "petscviewer.h" I*/
3 
4 static PetscErrorCode PetscViewerDestroy_Draw(PetscViewer v)
5 {
6   PetscInt          i;
7   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
8 
9   PetscFunctionBegin;
10   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Destroying PetscViewer without first restoring singleton");
11   for (i = 0; i < vdraw->draw_max; i++) {
12     PetscCall(PetscDrawAxisDestroy(&vdraw->drawaxis[i]));
13     PetscCall(PetscDrawLGDestroy(&vdraw->drawlg[i]));
14     PetscCall(PetscDrawDestroy(&vdraw->draw[i]));
15   }
16   PetscCall(PetscFree(vdraw->display));
17   PetscCall(PetscFree(vdraw->title));
18   PetscCall(PetscFree3(vdraw->draw, vdraw->drawlg, vdraw->drawaxis));
19   PetscCall(PetscFree(vdraw->bounds));
20   PetscCall(PetscFree(vdraw->drawtype));
21   PetscCall(PetscFree(v->data));
22   PetscFunctionReturn(PETSC_SUCCESS);
23 }
24 
25 static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
26 {
27   PetscInt          i;
28   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
29 
30   PetscFunctionBegin;
31   for (i = 0; i < vdraw->draw_max; i++) {
32     if (vdraw->draw[i]) PetscCall(PetscDrawFlush(vdraw->draw[i]));
33   }
34   PetscFunctionReturn(PETSC_SUCCESS);
35 }
36 
37 /*@
38   PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
39 
40   Logically Collective
41 
42   Input Parameters:
43 + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
44 - windownumber - how much to add to the base
45 
46   Level: developer
47 
48   Note:
49   A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
50 
51 .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
52 @*/
53 PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
54 {
55   PetscViewer_Draw *vdraw;
56   PetscBool         isdraw;
57 
58   PetscFunctionBegin;
59   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
60   PetscValidLogicalCollectiveInt(viewer, windownumber, 2);
61   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
62   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
63   vdraw = (PetscViewer_Draw *)viewer->data;
64 
65   PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
66   vdraw->draw_base += windownumber;
67   PetscFunctionReturn(PETSC_SUCCESS);
68 }
69 
70 /*@
71   PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
72 
73   Logically Collective
74 
75   Input Parameters:
76 + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
77 - windownumber - value to set the base
78 
79   Level: developer
80 
81   Note:
82   A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
83 
84 .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
85 @*/
86 PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
87 {
88   PetscViewer_Draw *vdraw;
89   PetscBool         isdraw;
90 
91   PetscFunctionBegin;
92   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
93   PetscValidLogicalCollectiveInt(viewer, windownumber, 2);
94   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
95   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
96   vdraw = (PetscViewer_Draw *)viewer->data;
97 
98   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
99   vdraw->draw_base = windownumber;
100   PetscFunctionReturn(PETSC_SUCCESS);
101 }
102 
103 PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
104 {
105   PetscViewer_Draw *vdraw;
106   PetscBool         isdraw;
107 
108   PetscFunctionBegin;
109   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
110   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
111   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
112   vdraw = (PetscViewer_Draw *)v->data;
113 
114   if (w >= 1) vdraw->w = w;
115   if (h >= 1) vdraw->h = h;
116   PetscFunctionReturn(PETSC_SUCCESS);
117 }
118 
119 PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
120 {
121   PetscViewer_Draw *vdraw;
122   PetscBool         isdraw;
123 
124   PetscFunctionBegin;
125   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
126   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
127   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
128   vdraw = (PetscViewer_Draw *)v->data;
129 
130   PetscCall(PetscStrallocpy(display, &vdraw->display));
131   PetscCall(PetscStrallocpy(title, &vdraw->title));
132   if (w >= 1) vdraw->w = w;
133   if (h >= 1) vdraw->h = h;
134   PetscFunctionReturn(PETSC_SUCCESS);
135 }
136 
137 PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
138 {
139   PetscViewer_Draw *vdraw;
140   PetscBool         isdraw;
141 
142   PetscFunctionBegin;
143   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
144   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
145   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
146   vdraw = (PetscViewer_Draw *)v->data;
147 
148   PetscCall(PetscFree(vdraw->title));
149   PetscCall(PetscStrallocpy(title, &vdraw->title));
150   PetscFunctionReturn(PETSC_SUCCESS);
151 }
152 
153 PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
154 {
155   PetscViewer_Draw *vdraw;
156   PetscBool         isdraw;
157 
158   PetscFunctionBegin;
159   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
160   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
161   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
162   vdraw = (PetscViewer_Draw *)v->data;
163 
164   *title = vdraw->title;
165   PetscFunctionReturn(PETSC_SUCCESS);
166 }
167 
168 /*@
169   PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
170   `PETSCVIEWERDRAW`.
171 
172   Collective
173 
174   Input Parameters:
175 + comm    - communicator that will share window
176 . display - the X display on which to open, or `NULL` for the local machine
177 . title   - the title to put in the title bar, or `NULL` for no title
178 . x       - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
179 . y       - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
180 . w       - window width in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
181 - h       - window height in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
182 
183   Output Parameter:
184 . viewer - the `PetscViewer`
185 
186   Options Database Keys:
187 + -draw_type          - use x or null
188 . -nox                - Disables all x-windows output
189 . -display <name>     - Specifies name of machine for the X display
190 . -geometry <x,y,w,h> - allows setting the window location and size
191 - -draw_pause <pause> - Sets time (in seconds) that the
192                         program pauses after `PetscDrawPause()` has been called
193                         (0 is default, -1 implies until user input).
194 
195   Level: beginner
196 
197   Notes:
198   If you want to do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
199   perform the graphics on the `PetscDraw` object.
200 
201   Format options include\:
202 + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
203 - `PETSC_VIEWER_DRAW_LG`    - displays using a line graph
204 
205   Fortran Note:
206   Whenever indicating null character data in a Fortran code,
207   `PETSC_NULL_CHARACTER` must be employed. Thus, `PETSC_NULL_CHARACTER` can be
208   used for the `display` and `title` input parameters.
209 
210 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
211           `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
212 @*/
213 PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
214 {
215   PetscFunctionBegin;
216   PetscCall(PetscViewerCreate(comm, viewer));
217   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
218   PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
219   PetscFunctionReturn(PETSC_SUCCESS);
220 }
221 
222 #include <petsc/private/drawimpl.h>
223 
224 static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
225 {
226   PetscMPIInt       rank;
227   PetscInt          i;
228   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
229 
230   PetscFunctionBegin;
231   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
232   /* only processor zero can use the PetscViewer draw singleton */
233   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
234   if (rank == 0) {
235     PetscMPIInt flg;
236     PetscDraw   draw, sdraw;
237 
238     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
239     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
240     PetscCall(PetscViewerCreate(comm, sviewer));
241     PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
242     svdraw             = (PetscViewer_Draw *)(*sviewer)->data;
243     (*sviewer)->format = viewer->format;
244     for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
245       if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
246     }
247     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
248     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
249     if (draw->savefilename) {
250       PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
251       sdraw->savefilecount  = draw->savefilecount;
252       sdraw->savesinglefile = draw->savesinglefile;
253       sdraw->savemoviefps   = draw->savemoviefps;
254       sdraw->saveonclear    = draw->saveonclear;
255       sdraw->saveonflush    = draw->saveonflush;
256     }
257     if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
258   } else {
259     PetscDraw draw;
260     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
261   }
262   vdraw->singleton_made = PETSC_TRUE;
263   PetscFunctionReturn(PETSC_SUCCESS);
264 }
265 
266 static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
267 {
268   PetscMPIInt       rank;
269   PetscInt          i;
270   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
271 
272   PetscFunctionBegin;
273   PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
274   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
275   if (rank == 0) {
276     PetscDraw draw, sdraw;
277 
278     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
279     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
280     if (draw->savefilename) {
281       draw->savefilecount = sdraw->savefilecount;
282       PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
283     }
284     svdraw = (PetscViewer_Draw *)(*sviewer)->data;
285     for (i = 0; i < vdraw->draw_max; i++) {
286       if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
287     }
288     PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
289     PetscCall(PetscFree((*sviewer)->data));
290     PetscCall(PetscHeaderDestroy(sviewer));
291   } else {
292     PetscDraw draw;
293 
294     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
295     if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
296   }
297 
298   vdraw->singleton_made = PETSC_FALSE;
299   PetscFunctionReturn(PETSC_SUCCESS);
300 }
301 
302 static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
303 {
304   PetscReal bounds[16];
305   PetscInt  nbounds = 16;
306   PetscBool flg;
307 
308   PetscFunctionBegin;
309   PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
310   PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
311   if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
312   PetscOptionsHeadEnd();
313   PetscFunctionReturn(PETSC_SUCCESS);
314 }
315 
316 static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
317 {
318   PetscDraw         draw;
319   PetscInt          i;
320   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
321   PetscBool         iascii;
322 
323   PetscFunctionBegin;
324   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
325   if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
326   /*  If the PetscViewer has just been created then no vdraw->draw yet
327       exists so this will not actually call the viewer on any draws. */
328   for (i = 0; i < vdraw->draw_base; i++) {
329     if (vdraw->draw[i]) {
330       PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
331       PetscCall(PetscDrawView(draw, v));
332     }
333   }
334   PetscFunctionReturn(PETSC_SUCCESS);
335 }
336 
337 /*MC
338    PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
339 
340   Level: beginner
341 
342 .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
343           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
344           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
345           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
346 M*/
347 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
348 {
349   PetscViewer_Draw *vdraw;
350 
351   PetscFunctionBegin;
352   PetscCall(PetscNew(&vdraw));
353   viewer->data = (void *)vdraw;
354 
355   viewer->ops->flush            = PetscViewerFlush_Draw;
356   viewer->ops->view             = PetscViewerView_Draw;
357   viewer->ops->destroy          = PetscViewerDestroy_Draw;
358   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
359   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
360   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
361 
362   /* these are created on the fly if requested */
363   vdraw->draw_max  = 5;
364   vdraw->draw_base = 0;
365   vdraw->w         = PETSC_DECIDE;
366   vdraw->h         = PETSC_DECIDE;
367 
368   PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
369   vdraw->singleton_made = PETSC_FALSE;
370   PetscFunctionReturn(PETSC_SUCCESS);
371 }
372 
373 /*@
374   PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
375 
376   Not Collective
377 
378   Input Parameter:
379 . viewer - the `PetscViewer`
380 
381   Level: intermediate
382 
383 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
384 @*/
385 PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
386 {
387   PetscViewer_Draw *vdraw;
388   PetscBool         isdraw;
389   PetscInt          i;
390 
391   PetscFunctionBegin;
392   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
393   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
394   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
395   vdraw = (PetscViewer_Draw *)viewer->data;
396 
397   for (i = 0; i < vdraw->draw_max; i++) {
398     if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
399   }
400   PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 /*@
404   PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed)  in the `PETSCVIEWERDRAW` `PetscViewer`
405 
406   Not Collective
407 
408   Input Parameter:
409 . viewer - the `PetscViewer`
410 
411   Output Parameter:
412 . pause - the pause value
413 
414   Level: intermediate
415 
416 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
417 @*/
418 PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
419 {
420   PetscViewer_Draw *vdraw;
421   PetscBool         isdraw;
422   PetscInt          i;
423   PetscDraw         draw;
424 
425   PetscFunctionBegin;
426   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
427   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
428   if (!isdraw) {
429     *pause = 0.0;
430     PetscFunctionReturn(PETSC_SUCCESS);
431   }
432   vdraw = (PetscViewer_Draw *)viewer->data;
433 
434   for (i = 0; i < vdraw->draw_max; i++) {
435     if (vdraw->draw[i]) {
436       PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
437       PetscFunctionReturn(PETSC_SUCCESS);
438     }
439   }
440   /* none exist yet so create one and get its pause */
441   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
442   PetscCall(PetscDrawGetPause(draw, pause));
443   PetscFunctionReturn(PETSC_SUCCESS);
444 }
445 
446 /*@
447   PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
448 
449   Not Collective
450 
451   Input Parameters:
452 + viewer - the `PetscViewer`
453 - pause  - the pause value
454 
455   Level: intermediate
456 
457 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
458 @*/
459 PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
460 {
461   PetscViewer_Draw *vdraw;
462   PetscBool         isdraw;
463   PetscInt          i;
464 
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
467   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
468   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
469   vdraw = (PetscViewer_Draw *)viewer->data;
470 
471   vdraw->pause = pause;
472   for (i = 0; i < vdraw->draw_max; i++) {
473     if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
474   }
475   PetscFunctionReturn(PETSC_SUCCESS);
476 }
477 
478 /*@
479   PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
480 
481   Not Collective
482 
483   Input Parameters:
484 + viewer - the `PetscViewer`
485 - hold   - `PETSC_TRUE` indicates to hold the previous image
486 
487   Level: intermediate
488 
489 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
490 @*/
491 PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
492 {
493   PetscViewer_Draw *vdraw;
494   PetscBool         isdraw;
495 
496   PetscFunctionBegin;
497   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
498   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
499   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
500   vdraw = (PetscViewer_Draw *)viewer->data;
501 
502   vdraw->hold = hold;
503   PetscFunctionReturn(PETSC_SUCCESS);
504 }
505 
506 /*@
507   PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
508 
509   Not Collective
510 
511   Input Parameter:
512 . viewer - the `PetscViewer`
513 
514   Output Parameter:
515 . hold - indicates to hold or not
516 
517   Level: intermediate
518 
519 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
520 @*/
521 PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
522 {
523   PetscViewer_Draw *vdraw;
524   PetscBool         isdraw;
525 
526   PetscFunctionBegin;
527   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
528   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
529   if (!isdraw) {
530     *hold = PETSC_FALSE;
531     PetscFunctionReturn(PETSC_SUCCESS);
532   }
533   vdraw = (PetscViewer_Draw *)viewer->data;
534 
535   *hold = vdraw->hold;
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 /*
540     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
541   is attached to a communicator, in this case the attribute is a PetscViewer.
542 */
543 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
544 
545 /*@C
546    PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
547                      in an MPI communicator.
548 
549    Collective
550 
551    Input Parameter:
552 .  comm - the MPI communicator to share the window `PetscViewer`
553 
554    Level: intermediate
555 
556    Notes:
557    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
558 
559    Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
560    an error code.  The window is usually used in the form
561 .vb
562    XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
563 .ve
564 
565 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
566 @*/
567 PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
568 {
569   PetscMPIInt flag;
570   PetscViewer viewer;
571   MPI_Comm    ncomm;
572 
573   PetscFunctionBegin;
574   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
575   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) { PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL)); }
576   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
577   if (!flag) { /* PetscViewer not yet created */
578     PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
579     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
580     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
581   }
582   PetscCallNull(PetscCommDestroy(&ncomm));
583   PetscFunctionReturn(viewer);
584 }
585 
586 /*@
587   PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
588 
589   Collective
590 
591   Input Parameters:
592 + viewer  - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
593 . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
594 - bounds  - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
595 
596   Options Database Key:
597 . -draw_bounds  minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
598 
599   Level: intermediate
600 
601   Note:
602   this determines the colors used in 2d contour plots generated with VecView() for `DMDA` in 2d. Any values in the vector below or above the
603   bounds are moved to the bound value before plotting. In this way the color index from color to physical value remains the same for all plots generated with
604   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
605 
606 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
607 @*/
608 PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
609 {
610   PetscViewer_Draw *vdraw;
611   PetscBool         isdraw;
612 
613   PetscFunctionBegin;
614   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
615   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
616   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
617   vdraw = (PetscViewer_Draw *)viewer->data;
618 
619   vdraw->nbounds = nbounds;
620   PetscCall(PetscFree(vdraw->bounds));
621   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
622   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
623   PetscFunctionReturn(PETSC_SUCCESS);
624 }
625 
626 /*@C
627   PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
628 
629   Collective
630 
631   Input Parameter:
632 . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
633 
634   Output Parameters:
635 + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
636 - bounds  - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
637 
638   Level: intermediate
639 
640 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
641 @*/
642 PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
643 {
644   PetscViewer_Draw *vdraw;
645   PetscBool         isdraw;
646 
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
649   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
650   if (!isdraw) {
651     if (nbounds) *nbounds = 0;
652     if (bounds) *bounds = NULL;
653     PetscFunctionReturn(PETSC_SUCCESS);
654   }
655   vdraw = (PetscViewer_Draw *)viewer->data;
656 
657   if (nbounds) *nbounds = vdraw->nbounds;
658   if (bounds) *bounds = vdraw->bounds;
659   PetscFunctionReturn(PETSC_SUCCESS);
660 }
661 
662 /*@C
663   PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`
664 
665   Collective
666 
667   Input Parameters:
668 + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
669 . host   - the host to open the window on, 'NULL' indicates the local host
670 . title  - the title at the top of the window
671 . metric - the label above the graph
672 . l      - the number of curves
673 . names  - the names of each curve to be used in displaying the legend. May be 'NULL'
674 . x      - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
675 . y      - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
676 . m      - window width in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
677 - n      - window height in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
678 
679   Level: developer
680 
681 .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
682 @*/
683 PetscErrorCode PetscViewerMonitorLGSetUp(PetscViewer viewer, const char host[], const char title[], const char metric[], PetscInt l, const char *names[], int x, int y, int m, int n) PeNS
684 {
685   PetscDrawAxis axis;
686   PetscDrawLG   lg;
687 
688   PetscFunctionBegin;
689   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
690   PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
691   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
692   if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
693   PetscCall(PetscDrawLGSetFromOptions(lg));
694   PetscCall(PetscDrawLGGetAxis(lg, &axis));
695   PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
696   PetscFunctionReturn(PETSC_SUCCESS);
697 }
698