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