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