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