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