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