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