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 PetscFunctionBegin; 29 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 30 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); 31 draw->port_xl = xl; 32 draw->port_yl = yl; 33 draw->port_xr = xr; 34 draw->port_yr = yr; 35 PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr); 36 PetscFunctionReturn(0); 37 } 38 39 /*@ 40 PetscDrawGetViewPort - Gets the portion of the window (page) to which draw 41 routines will write. 42 43 Collective on PetscDraw 44 45 Input Parameter: 46 . draw - the drawing context 47 48 Output Parameters: 49 + xl - the horizontal coordinate of the lower left corner of the subwindow. 50 . yl - the vertical coordinate of the lower left corner of the subwindow. 51 . xr - the horizontal coordinate of the upper right corner of the subwindow. 52 - yr - the vertical coordinate of the upper right corner of the subwindow. 53 54 Notes: 55 These numbers must always be between 0.0 and 1.0. 56 Lower left corner is (0,0). 57 58 Level: advanced 59 60 @*/ 61 PetscErrorCode PetscDrawGetViewPort(PetscDraw draw, PetscReal *xl, PetscReal *yl, PetscReal *xr, PetscReal *yr) { 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 PetscMPIInt rank, size; 91 PetscInt n; 92 PetscBool isnull; 93 PetscReal xl, xr, yl, yr, h; 94 95 PetscFunctionBegin; 96 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 97 PetscCall(PetscDrawIsNull(draw, &isnull)); 98 if (isnull) PetscFunctionReturn(0); 99 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 100 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size)); 101 102 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size)); 103 while (n * n < size) n++; 104 105 h = 1.0 / n; 106 xl = (rank % n) * h; 107 xr = xl + h; 108 yl = (rank / n) * h; 109 yr = yl + h; 110 111 PetscDrawCollectiveBegin(draw); 112 PetscCall(PetscDrawLine(draw, xl, yl, xl, yr, PETSC_DRAW_BLACK)); 113 PetscCall(PetscDrawLine(draw, xl, yr, xr, yr, PETSC_DRAW_BLACK)); 114 PetscCall(PetscDrawLine(draw, xr, yr, xr, yl, PETSC_DRAW_BLACK)); 115 PetscCall(PetscDrawLine(draw, xr, yl, xl, yl, PETSC_DRAW_BLACK)); 116 PetscDrawCollectiveEnd(draw); 117 PetscCall(PetscDrawFlush(draw)); 118 119 draw->port_xl = xl + .05 * h; 120 draw->port_xr = xr - .05 * h; 121 draw->port_yl = yl + .05 * h; 122 draw->port_yr = yr - .05 * h; 123 124 PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr); 125 PetscFunctionReturn(0); 126 } 127 128 /*@C 129 PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports. 130 131 Collective on PetscDraw 132 133 Input Parameters: 134 + draw - the drawing context 135 - nports - the number of ports 136 137 Output Parameter: 138 . ports - a PetscDrawViewPorts context (C structure) 139 140 Options Database: 141 . -draw_ports - display multiple fields in the same window with PetscDrawPorts() instead of in separate windows 142 143 Level: advanced 144 145 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsDestroy()` 146 147 @*/ 148 PetscErrorCode PetscDrawViewPortsCreate(PetscDraw draw, PetscInt nports, PetscDrawViewPorts **newports) { 149 PetscDrawViewPorts *ports; 150 PetscInt i, n; 151 PetscBool isnull; 152 PetscMPIInt rank; 153 PetscReal *xl, *xr, *yl, *yr, h; 154 155 PetscFunctionBegin; 156 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 157 PetscCheck(nports >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT, nports); 158 PetscValidPointer(newports, 3); 159 PetscCall(PetscDrawIsNull(draw, &isnull)); 160 if (isnull) { 161 *newports = NULL; 162 PetscFunctionReturn(0); 163 } 164 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 165 166 PetscCall(PetscNew(&ports)); 167 *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 PetscDrawViewPorts *ports; 231 PetscReal *xl, *xr, *yl, *yr, hx, hy; 232 PetscInt i, j, k, n; 233 PetscBool isnull; 234 PetscMPIInt rank; 235 236 PetscFunctionBegin; 237 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 238 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); 239 PetscValidPointer(newports, 4); 240 PetscCall(PetscDrawIsNull(draw, &isnull)); 241 if (isnull) { 242 *newports = NULL; 243 PetscFunctionReturn(0); 244 } 245 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 246 247 n = nx * ny; 248 hx = 1.0 / nx; 249 hy = 1.0 / ny; 250 PetscCall(PetscNew(&ports)); 251 *newports = ports; 252 ports->draw = draw; 253 ports->nports = n; 254 PetscCall(PetscObjectReference((PetscObject)draw)); 255 /* save previous drawport of window */ 256 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr)); 257 258 PetscCall(PetscMalloc4(n, &xl, n, &xr, n, &yl, n, &yr)); 259 ports->xr = xr; 260 ports->xl = xl; 261 ports->yl = yl; 262 ports->yr = yr; 263 264 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0)); 265 PetscDrawCollectiveBegin(draw); 266 for (i = 0; i < nx; i++) { 267 for (j = 0; j < ny; j++) { 268 k = j * nx + i; 269 270 xl[k] = i * hx; 271 xr[k] = xl[k] + hx; 272 yl[k] = j * hy; 273 yr[k] = yl[k] + hy; 274 275 if (rank == 0) { 276 PetscCall(PetscDrawLine(draw, xl[k], yl[k], xl[k], yr[k], PETSC_DRAW_BLACK)); 277 PetscCall(PetscDrawLine(draw, xl[k], yr[k], xr[k], yr[k], PETSC_DRAW_BLACK)); 278 PetscCall(PetscDrawLine(draw, xr[k], yr[k], xr[k], yl[k], PETSC_DRAW_BLACK)); 279 PetscCall(PetscDrawLine(draw, xr[k], yl[k], xl[k], yl[k], PETSC_DRAW_BLACK)); 280 } 281 282 xl[k] += .05 * hx; 283 xr[k] -= .05 * hx; 284 yl[k] += .05 * hy; 285 yr[k] -= .05 * hy; 286 } 287 } 288 PetscDrawCollectiveEnd(draw); 289 PetscCall(PetscDrawFlush(draw)); 290 PetscFunctionReturn(0); 291 } 292 293 /*@C 294 PetscDrawViewPortsDestroy - frees a PetscDrawViewPorts object 295 296 Collective on PetscDraw inside PetscDrawViewPorts 297 298 Input Parameter: 299 . ports - the PetscDrawViewPorts object 300 301 Level: advanced 302 303 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsCreate()` 304 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 PetscDraw inside PetscDrawViewPorts 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: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPortsCreate()` 330 331 @*/ 332 PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports, PetscInt port) { 333 PetscFunctionBegin; 334 if (!ports) PetscFunctionReturn(0); 335 PetscValidPointer(ports, 1); 336 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); 337 PetscCall(PetscDrawSetViewPort(ports->draw, ports->xl[port], ports->yl[port], ports->xr[port], ports->yr[port])); 338 PetscFunctionReturn(0); 339 } 340