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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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 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: [](sec_viewers), `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(PETSC_SUCCESS); 102 } 103 104 /*@C 105 PetscViewerDrawBaseAdd - add to the base integer that is added to the windownumber passed to `PetscViewerDrawGetDraw()` 106 107 Logically Collective 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: [](sec_viewers), `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(PETSC_SUCCESS); 135 } 136 137 /*@C 138 PetscViewerDrawBaseSet - sets the base integer that is added to the windownumber passed to `PetscViewerDrawGetDraw()` 139 140 Logically Collective 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: [](sec_viewers), `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(PETSC_SUCCESS); 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 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: [](sec_viewers), `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(PETSC_SUCCESS); 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 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: [](sec_viewers), `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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 262 vdraw = (PetscViewer_Draw *)v->data; 263 264 if (w >= 1) vdraw->w = w; 265 if (h >= 1) vdraw->h = h; 266 PetscFunctionReturn(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 296 vdraw = (PetscViewer_Draw *)v->data; 297 298 PetscCall(PetscFree(vdraw->drawtype)); 299 PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype)); 300 PetscFunctionReturn(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 327 vdraw = (PetscViewer_Draw *)v->data; 328 329 PetscCall(PetscFree(vdraw->title)); 330 PetscCall(PetscStrallocpy(title, &vdraw->title)); 331 PetscFunctionReturn(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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 Fortran Note: 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: [](sec_viewers), `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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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 PetscBool iascii; 501 502 PetscFunctionBegin; 503 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 504 if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype)); 505 /* If the PetscViewer has just been created then no vdraw->draw yet 506 exists so this will not actually call the viewer on any draws. */ 507 for (i = 0; i < vdraw->draw_base; i++) { 508 if (vdraw->draw[i]) { 509 PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw)); 510 PetscCall(PetscDrawView(draw, v)); 511 } 512 } 513 PetscFunctionReturn(PETSC_SUCCESS); 514 } 515 516 /*MC 517 PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file 518 519 Level: beginner 520 521 .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`, 522 `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, 523 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, 524 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 525 M*/ 526 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer) 527 { 528 PetscViewer_Draw *vdraw; 529 530 PetscFunctionBegin; 531 PetscCall(PetscNew(&vdraw)); 532 viewer->data = (void *)vdraw; 533 534 viewer->ops->flush = PetscViewerFlush_Draw; 535 viewer->ops->view = PetscViewerView_Draw; 536 viewer->ops->destroy = PetscViewerDestroy_Draw; 537 viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw; 538 viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw; 539 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw; 540 541 /* these are created on the fly if requested */ 542 vdraw->draw_max = 5; 543 vdraw->draw_base = 0; 544 vdraw->w = PETSC_DECIDE; 545 vdraw->h = PETSC_DECIDE; 546 547 PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis)); 548 vdraw->singleton_made = PETSC_FALSE; 549 PetscFunctionReturn(PETSC_SUCCESS); 550 } 551 552 /*@ 553 PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`. 554 555 Not Collective 556 557 Input Parameter: 558 . viewer - the `PetscViewer` 559 560 Level: intermediate 561 562 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 563 @*/ 564 PetscErrorCode PetscViewerDrawClear(PetscViewer viewer) 565 { 566 PetscViewer_Draw *vdraw; 567 PetscBool isdraw; 568 PetscInt i; 569 570 PetscFunctionBegin; 571 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 572 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 573 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 574 vdraw = (PetscViewer_Draw *)viewer->data; 575 576 for (i = 0; i < vdraw->draw_max; i++) { 577 if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i])); 578 } 579 PetscFunctionReturn(PETSC_SUCCESS); 580 } 581 582 /*@ 583 PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer` 584 585 Not Collective 586 587 Input Parameter: 588 . viewer - the `PetscViewer` 589 590 Output Parameter: 591 . pause - the pause value 592 593 Level: intermediate 594 595 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 596 @*/ 597 PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause) 598 { 599 PetscViewer_Draw *vdraw; 600 PetscBool isdraw; 601 PetscInt i; 602 PetscDraw draw; 603 604 PetscFunctionBegin; 605 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 606 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 607 if (!isdraw) { 608 *pause = 0.0; 609 PetscFunctionReturn(PETSC_SUCCESS); 610 } 611 vdraw = (PetscViewer_Draw *)viewer->data; 612 613 for (i = 0; i < vdraw->draw_max; i++) { 614 if (vdraw->draw[i]) { 615 PetscCall(PetscDrawGetPause(vdraw->draw[i], pause)); 616 PetscFunctionReturn(PETSC_SUCCESS); 617 } 618 } 619 /* none exist yet so create one and get its pause */ 620 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 621 PetscCall(PetscDrawGetPause(draw, pause)); 622 PetscFunctionReturn(PETSC_SUCCESS); 623 } 624 625 /*@ 626 PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer` 627 628 Not Collective 629 630 Input Parameters: 631 + viewer - the `PetscViewer` 632 - pause - the pause value 633 634 Level: intermediate 635 636 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 637 @*/ 638 PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause) 639 { 640 PetscViewer_Draw *vdraw; 641 PetscBool isdraw; 642 PetscInt i; 643 644 PetscFunctionBegin; 645 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 646 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 647 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 648 vdraw = (PetscViewer_Draw *)viewer->data; 649 650 vdraw->pause = pause; 651 for (i = 0; i < vdraw->draw_max; i++) { 652 if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause)); 653 } 654 PetscFunctionReturn(PETSC_SUCCESS); 655 } 656 657 /*@ 658 PetscViewerDrawSetHold - Holds previous image when drawing new image 659 660 Not Collective 661 662 Input Parameters: 663 + viewer - the `PetscViewer` 664 - hold - `PETSC_TRUE` indicates to hold the previous image 665 666 Level: intermediate 667 668 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 669 @*/ 670 PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold) 671 { 672 PetscViewer_Draw *vdraw; 673 PetscBool isdraw; 674 675 PetscFunctionBegin; 676 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 677 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 678 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 679 vdraw = (PetscViewer_Draw *)viewer->data; 680 681 vdraw->hold = hold; 682 PetscFunctionReturn(PETSC_SUCCESS); 683 } 684 685 /*@ 686 PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image 687 688 Not Collective 689 690 Input Parameter: 691 . viewer - the `PetscViewer` 692 693 Output Parameter: 694 . hold - indicates to hold or not 695 696 Level: intermediate 697 698 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 699 @*/ 700 PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold) 701 { 702 PetscViewer_Draw *vdraw; 703 PetscBool isdraw; 704 705 PetscFunctionBegin; 706 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 707 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 708 if (!isdraw) { 709 *hold = PETSC_FALSE; 710 PetscFunctionReturn(PETSC_SUCCESS); 711 } 712 vdraw = (PetscViewer_Draw *)viewer->data; 713 714 *hold = vdraw->hold; 715 PetscFunctionReturn(PETSC_SUCCESS); 716 } 717 718 /* 719 The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that 720 is attached to a communicator, in this case the attribute is a PetscViewer. 721 */ 722 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID; 723 724 /*@C 725 PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors 726 in a communicator. 727 728 Collective 729 730 Input Parameter: 731 . comm - the MPI communicator to share the window `PetscViewer` 732 733 Level: intermediate 734 735 Note: 736 Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return 737 an error code. The window is usually used in the form 738 $ XXXView(XXX object,PETSC_VIEWER_DRAW_(comm)); 739 740 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`, 741 @*/ 742 PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm) 743 { 744 PetscErrorCode ierr; 745 PetscMPIInt flag, mpi_ierr; 746 PetscViewer viewer; 747 MPI_Comm ncomm; 748 749 PetscFunctionBegin; 750 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 751 if (ierr) { 752 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 753 PetscFunctionReturn(NULL); 754 } 755 if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) { 756 mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL); 757 if (mpi_ierr) { 758 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 759 PetscFunctionReturn(NULL); 760 } 761 } 762 mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag); 763 if (mpi_ierr) { 764 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 765 PetscFunctionReturn(NULL); 766 } 767 if (!flag) { /* PetscViewer not yet created */ 768 ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer); 769 if (ierr) { 770 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 771 PetscFunctionReturn(NULL); 772 } 773 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 774 if (ierr) { 775 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 776 PetscFunctionReturn(NULL); 777 } 778 mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer); 779 if (mpi_ierr) { 780 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 781 PetscFunctionReturn(NULL); 782 } 783 } 784 ierr = PetscCommDestroy(&ncomm); 785 if (ierr) { 786 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 787 PetscFunctionReturn(NULL); 788 } 789 PetscFunctionReturn(viewer); 790 } 791 792 /*@ 793 PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting 794 795 Collective 796 797 Input Parameters: 798 + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`) 799 . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()` 800 - 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, ..... 801 802 Options Database Key: 803 . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds 804 805 Level: intermediate 806 807 Note: 808 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 809 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 810 this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set. 811 812 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()` 813 @*/ 814 PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds) 815 { 816 PetscViewer_Draw *vdraw; 817 PetscBool isdraw; 818 819 PetscFunctionBegin; 820 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 821 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 822 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 823 vdraw = (PetscViewer_Draw *)viewer->data; 824 825 vdraw->nbounds = nbounds; 826 PetscCall(PetscFree(vdraw->bounds)); 827 PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds)); 828 PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds)); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 832 /*@C 833 PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()` 834 835 Collective 836 837 Input Parameter: 838 . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 839 840 Output Parameters: 841 + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()` 842 - 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, ..... 843 844 Level: intermediate 845 846 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()` 847 @*/ 848 PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds) 849 { 850 PetscViewer_Draw *vdraw; 851 PetscBool isdraw; 852 853 PetscFunctionBegin; 854 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 855 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 856 if (!isdraw) { 857 if (nbounds) *nbounds = 0; 858 if (bounds) *bounds = NULL; 859 PetscFunctionReturn(PETSC_SUCCESS); 860 } 861 vdraw = (PetscViewer_Draw *)viewer->data; 862 863 if (nbounds) *nbounds = vdraw->nbounds; 864 if (bounds) *bounds = vdraw->bounds; 865 PetscFunctionReturn(PETSC_SUCCESS); 866 } 867