1 2 /* 3 Provides the calling sequences for all the basic PetscDraw routines. 4 */ 5 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/ 6 7 /*@ 8 PetscDrawSetViewPort - Sets the portion of the window (page) to which draw 9 routines will write. 10 11 Collective on PetscDraw 12 13 Input Parameters: 14 + xl - the horizontal coordinate of the lower left corner of the subwindow. 15 . yl - the vertical coordinate of the lower left corner of the subwindow. 16 . xr - the horizontal coordinate of the upper right corner of the subwindow. 17 . yr - the vertical coordinate of the upper right corner of the subwindow. 18 - draw - the drawing context 19 20 Notes: 21 These numbers must always be between 0.0 and 1.0. 22 Lower left corner is (0,0). 23 24 Level: advanced 25 26 @*/ 27 PetscErrorCode PetscDrawSetViewPort(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr) 28 { 29 PetscFunctionBegin; 30 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 31 PetscCheck(xl >= 0.0 && xr <= 1.0 && yl >= 0.0 && yr <= 1.0 && xr > xl && yr > yl,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ViewPort values must be >= 0 and <= 1: Instead %g %g %g %g",(double)xl,(double)yl,(double)xr,(double)yr); 32 draw->port_xl = xl; draw->port_yl = yl; 33 draw->port_xr = xr; draw->port_yr = yr; 34 if (draw->ops->setviewport) { 35 PetscCall((*draw->ops->setviewport)(draw,xl,yl,xr,yr)); 36 } 37 PetscFunctionReturn(0); 38 } 39 40 /*@ 41 PetscDrawGetViewPort - Gets the portion of the window (page) to which draw 42 routines will write. 43 44 Collective on PetscDraw 45 46 Input Parameter: 47 . draw - the drawing context 48 49 Output Parameters: 50 + xl - the horizontal coordinate of the lower left corner of the subwindow. 51 . yl - the vertical coordinate of the lower left corner of the subwindow. 52 . xr - the horizontal coordinate of the upper right corner of the subwindow. 53 - yr - the vertical coordinate of the upper right corner of the subwindow. 54 55 Notes: 56 These numbers must always be between 0.0 and 1.0. 57 Lower left corner is (0,0). 58 59 Level: advanced 60 61 @*/ 62 PetscErrorCode PetscDrawGetViewPort(PetscDraw draw,PetscReal *xl,PetscReal *yl,PetscReal *xr,PetscReal *yr) 63 { 64 PetscFunctionBegin; 65 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 66 PetscValidRealPointer(xl,2); 67 PetscValidRealPointer(yl,3); 68 PetscValidRealPointer(xr,4); 69 PetscValidRealPointer(yr,5); 70 *xl = draw->port_xl; 71 *yl = draw->port_yl; 72 *xr = draw->port_xr; 73 *yr = draw->port_yr; 74 PetscFunctionReturn(0); 75 } 76 77 /*@ 78 PetscDrawSplitViewPort - Splits a window shared by several processes into smaller 79 view ports. One for each process. 80 81 Collective on PetscDraw 82 83 Input Parameter: 84 . draw - the drawing context 85 86 Level: advanced 87 88 .seealso: PetscDrawDivideViewPort(), PetscDrawSetViewPort() 89 90 @*/ 91 PetscErrorCode PetscDrawSplitViewPort(PetscDraw draw) 92 { 93 PetscMPIInt rank,size; 94 PetscInt n; 95 PetscBool isnull; 96 PetscReal xl,xr,yl,yr,h; 97 98 PetscFunctionBegin; 99 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 100 PetscCall(PetscDrawIsNull(draw,&isnull)); 101 if (isnull) PetscFunctionReturn(0); 102 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank)); 103 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size)); 104 105 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size)); 106 while (n*n < size) n++; 107 108 h = 1.0/n; 109 xl = (rank % n)*h; 110 xr = xl + h; 111 yl = (rank / n)*h; 112 yr = yl + h; 113 114 PetscDrawCollectiveBegin(draw); 115 PetscCall(PetscDrawLine(draw,xl,yl,xl,yr,PETSC_DRAW_BLACK)); 116 PetscCall(PetscDrawLine(draw,xl,yr,xr,yr,PETSC_DRAW_BLACK)); 117 PetscCall(PetscDrawLine(draw,xr,yr,xr,yl,PETSC_DRAW_BLACK)); 118 PetscCall(PetscDrawLine(draw,xr,yl,xl,yl,PETSC_DRAW_BLACK)); 119 PetscDrawCollectiveEnd(draw); 120 PetscCall(PetscDrawFlush(draw)); 121 122 draw->port_xl = xl + .05*h; 123 draw->port_xr = xr - .05*h; 124 draw->port_yl = yl + .05*h; 125 draw->port_yr = yr - .05*h; 126 127 if (draw->ops->setviewport) PetscCall((*draw->ops->setviewport)(draw,xl,yl,xr,yr)); 128 PetscFunctionReturn(0); 129 } 130 131 /*@C 132 PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports. 133 134 Collective on PetscDraw 135 136 Input Parameters: 137 + draw - the drawing context 138 - nports - the number of ports 139 140 Output Parameter: 141 . ports - a PetscDrawViewPorts context (C structure) 142 143 Options Database: 144 . -draw_ports - display multiple fields in the same window with PetscDrawPorts() instead of in separate windows 145 146 Level: advanced 147 148 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy() 149 150 @*/ 151 PetscErrorCode PetscDrawViewPortsCreate(PetscDraw draw,PetscInt nports,PetscDrawViewPorts **newports) 152 { 153 PetscDrawViewPorts *ports; 154 PetscInt i,n; 155 PetscBool isnull; 156 PetscMPIInt rank; 157 PetscReal *xl,*xr,*yl,*yr,h; 158 159 PetscFunctionBegin; 160 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 161 PetscCheck(nports >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT, nports); 162 PetscValidPointer(newports,3); 163 PetscCall(PetscDrawIsNull(draw,&isnull)); 164 if (isnull) {*newports = NULL; PetscFunctionReturn(0);} 165 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank)); 166 167 PetscCall(PetscNew(&ports)); *newports = ports; 168 ports->draw = draw; 169 ports->nports = nports; 170 PetscCall(PetscObjectReference((PetscObject)draw)); 171 /* save previous drawport of window */ 172 PetscCall(PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr)); 173 174 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports)); 175 while (n*n < nports) n++; 176 h = 1.0/n; 177 178 PetscCall(PetscMalloc4(n*n,&xl,n*n,&xr,n*n,&yl,n*n,&yr)); 179 ports->xl = xl; 180 ports->xr = xr; 181 ports->yl = yl; 182 ports->yr = yr; 183 184 PetscCall(PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0)); 185 PetscDrawCollectiveBegin(draw); 186 for (i=0; i<n*n; i++) { 187 xl[i] = (i % n)*h; 188 xr[i] = xl[i] + h; 189 yl[i] = (i / n)*h; 190 yr[i] = yl[i] + h; 191 192 if (rank == 0) { 193 PetscCall(PetscDrawLine(draw,xl[i],yl[i],xl[i],yr[i],PETSC_DRAW_BLACK)); 194 PetscCall(PetscDrawLine(draw,xl[i],yr[i],xr[i],yr[i],PETSC_DRAW_BLACK)); 195 PetscCall(PetscDrawLine(draw,xr[i],yr[i],xr[i],yl[i],PETSC_DRAW_BLACK)); 196 PetscCall(PetscDrawLine(draw,xr[i],yl[i],xl[i],yl[i],PETSC_DRAW_BLACK)); 197 } 198 199 xl[i] += .05*h; 200 xr[i] -= .05*h; 201 yl[i] += .05*h; 202 yr[i] -= .05*h; 203 } 204 PetscDrawCollectiveEnd(draw); 205 PetscCall(PetscDrawFlush(draw)); 206 PetscFunctionReturn(0); 207 } 208 209 /*@C 210 PetscDrawViewPortsCreateRect - Splits a window into smaller 211 view ports. Each processor shares all the viewports. The number 212 of views in the x- and y-directions is specified. 213 214 Collective on PetscDraw 215 216 Input Parameters: 217 + draw - the drawing context 218 . nx - the number of x divisions 219 - ny - the number of y divisions 220 221 Output Parameter: 222 . ports - a PetscDrawViewPorts context (C structure) 223 224 Level: advanced 225 226 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy() 227 228 @*/ 229 PetscErrorCode PetscDrawViewPortsCreateRect(PetscDraw draw,PetscInt nx,PetscInt ny,PetscDrawViewPorts **newports) 230 { 231 PetscDrawViewPorts *ports; 232 PetscReal *xl,*xr,*yl,*yr,hx,hy; 233 PetscInt i,j,k,n; 234 PetscBool isnull; 235 PetscMPIInt rank; 236 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 239 PetscCheck(nx >= 1 && ny >= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT " x %" PetscInt_FMT, nx, ny); 240 PetscValidPointer(newports,4); 241 PetscCall(PetscDrawIsNull(draw,&isnull)); 242 if (isnull) {*newports = NULL; PetscFunctionReturn(0);} 243 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank)); 244 245 n = nx*ny; 246 hx = 1.0/nx; 247 hy = 1.0/ny; 248 PetscCall(PetscNew(&ports)); *newports = ports; 249 ports->draw = draw; 250 ports->nports = n; 251 PetscCall(PetscObjectReference((PetscObject) draw)); 252 /* save previous drawport of window */ 253 PetscCall(PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr)); 254 255 PetscCall(PetscMalloc4(n,&xl,n,&xr,n,&yl,n,&yr)); 256 ports->xr = xr; 257 ports->xl = xl; 258 ports->yl = yl; 259 ports->yr = yr; 260 261 PetscCall(PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0)); 262 PetscDrawCollectiveBegin(draw); 263 for (i = 0; i < nx; i++) { 264 for (j = 0; j < ny; j++) { 265 k = j*nx+i; 266 267 xl[k] = i*hx; 268 xr[k] = xl[k] + hx; 269 yl[k] = j*hy; 270 yr[k] = yl[k] + hy; 271 272 if (rank == 0) { 273 PetscCall(PetscDrawLine(draw,xl[k],yl[k],xl[k],yr[k],PETSC_DRAW_BLACK)); 274 PetscCall(PetscDrawLine(draw,xl[k],yr[k],xr[k],yr[k],PETSC_DRAW_BLACK)); 275 PetscCall(PetscDrawLine(draw,xr[k],yr[k],xr[k],yl[k],PETSC_DRAW_BLACK)); 276 PetscCall(PetscDrawLine(draw,xr[k],yl[k],xl[k],yl[k],PETSC_DRAW_BLACK)); 277 } 278 279 xl[k] += .05*hx; 280 xr[k] -= .05*hx; 281 yl[k] += .05*hy; 282 yr[k] -= .05*hy; 283 } 284 } 285 PetscDrawCollectiveEnd(draw); 286 PetscCall(PetscDrawFlush(draw)); 287 PetscFunctionReturn(0); 288 } 289 290 /*@C 291 PetscDrawViewPortsDestroy - frees a PetscDrawViewPorts object 292 293 Collective on PetscDraw inside PetscDrawViewPorts 294 295 Input Parameter: 296 . ports - the PetscDrawViewPorts object 297 298 Level: advanced 299 300 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsCreate() 301 302 @*/ 303 PetscErrorCode PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports) 304 { 305 PetscFunctionBegin; 306 if (!ports) PetscFunctionReturn(0); 307 PetscValidPointer(ports,1); 308 /* reset Drawport of Window back to previous value */ 309 PetscCall(PetscDrawSetViewPort(ports->draw,ports->port_xl,ports->port_yl,ports->port_xr,ports->port_yr)); 310 PetscCall(PetscDrawDestroy(&ports->draw)); 311 PetscCall(PetscFree4(ports->xl,ports->xr,ports->yl,ports->yr)); 312 PetscCall(PetscFree(ports)); 313 PetscFunctionReturn(0); 314 } 315 316 /*@C 317 PetscDrawViewPortsSet - sets a draw object to use a particular subport 318 319 Logically Collective on PetscDraw inside PetscDrawViewPorts 320 321 Input Parameters: 322 + ports - the PetscDrawViewPorts object 323 - port - the port number, from 0 to nports-1 324 325 Level: advanced 326 327 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsDestroy(), PetscDrawViewPortsCreate() 328 329 @*/ 330 PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports,PetscInt port) 331 { 332 PetscFunctionBegin; 333 if (!ports) PetscFunctionReturn(0); 334 PetscValidPointer(ports,1); 335 PetscCheck(port >= 0 && (port <= ports->nports-1),PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Port is out of range requested %" PetscInt_FMT " from 0 to %" PetscInt_FMT,port,ports->nports-1); 336 PetscCall(PetscDrawSetViewPort(ports->draw,ports->xl[port],ports->yl[port],ports->xr[port],ports->yr[port])); 337 PetscFunctionReturn(0); 338 } 339