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 PetscFunctionBegin; 31 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 32 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); 33 draw->port_xl = xl; 34 draw->port_yl = yl; 35 draw->port_xr = xr; 36 draw->port_yr = yr; 37 PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr); 38 PetscFunctionReturn(0); 39 } 40 41 /*@ 42 PetscDrawGetViewPort - Gets the portion of the window (page) to which draw 43 routines will write. 44 45 Collective on draw 46 47 Input Parameter: 48 . draw - the drawing context 49 50 Output Parameters: 51 + xl - the horizontal coordinate of the lower left corner of the subwindow. 52 . yl - the vertical coordinate of the lower left corner of the subwindow. 53 . xr - the horizontal coordinate of the upper right corner of the subwindow. 54 - yr - the vertical coordinate of the upper right corner of the subwindow. 55 56 Notes: 57 These numbers must always be between 0.0 and 1.0. 58 59 Lower left corner is (0,0). 60 61 Level: advanced 62 63 .seealso: `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()` 64 @*/ 65 PetscErrorCode PetscDrawGetViewPort(PetscDraw draw, PetscReal *xl, PetscReal *yl, PetscReal *xr, PetscReal *yr) { 66 PetscFunctionBegin; 67 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 68 PetscValidRealPointer(xl, 2); 69 PetscValidRealPointer(yl, 3); 70 PetscValidRealPointer(xr, 4); 71 PetscValidRealPointer(yr, 5); 72 *xl = draw->port_xl; 73 *yl = draw->port_yl; 74 *xr = draw->port_xr; 75 *yr = draw->port_yr; 76 PetscFunctionReturn(0); 77 } 78 79 /*@ 80 PetscDrawSplitViewPort - Splits a window shared by several processes into smaller 81 view ports. One for each process. 82 83 Collective on draw 84 85 Input Parameter: 86 . draw - the drawing context 87 88 Level: advanced 89 90 .seealso: `PetscDrawDivideViewPort()`, `PetscDrawSetViewPort()` 91 @*/ 92 PetscErrorCode PetscDrawSplitViewPort(PetscDraw draw) { 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 PetscTryTypeMethod(draw, setviewport, 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 draw 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 Key: 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 PetscErrorCode PetscDrawViewPortsCreate(PetscDraw draw, PetscInt nports, PetscDrawViewPorts **newports) { 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) { 163 *newports = NULL; 164 PetscFunctionReturn(0); 165 } 166 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 167 168 PetscCall(PetscNew(&ports)); 169 *newports = ports; 170 ports->draw = draw; 171 ports->nports = nports; 172 PetscCall(PetscObjectReference((PetscObject)draw)); 173 /* save previous drawport of window */ 174 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr)); 175 176 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports)); 177 while (n * n < nports) n++; 178 h = 1.0 / n; 179 180 PetscCall(PetscMalloc4(n * n, &xl, n * n, &xr, n * n, &yl, n * n, &yr)); 181 ports->xl = xl; 182 ports->xr = xr; 183 ports->yl = yl; 184 ports->yr = yr; 185 186 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0)); 187 PetscDrawCollectiveBegin(draw); 188 for (i = 0; i < n * n; i++) { 189 xl[i] = (i % n) * h; 190 xr[i] = xl[i] + h; 191 yl[i] = (i / n) * h; 192 yr[i] = yl[i] + h; 193 194 if (rank == 0) { 195 PetscCall(PetscDrawLine(draw, xl[i], yl[i], xl[i], yr[i], PETSC_DRAW_BLACK)); 196 PetscCall(PetscDrawLine(draw, xl[i], yr[i], xr[i], yr[i], PETSC_DRAW_BLACK)); 197 PetscCall(PetscDrawLine(draw, xr[i], yr[i], xr[i], yl[i], PETSC_DRAW_BLACK)); 198 PetscCall(PetscDrawLine(draw, xr[i], yl[i], xl[i], yl[i], PETSC_DRAW_BLACK)); 199 } 200 201 xl[i] += .05 * h; 202 xr[i] -= .05 * h; 203 yl[i] += .05 * h; 204 yr[i] -= .05 * h; 205 } 206 PetscDrawCollectiveEnd(draw); 207 PetscCall(PetscDrawFlush(draw)); 208 PetscFunctionReturn(0); 209 } 210 211 /*@C 212 PetscDrawViewPortsCreateRect - Splits a window into smaller 213 view ports. Each processor shares all the viewports. The number 214 of views in the x- and y-directions is specified. 215 216 Collective on draw 217 218 Input Parameters: 219 + draw - the drawing context 220 . nx - the number of x divisions 221 - ny - the number of y divisions 222 223 Output Parameter: 224 . ports - a `PetscDrawViewPorts` context (C structure) 225 226 Level: advanced 227 228 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPorts` 229 @*/ 230 PetscErrorCode PetscDrawViewPortsCreateRect(PetscDraw draw, PetscInt nx, PetscInt ny, PetscDrawViewPorts **newports) { 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) { 243 *newports = NULL; 244 PetscFunctionReturn(0); 245 } 246 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 247 248 n = nx * ny; 249 hx = 1.0 / nx; 250 hy = 1.0 / ny; 251 PetscCall(PetscNew(&ports)); 252 *newports = ports; 253 ports->draw = draw; 254 ports->nports = n; 255 PetscCall(PetscObjectReference((PetscObject)draw)); 256 /* save previous drawport of window */ 257 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr)); 258 259 PetscCall(PetscMalloc4(n, &xl, n, &xr, n, &yl, n, &yr)); 260 ports->xr = xr; 261 ports->xl = xl; 262 ports->yl = yl; 263 ports->yr = yr; 264 265 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0)); 266 PetscDrawCollectiveBegin(draw); 267 for (i = 0; i < nx; i++) { 268 for (j = 0; j < ny; j++) { 269 k = j * nx + i; 270 271 xl[k] = i * hx; 272 xr[k] = xl[k] + hx; 273 yl[k] = j * hy; 274 yr[k] = yl[k] + hy; 275 276 if (rank == 0) { 277 PetscCall(PetscDrawLine(draw, xl[k], yl[k], xl[k], yr[k], PETSC_DRAW_BLACK)); 278 PetscCall(PetscDrawLine(draw, xl[k], yr[k], xr[k], yr[k], PETSC_DRAW_BLACK)); 279 PetscCall(PetscDrawLine(draw, xr[k], yr[k], xr[k], yl[k], PETSC_DRAW_BLACK)); 280 PetscCall(PetscDrawLine(draw, xr[k], yl[k], xl[k], yl[k], PETSC_DRAW_BLACK)); 281 } 282 283 xl[k] += .05 * hx; 284 xr[k] -= .05 * hx; 285 yl[k] += .05 * hy; 286 yr[k] -= .05 * hy; 287 } 288 } 289 PetscDrawCollectiveEnd(draw); 290 PetscCall(PetscDrawFlush(draw)); 291 PetscFunctionReturn(0); 292 } 293 294 /*@C 295 PetscDrawViewPortsDestroy - frees a `PetscDrawViewPorts` object 296 297 Collective on the PetscDraw inside ports 298 299 Input Parameter: 300 . ports - the `PetscDrawViewPorts` object 301 302 Level: advanced 303 304 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsCreate()` 305 @*/ 306 PetscErrorCode PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports) { 307 PetscFunctionBegin; 308 if (!ports) PetscFunctionReturn(0); 309 PetscValidPointer(ports, 1); 310 /* reset Drawport of Window back to previous value */ 311 PetscCall(PetscDrawSetViewPort(ports->draw, ports->port_xl, ports->port_yl, ports->port_xr, ports->port_yr)); 312 PetscCall(PetscDrawDestroy(&ports->draw)); 313 PetscCall(PetscFree4(ports->xl, ports->xr, ports->yl, ports->yr)); 314 PetscCall(PetscFree(ports)); 315 PetscFunctionReturn(0); 316 } 317 318 /*@C 319 PetscDrawViewPortsSet - sets a draw object to use a particular subport 320 321 Logically Collective on the `PetscDraw` inside ports 322 323 Input Parameters: 324 + ports - the `PetscDrawViewPorts` object 325 - port - the port number, from 0 to nports-1 326 327 Level: advanced 328 329 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPortsCreate()` 330 @*/ 331 PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports, PetscInt port) { 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