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