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