xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 6dd63270497ad23dcf16ae500a87ff2b2a0b7474)
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 Notes:
206   Whenever indicating null character data in a Fortran code,
207   `PETSC_NULL_CHARACTER` must be employed; using NULL is not
208   correct for character data!  Thus, `PETSC_NULL_CHARACTER` can be
209   used for the display and title input parameters.
210 
211 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
212           `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
213 @*/
214 PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
215 {
216   PetscFunctionBegin;
217   PetscCall(PetscViewerCreate(comm, viewer));
218   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
219   PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
220   PetscFunctionReturn(PETSC_SUCCESS);
221 }
222 
223 #include <petsc/private/drawimpl.h>
224 
225 static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
226 {
227   PetscMPIInt       rank;
228   PetscInt          i;
229   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
230 
231   PetscFunctionBegin;
232   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
233   /* only processor zero can use the PetscViewer draw singleton */
234   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
235   if (rank == 0) {
236     PetscMPIInt flg;
237     PetscDraw   draw, sdraw;
238 
239     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
240     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
241     PetscCall(PetscViewerCreate(comm, sviewer));
242     PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
243     svdraw             = (PetscViewer_Draw *)(*sviewer)->data;
244     (*sviewer)->format = viewer->format;
245     for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
246       if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
247     }
248     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
249     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
250     if (draw->savefilename) {
251       PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
252       sdraw->savefilecount  = draw->savefilecount;
253       sdraw->savesinglefile = draw->savesinglefile;
254       sdraw->savemoviefps   = draw->savemoviefps;
255       sdraw->saveonclear    = draw->saveonclear;
256       sdraw->saveonflush    = draw->saveonflush;
257     }
258     if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
259   } else {
260     PetscDraw draw;
261     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
262   }
263   vdraw->singleton_made = PETSC_TRUE;
264   PetscFunctionReturn(PETSC_SUCCESS);
265 }
266 
267 static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
268 {
269   PetscMPIInt       rank;
270   PetscInt          i;
271   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
272 
273   PetscFunctionBegin;
274   PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
275   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
276   if (rank == 0) {
277     PetscDraw draw, sdraw;
278 
279     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
280     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
281     if (draw->savefilename) {
282       draw->savefilecount = sdraw->savefilecount;
283       PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
284     }
285     svdraw = (PetscViewer_Draw *)(*sviewer)->data;
286     for (i = 0; i < vdraw->draw_max; i++) {
287       if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
288     }
289     PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
290     PetscCall(PetscFree((*sviewer)->data));
291     PetscCall(PetscHeaderDestroy(sviewer));
292   } else {
293     PetscDraw draw;
294 
295     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
296     if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
297   }
298 
299   vdraw->singleton_made = PETSC_FALSE;
300   PetscFunctionReturn(PETSC_SUCCESS);
301 }
302 
303 static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
304 {
305   PetscReal bounds[16];
306   PetscInt  nbounds = 16;
307   PetscBool flg;
308 
309   PetscFunctionBegin;
310   PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
311   PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
312   if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
313   PetscOptionsHeadEnd();
314   PetscFunctionReturn(PETSC_SUCCESS);
315 }
316 
317 static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
318 {
319   PetscDraw         draw;
320   PetscInt          i;
321   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
322   PetscBool         iascii;
323 
324   PetscFunctionBegin;
325   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
326   if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
327   /*  If the PetscViewer has just been created then no vdraw->draw yet
328       exists so this will not actually call the viewer on any draws. */
329   for (i = 0; i < vdraw->draw_base; i++) {
330     if (vdraw->draw[i]) {
331       PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
332       PetscCall(PetscDrawView(draw, v));
333     }
334   }
335   PetscFunctionReturn(PETSC_SUCCESS);
336 }
337 
338 /*MC
339    PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
340 
341   Level: beginner
342 
343 .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
344           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
345           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
346           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
347 M*/
348 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
349 {
350   PetscViewer_Draw *vdraw;
351 
352   PetscFunctionBegin;
353   PetscCall(PetscNew(&vdraw));
354   viewer->data = (void *)vdraw;
355 
356   viewer->ops->flush            = PetscViewerFlush_Draw;
357   viewer->ops->view             = PetscViewerView_Draw;
358   viewer->ops->destroy          = PetscViewerDestroy_Draw;
359   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
360   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
361   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
362 
363   /* these are created on the fly if requested */
364   vdraw->draw_max  = 5;
365   vdraw->draw_base = 0;
366   vdraw->w         = PETSC_DECIDE;
367   vdraw->h         = PETSC_DECIDE;
368 
369   PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
370   vdraw->singleton_made = PETSC_FALSE;
371   PetscFunctionReturn(PETSC_SUCCESS);
372 }
373 
374 /*@
375   PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
376 
377   Not Collective
378 
379   Input Parameter:
380 . viewer - the `PetscViewer`
381 
382   Level: intermediate
383 
384 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
385 @*/
386 PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
387 {
388   PetscViewer_Draw *vdraw;
389   PetscBool         isdraw;
390   PetscInt          i;
391 
392   PetscFunctionBegin;
393   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
394   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
395   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
396   vdraw = (PetscViewer_Draw *)viewer->data;
397 
398   for (i = 0; i < vdraw->draw_max; i++) {
399     if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
400   }
401   PetscFunctionReturn(PETSC_SUCCESS);
402 }
403 
404 /*@
405   PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed)  in the `PETSCVIEWERDRAW` `PetscViewer`
406 
407   Not Collective
408 
409   Input Parameter:
410 . viewer - the `PetscViewer`
411 
412   Output Parameter:
413 . pause - the pause value
414 
415   Level: intermediate
416 
417 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
418 @*/
419 PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
420 {
421   PetscViewer_Draw *vdraw;
422   PetscBool         isdraw;
423   PetscInt          i;
424   PetscDraw         draw;
425 
426   PetscFunctionBegin;
427   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
428   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
429   if (!isdraw) {
430     *pause = 0.0;
431     PetscFunctionReturn(PETSC_SUCCESS);
432   }
433   vdraw = (PetscViewer_Draw *)viewer->data;
434 
435   for (i = 0; i < vdraw->draw_max; i++) {
436     if (vdraw->draw[i]) {
437       PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
438       PetscFunctionReturn(PETSC_SUCCESS);
439     }
440   }
441   /* none exist yet so create one and get its pause */
442   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
443   PetscCall(PetscDrawGetPause(draw, pause));
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
449 
450   Not Collective
451 
452   Input Parameters:
453 + viewer - the `PetscViewer`
454 - pause  - the pause value
455 
456   Level: intermediate
457 
458 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
459 @*/
460 PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
461 {
462   PetscViewer_Draw *vdraw;
463   PetscBool         isdraw;
464   PetscInt          i;
465 
466   PetscFunctionBegin;
467   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
468   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
469   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
470   vdraw = (PetscViewer_Draw *)viewer->data;
471 
472   vdraw->pause = pause;
473   for (i = 0; i < vdraw->draw_max; i++) {
474     if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
475   }
476   PetscFunctionReturn(PETSC_SUCCESS);
477 }
478 
479 /*@
480   PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
481 
482   Not Collective
483 
484   Input Parameters:
485 + viewer - the `PetscViewer`
486 - hold   - `PETSC_TRUE` indicates to hold the previous image
487 
488   Level: intermediate
489 
490 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
491 @*/
492 PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
493 {
494   PetscViewer_Draw *vdraw;
495   PetscBool         isdraw;
496 
497   PetscFunctionBegin;
498   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
499   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
500   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
501   vdraw = (PetscViewer_Draw *)viewer->data;
502 
503   vdraw->hold = hold;
504   PetscFunctionReturn(PETSC_SUCCESS);
505 }
506 
507 /*@
508   PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
509 
510   Not Collective
511 
512   Input Parameter:
513 . viewer - the `PetscViewer`
514 
515   Output Parameter:
516 . hold - indicates to hold or not
517 
518   Level: intermediate
519 
520 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
521 @*/
522 PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
523 {
524   PetscViewer_Draw *vdraw;
525   PetscBool         isdraw;
526 
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
529   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
530   if (!isdraw) {
531     *hold = PETSC_FALSE;
532     PetscFunctionReturn(PETSC_SUCCESS);
533   }
534   vdraw = (PetscViewer_Draw *)viewer->data;
535 
536   *hold = vdraw->hold;
537   PetscFunctionReturn(PETSC_SUCCESS);
538 }
539 
540 /*
541     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
542   is attached to a communicator, in this case the attribute is a PetscViewer.
543 */
544 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
545 
546 /*@C
547    PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
548                      in an MPI communicator.
549 
550    Collective
551 
552    Input Parameter:
553 .  comm - the MPI communicator to share the window `PetscViewer`
554 
555    Level: intermediate
556 
557    Notes:
558    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
559 
560    Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
561    an error code.  The window is usually used in the form
562 .vb
563    XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
564 .ve
565 
566 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
567 @*/
568 PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
569 {
570   PetscMPIInt flag;
571   PetscViewer viewer;
572   MPI_Comm    ncomm;
573 
574   PetscFunctionBegin;
575   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
576   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)); }
577   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
578   if (!flag) { /* PetscViewer not yet created */
579     PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
580     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
581     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
582   }
583   PetscCallNull(PetscCommDestroy(&ncomm));
584   PetscFunctionReturn(viewer);
585 }
586 
587 /*@
588   PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
589 
590   Collective
591 
592   Input Parameters:
593 + viewer  - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
594 . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
595 - 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, .....
596 
597   Options Database Key:
598 . -draw_bounds  minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
599 
600   Level: intermediate
601 
602   Note:
603   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
604   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
605   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
606 
607 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
608 @*/
609 PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
610 {
611   PetscViewer_Draw *vdraw;
612   PetscBool         isdraw;
613 
614   PetscFunctionBegin;
615   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
616   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
617   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
618   vdraw = (PetscViewer_Draw *)viewer->data;
619 
620   vdraw->nbounds = nbounds;
621   PetscCall(PetscFree(vdraw->bounds));
622   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
623   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
624   PetscFunctionReturn(PETSC_SUCCESS);
625 }
626 
627 /*@C
628   PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
629 
630   Collective
631 
632   Input Parameter:
633 . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
634 
635   Output Parameters:
636 + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
637 - 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, .....
638 
639   Level: intermediate
640 
641 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
642 @*/
643 PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
644 {
645   PetscViewer_Draw *vdraw;
646   PetscBool         isdraw;
647 
648   PetscFunctionBegin;
649   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
650   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
651   if (!isdraw) {
652     if (nbounds) *nbounds = 0;
653     if (bounds) *bounds = NULL;
654     PetscFunctionReturn(PETSC_SUCCESS);
655   }
656   vdraw = (PetscViewer_Draw *)viewer->data;
657 
658   if (nbounds) *nbounds = vdraw->nbounds;
659   if (bounds) *bounds = vdraw->bounds;
660   PetscFunctionReturn(PETSC_SUCCESS);
661 }
662 
663 /*@C
664   PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`
665 
666   Collective
667 
668   Input Parameters:
669 + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
670 . host   - the host to open the window on, 'NULL' indicates the local host
671 . title  - the title at the top of the window
672 . metric - the label above the graph
673 . l      - the number of curves
674 . names  - the names of each curve to be used in displaying the legend. May be 'NULL'
675 . x      - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
676 . y      - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
677 . 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`
678 - 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`
679 
680   Level: developer
681 
682 .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
683 @*/
684 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
685 {
686   PetscDrawAxis axis;
687   PetscDrawLG   lg;
688 
689   PetscFunctionBegin;
690   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
691   PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
692   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
693   if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
694   PetscCall(PetscDrawLGSetFromOptions(lg));
695   PetscCall(PetscDrawLGGetAxis(lg, &axis));
696   PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
697   PetscFunctionReturn(PETSC_SUCCESS);
698 }
699