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