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 + viewer - 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 - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE` 361 . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE` 362 . w - window width in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE` 363 - h - window height in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE` 364 365 Output Parameter: 366 . viewer - the `PetscViewer` 367 368 Format Options: 369 + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format 370 - `PETSC_VIEWER_DRAW_LG` - displays using a line graph 371 372 Options Database Keys: 373 + -draw_type - use x or null 374 . -nox - Disables all x-windows output 375 . -display <name> - Specifies name of machine for the X display 376 . -geometry <x,y,w,h> - allows setting the window location and size 377 - -draw_pause <pause> - Sets time (in seconds) that the 378 program pauses after PetscDrawPause() has been called 379 (0 is default, -1 implies until user input). 380 381 Level: beginner 382 383 Fortran Note: 384 Whenever indicating null character data in a Fortran code, 385 `PETSC_NULL_CHARACTER` must be employed; using NULL is not 386 correct for character data! Thus, `PETSC_NULL_CHARACTER` can be 387 used for the display and title input parameters. 388 389 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`, 390 `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF` 391 @*/ 392 PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer) 393 { 394 PetscFunctionBegin; 395 PetscCall(PetscViewerCreate(comm, viewer)); 396 PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW)); 397 PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h)); 398 PetscFunctionReturn(PETSC_SUCCESS); 399 } 400 401 #include <petsc/private/drawimpl.h> 402 403 PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) 404 { 405 PetscMPIInt rank; 406 PetscInt i; 407 PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw; 408 409 PetscFunctionBegin; 410 PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous"); 411 /* only processor zero can use the PetscViewer draw singleton */ 412 if (sviewer) *sviewer = NULL; 413 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 414 if (rank == 0) { 415 PetscMPIInt flg; 416 PetscDraw draw, sdraw; 417 418 PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg)); 419 PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm"); 420 PetscCall(PetscViewerCreate(comm, sviewer)); 421 PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW)); 422 svdraw = (PetscViewer_Draw *)(*sviewer)->data; 423 (*sviewer)->format = viewer->format; 424 for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */ 425 if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i])); 426 } 427 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 428 PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw)); 429 if (draw->savefilename) { 430 PetscCall(PetscDrawSetSave(sdraw, draw->savefilename)); 431 sdraw->savefilecount = draw->savefilecount; 432 sdraw->savesinglefile = draw->savesinglefile; 433 sdraw->savemoviefps = draw->savemoviefps; 434 sdraw->saveonclear = draw->saveonclear; 435 sdraw->saveonflush = draw->saveonflush; 436 } 437 if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename)); 438 } else { 439 PetscDraw draw; 440 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 441 } 442 vdraw->singleton_made = PETSC_TRUE; 443 PetscFunctionReturn(PETSC_SUCCESS); 444 } 445 446 PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) 447 { 448 PetscMPIInt rank; 449 PetscInt i; 450 PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw; 451 452 PetscFunctionBegin; 453 PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten"); 454 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 455 if (rank == 0) { 456 PetscDraw draw, sdraw; 457 458 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 459 PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw)); 460 if (draw->savefilename) { 461 draw->savefilecount = sdraw->savefilecount; 462 PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw))); 463 } 464 svdraw = (PetscViewer_Draw *)(*sviewer)->data; 465 for (i = 0; i < vdraw->draw_max; i++) { 466 if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i])); 467 } 468 PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis)); 469 PetscCall(PetscFree((*sviewer)->data)); 470 PetscCall(PetscHeaderDestroy(sviewer)); 471 } else { 472 PetscDraw draw; 473 474 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 475 if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw))); 476 } 477 478 vdraw->singleton_made = PETSC_FALSE; 479 PetscFunctionReturn(PETSC_SUCCESS); 480 } 481 482 PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems *PetscOptionsObject) 483 { 484 PetscReal bounds[16]; 485 PetscInt nbounds = 16; 486 PetscBool flg; 487 488 PetscFunctionBegin; 489 PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options"); 490 PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg)); 491 if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds)); 492 PetscOptionsHeadEnd(); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v) 497 { 498 PetscDraw draw; 499 PetscInt i; 500 PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data; 501 PetscBool iascii; 502 503 PetscFunctionBegin; 504 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 505 if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype)); 506 /* If the PetscViewer has just been created then no vdraw->draw yet 507 exists so this will not actually call the viewer on any draws. */ 508 for (i = 0; i < vdraw->draw_base; i++) { 509 if (vdraw->draw[i]) { 510 PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw)); 511 PetscCall(PetscDrawView(draw, v)); 512 } 513 } 514 PetscFunctionReturn(PETSC_SUCCESS); 515 } 516 517 /*MC 518 PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file 519 520 Level: beginner 521 522 .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`, 523 `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, 524 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, 525 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 526 M*/ 527 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer) 528 { 529 PetscViewer_Draw *vdraw; 530 531 PetscFunctionBegin; 532 PetscCall(PetscNew(&vdraw)); 533 viewer->data = (void *)vdraw; 534 535 viewer->ops->flush = PetscViewerFlush_Draw; 536 viewer->ops->view = PetscViewerView_Draw; 537 viewer->ops->destroy = PetscViewerDestroy_Draw; 538 viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw; 539 viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw; 540 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw; 541 542 /* these are created on the fly if requested */ 543 vdraw->draw_max = 5; 544 vdraw->draw_base = 0; 545 vdraw->w = PETSC_DECIDE; 546 vdraw->h = PETSC_DECIDE; 547 548 PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis)); 549 vdraw->singleton_made = PETSC_FALSE; 550 PetscFunctionReturn(PETSC_SUCCESS); 551 } 552 553 /*@ 554 PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`. 555 556 Not Collective 557 558 Input Parameter: 559 . viewer - the `PetscViewer` 560 561 Level: intermediate 562 563 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 564 @*/ 565 PetscErrorCode PetscViewerDrawClear(PetscViewer viewer) 566 { 567 PetscViewer_Draw *vdraw; 568 PetscBool isdraw; 569 PetscInt i; 570 571 PetscFunctionBegin; 572 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 573 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 574 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 575 vdraw = (PetscViewer_Draw *)viewer->data; 576 577 for (i = 0; i < vdraw->draw_max; i++) { 578 if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i])); 579 } 580 PetscFunctionReturn(PETSC_SUCCESS); 581 } 582 583 /*@ 584 PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer` 585 586 Not Collective 587 588 Input Parameter: 589 . viewer - the `PetscViewer` 590 591 Output Parameter: 592 . pause - the pause value 593 594 Level: intermediate 595 596 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 597 @*/ 598 PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause) 599 { 600 PetscViewer_Draw *vdraw; 601 PetscBool isdraw; 602 PetscInt i; 603 PetscDraw draw; 604 605 PetscFunctionBegin; 606 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 607 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 608 if (!isdraw) { 609 *pause = 0.0; 610 PetscFunctionReturn(PETSC_SUCCESS); 611 } 612 vdraw = (PetscViewer_Draw *)viewer->data; 613 614 for (i = 0; i < vdraw->draw_max; i++) { 615 if (vdraw->draw[i]) { 616 PetscCall(PetscDrawGetPause(vdraw->draw[i], pause)); 617 PetscFunctionReturn(PETSC_SUCCESS); 618 } 619 } 620 /* none exist yet so create one and get its pause */ 621 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 622 PetscCall(PetscDrawGetPause(draw, pause)); 623 PetscFunctionReturn(PETSC_SUCCESS); 624 } 625 626 /*@ 627 PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer` 628 629 Not Collective 630 631 Input Parameters: 632 + viewer - the `PetscViewer` 633 - pause - the pause value 634 635 Level: intermediate 636 637 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 638 @*/ 639 PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause) 640 { 641 PetscViewer_Draw *vdraw; 642 PetscBool isdraw; 643 PetscInt i; 644 645 PetscFunctionBegin; 646 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 647 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 648 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 649 vdraw = (PetscViewer_Draw *)viewer->data; 650 651 vdraw->pause = pause; 652 for (i = 0; i < vdraw->draw_max; i++) { 653 if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause)); 654 } 655 PetscFunctionReturn(PETSC_SUCCESS); 656 } 657 658 /*@ 659 PetscViewerDrawSetHold - Holds previous image when drawing new image 660 661 Not Collective 662 663 Input Parameters: 664 + viewer - the `PetscViewer` 665 - hold - `PETSC_TRUE` indicates to hold the previous image 666 667 Level: intermediate 668 669 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 670 @*/ 671 PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold) 672 { 673 PetscViewer_Draw *vdraw; 674 PetscBool isdraw; 675 676 PetscFunctionBegin; 677 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 678 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 679 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 680 vdraw = (PetscViewer_Draw *)viewer->data; 681 682 vdraw->hold = hold; 683 PetscFunctionReturn(PETSC_SUCCESS); 684 } 685 686 /*@ 687 PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image 688 689 Not Collective 690 691 Input Parameter: 692 . viewer - the `PetscViewer` 693 694 Output Parameter: 695 . hold - indicates to hold or not 696 697 Level: intermediate 698 699 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, 700 @*/ 701 PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold) 702 { 703 PetscViewer_Draw *vdraw; 704 PetscBool isdraw; 705 706 PetscFunctionBegin; 707 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 708 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 709 if (!isdraw) { 710 *hold = PETSC_FALSE; 711 PetscFunctionReturn(PETSC_SUCCESS); 712 } 713 vdraw = (PetscViewer_Draw *)viewer->data; 714 715 *hold = vdraw->hold; 716 PetscFunctionReturn(PETSC_SUCCESS); 717 } 718 719 /* 720 The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that 721 is attached to a communicator, in this case the attribute is a PetscViewer. 722 */ 723 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID; 724 725 /*@C 726 PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors 727 in a communicator. 728 729 Collective 730 731 Input Parameter: 732 . comm - the MPI communicator to share the window `PetscViewer` 733 734 Level: intermediate 735 736 Note: 737 Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return 738 an error code. The window is usually used in the form 739 $ XXXView(XXX object,PETSC_VIEWER_DRAW_(comm)); 740 741 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`, 742 @*/ 743 PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm) 744 { 745 PetscErrorCode ierr; 746 PetscMPIInt flag, mpi_ierr; 747 PetscViewer viewer; 748 MPI_Comm ncomm; 749 750 PetscFunctionBegin; 751 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 752 if (ierr) { 753 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 754 PetscFunctionReturn(NULL); 755 } 756 if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) { 757 mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL); 758 if (mpi_ierr) { 759 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 760 PetscFunctionReturn(NULL); 761 } 762 } 763 mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag); 764 if (mpi_ierr) { 765 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 766 PetscFunctionReturn(NULL); 767 } 768 if (!flag) { /* PetscViewer not yet created */ 769 ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer); 770 if (ierr) { 771 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 772 PetscFunctionReturn(NULL); 773 } 774 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 775 if (ierr) { 776 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 777 PetscFunctionReturn(NULL); 778 } 779 mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer); 780 if (mpi_ierr) { 781 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 782 PetscFunctionReturn(NULL); 783 } 784 } 785 ierr = PetscCommDestroy(&ncomm); 786 if (ierr) { 787 ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 788 PetscFunctionReturn(NULL); 789 } 790 PetscFunctionReturn(viewer); 791 } 792 793 /*@ 794 PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting 795 796 Collective 797 798 Input Parameters: 799 + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`) 800 . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()` 801 - 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, ..... 802 803 Options Database Key: 804 . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds 805 806 Level: intermediate 807 808 Note: 809 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 810 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 811 this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set. 812 813 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()` 814 @*/ 815 PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds) 816 { 817 PetscViewer_Draw *vdraw; 818 PetscBool isdraw; 819 820 PetscFunctionBegin; 821 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 822 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 823 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 824 vdraw = (PetscViewer_Draw *)viewer->data; 825 826 vdraw->nbounds = nbounds; 827 PetscCall(PetscFree(vdraw->bounds)); 828 PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds)); 829 PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds)); 830 PetscFunctionReturn(PETSC_SUCCESS); 831 } 832 833 /*@C 834 PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()` 835 836 Collective 837 838 Input Parameter: 839 . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 840 841 Output Parameters: 842 + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()` 843 - 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, ..... 844 845 Level: intermediate 846 847 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()` 848 @*/ 849 PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds) 850 { 851 PetscViewer_Draw *vdraw; 852 PetscBool isdraw; 853 854 PetscFunctionBegin; 855 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 856 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 857 if (!isdraw) { 858 if (nbounds) *nbounds = 0; 859 if (bounds) *bounds = NULL; 860 PetscFunctionReturn(PETSC_SUCCESS); 861 } 862 vdraw = (PetscViewer_Draw *)viewer->data; 863 864 if (nbounds) *nbounds = vdraw->nbounds; 865 if (bounds) *bounds = vdraw->bounds; 866 PetscFunctionReturn(PETSC_SUCCESS); 867 } 868