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