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 `PETSCVIEWERDRAW` `PetscViewer` object. 40 This `PetscDraw` object may then be used to perform graphics using `PetscDraw` commands. 41 42 Collective 43 44 Input Parameters: 45 + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()` of type `PETSCVIEWERDRAW`) 46 - windownumber - indicates which subwindow (usually 0) to obtain 47 48 Output Parameter: 49 . draw - the draw object 50 51 Level: intermediate 52 53 .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()` 54 @*/ 55 PetscErrorCode PetscViewerDrawGetDraw(PetscViewer viewer, PetscInt windownumber, PetscDraw *draw) 56 { 57 PetscViewer_Draw *vdraw; 58 PetscBool isdraw; 59 60 PetscFunctionBegin; 61 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 62 PetscValidLogicalCollectiveInt(viewer, windownumber, 2); 63 if (draw) PetscValidPointer(draw, 3); 64 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 65 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 66 PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative"); 67 vdraw = (PetscViewer_Draw *)viewer->data; 68 69 windownumber += vdraw->draw_base; 70 if (windownumber >= vdraw->draw_max) { 71 /* allocate twice as many slots as needed */ 72 PetscInt draw_max = vdraw->draw_max; 73 PetscDraw *tdraw = vdraw->draw; 74 PetscDrawLG *drawlg = vdraw->drawlg; 75 PetscDrawAxis *drawaxis = vdraw->drawaxis; 76 77 vdraw->draw_max = 2 * windownumber; 78 79 PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis)); 80 PetscCall(PetscArraycpy(vdraw->draw, tdraw, draw_max)); 81 PetscCall(PetscArraycpy(vdraw->drawlg, drawlg, draw_max)); 82 PetscCall(PetscArraycpy(vdraw->drawaxis, drawaxis, draw_max)); 83 PetscCall(PetscFree3(tdraw, drawlg, drawaxis)); 84 } 85 86 if (!vdraw->draw[windownumber]) { 87 char *title = vdraw->title, tmp_str[128]; 88 if (windownumber) { 89 PetscCall(PetscSNPrintf(tmp_str, sizeof(tmp_str), "%s:%" PetscInt_FMT, vdraw->title ? vdraw->title : "", windownumber)); 90 title = tmp_str; 91 } 92 PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)viewer), vdraw->display, title, PETSC_DECIDE, PETSC_DECIDE, vdraw->w, vdraw->h, &vdraw->draw[windownumber])); 93 if (vdraw->drawtype) PetscCall(PetscDrawSetType(vdraw->draw[windownumber], vdraw->drawtype)); 94 PetscCall(PetscDrawSetPause(vdraw->draw[windownumber], vdraw->pause)); 95 PetscCall(PetscDrawSetOptionsPrefix(vdraw->draw[windownumber], ((PetscObject)viewer)->prefix)); 96 PetscCall(PetscDrawSetFromOptions(vdraw->draw[windownumber])); 97 } 98 if (draw) *draw = vdraw->draw[windownumber]; 99 if (draw) PetscValidHeaderSpecific(*draw, PETSC_DRAW_CLASSID, 3); 100 PetscFunctionReturn(PETSC_SUCCESS); 101 } 102 103 /*@C 104 PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()` 105 106 Logically Collective 107 108 Input Parameters: 109 + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 110 - windownumber - how much to add to the base 111 112 Level: developer 113 114 Note: 115 A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()` 116 117 .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()` 118 @*/ 119 PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber) 120 { 121 PetscViewer_Draw *vdraw; 122 PetscBool isdraw; 123 124 PetscFunctionBegin; 125 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 126 PetscValidLogicalCollectiveInt(viewer, windownumber, 2); 127 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 128 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 129 vdraw = (PetscViewer_Draw *)viewer->data; 130 131 PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base); 132 vdraw->draw_base += windownumber; 133 PetscFunctionReturn(PETSC_SUCCESS); 134 } 135 136 /*@C 137 PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()` 138 139 Logically Collective 140 141 Input Parameters: 142 + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 143 - windownumber - value to set the base 144 145 Level: developer 146 147 Note: 148 A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()` 149 150 .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()` 151 @*/ 152 PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber) 153 { 154 PetscViewer_Draw *vdraw; 155 PetscBool isdraw; 156 157 PetscFunctionBegin; 158 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 159 PetscValidLogicalCollectiveInt(viewer, windownumber, 2); 160 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 161 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 162 vdraw = (PetscViewer_Draw *)viewer->data; 163 164 PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber); 165 vdraw->draw_base = windownumber; 166 PetscFunctionReturn(PETSC_SUCCESS); 167 } 168 169 /*@C 170 PetscViewerDrawGetDrawLG - Returns a `PetscDrawLG` object from `PetscViewer` object of type `PETSCVIEWERDRAW`. 171 This `PetscDrawLG` object may then be used to perform graphics using `PetscDrawLG` commands. 172 173 Collective 174 175 Input Parameters: 176 + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 177 - windownumber - indicates which subwindow (usually 0) 178 179 Output Parameter: 180 . draw - the draw line graph object 181 182 Level: intermediate 183 184 Note: 185 A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows 186 187 .seealso: [](sec_viewers), `PetscDrawLG`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()` 188 @*/ 189 PetscErrorCode PetscViewerDrawGetDrawLG(PetscViewer viewer, PetscInt windownumber, PetscDrawLG *drawlg) 190 { 191 PetscBool isdraw; 192 PetscViewer_Draw *vdraw; 193 194 PetscFunctionBegin; 195 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 196 PetscValidLogicalCollectiveInt(viewer, windownumber, 2); 197 PetscValidPointer(drawlg, 3); 198 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 199 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 200 PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative"); 201 vdraw = (PetscViewer_Draw *)viewer->data; 202 203 if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL)); 204 if (!vdraw->drawlg[windownumber + vdraw->draw_base]) { 205 PetscCall(PetscDrawLGCreate(vdraw->draw[windownumber + vdraw->draw_base], 1, &vdraw->drawlg[windownumber + vdraw->draw_base])); 206 PetscCall(PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber + vdraw->draw_base])); 207 } 208 *drawlg = vdraw->drawlg[windownumber + vdraw->draw_base]; 209 PetscFunctionReturn(PETSC_SUCCESS); 210 } 211 212 /*@C 213 PetscViewerDrawGetDrawAxis - Returns a `PetscDrawAxis` object from a `PetscViewer` object of type `PETSCVIEWERDRAW`. 214 This `PetscDrawAxis` object may then be used to perform graphics using `PetscDrawAxis` commands. 215 216 Collective 217 218 Input Parameters: 219 + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`) 220 - windownumber - indicates which subwindow (usually 0) 221 222 Output Parameter: 223 . drawaxis - the draw axis object 224 225 Level: advanced 226 227 Note: 228 A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows 229 230 .seealso: [](sec_viewers), `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetLG()`, `PetscViewerDrawOpen()` 231 @*/ 232 PetscErrorCode PetscViewerDrawGetDrawAxis(PetscViewer viewer, PetscInt windownumber, PetscDrawAxis *drawaxis) 233 { 234 PetscBool isdraw; 235 PetscViewer_Draw *vdraw; 236 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 239 PetscValidLogicalCollectiveInt(viewer, windownumber, 2); 240 PetscValidPointer(drawaxis, 3); 241 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 242 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 243 PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative"); 244 vdraw = (PetscViewer_Draw *)viewer->data; 245 246 if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL)); 247 if (!vdraw->drawaxis[windownumber + vdraw->draw_base]) PetscCall(PetscDrawAxisCreate(vdraw->draw[windownumber + vdraw->draw_base], &vdraw->drawaxis[windownumber + vdraw->draw_base])); 248 *drawaxis = vdraw->drawaxis[windownumber + vdraw->draw_base]; 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h) 253 { 254 PetscViewer_Draw *vdraw; 255 PetscBool isdraw; 256 257 PetscFunctionBegin; 258 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 259 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 260 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 261 vdraw = (PetscViewer_Draw *)v->data; 262 263 if (w >= 1) vdraw->w = w; 264 if (h >= 1) vdraw->h = h; 265 PetscFunctionReturn(PETSC_SUCCESS); 266 } 267 268 PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h) 269 { 270 PetscViewer_Draw *vdraw; 271 PetscBool isdraw; 272 273 PetscFunctionBegin; 274 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 275 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 276 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 277 vdraw = (PetscViewer_Draw *)v->data; 278 279 PetscCall(PetscStrallocpy(display, &vdraw->display)); 280 PetscCall(PetscStrallocpy(title, &vdraw->title)); 281 if (w >= 1) vdraw->w = w; 282 if (h >= 1) vdraw->h = h; 283 PetscFunctionReturn(PETSC_SUCCESS); 284 } 285 286 PetscErrorCode PetscViewerDrawSetDrawType(PetscViewer v, PetscDrawType drawtype) 287 { 288 PetscViewer_Draw *vdraw; 289 PetscBool isdraw; 290 291 PetscFunctionBegin; 292 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 293 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 294 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 295 vdraw = (PetscViewer_Draw *)v->data; 296 297 PetscCall(PetscFree(vdraw->drawtype)); 298 PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype)); 299 PetscFunctionReturn(PETSC_SUCCESS); 300 } 301 302 PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v, PetscDrawType *drawtype) 303 { 304 PetscViewer_Draw *vdraw; 305 PetscBool isdraw; 306 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 309 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 310 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 311 vdraw = (PetscViewer_Draw *)v->data; 312 313 *drawtype = vdraw->drawtype; 314 PetscFunctionReturn(PETSC_SUCCESS); 315 } 316 317 PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[]) 318 { 319 PetscViewer_Draw *vdraw; 320 PetscBool isdraw; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 324 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 325 if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS); 326 vdraw = (PetscViewer_Draw *)v->data; 327 328 PetscCall(PetscFree(vdraw->title)); 329 PetscCall(PetscStrallocpy(title, &vdraw->title)); 330 PetscFunctionReturn(PETSC_SUCCESS); 331 } 332 333 PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[]) 334 { 335 PetscViewer_Draw *vdraw; 336 PetscBool isdraw; 337 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 340 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw)); 341 PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer"); 342 vdraw = (PetscViewer_Draw *)v->data; 343 344 *title = vdraw->title; 345 PetscFunctionReturn(PETSC_SUCCESS); 346 } 347 348 /*@C 349 PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type `PETSCVIEWERDRAW`. If you want to 350 do graphics in this window, you must call `PetscViewerDrawGetDraw()` and 351 perform the graphics on the `PetscDraw` object. 352 353 Collective 354 355 Input Parameters: 356 + comm - communicator that will share window 357 . display - the X display on which to open, or `NULL` for the local machine 358 . title - the title to put in the title bar, or `NULL` for no title 359 . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE` 360 . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE` 361 . 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` 362 - 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` 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 in a `PETSCVIEWERDRAW` 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 an MPI 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 in a `PETSCVIEWERDRAW` `PetscViewer` 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