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