1 2 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/ 3 4 /*@ 5 PetscDrawSetViewPort - Sets the portion of the window (page) to which draw 6 routines will write. 7 8 Collective 9 10 Input Parameters: 11 + xl - the horizontal coordinate of the lower left corner of the subwindow. 12 . yl - the vertical coordinate of the lower left corner of the subwindow. 13 . xr - the horizontal coordinate of the upper right corner of the subwindow. 14 . yr - the vertical coordinate of the upper right corner of the subwindow. 15 - draw - the drawing context 16 17 Level: advanced 18 19 Notes: 20 These numbers must always be between 0.0 and 1.0. 21 22 Lower left corner is (0,0). 23 24 .seealso: `PetscDrawGetViewPort()`, `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawViewPortsCreate()` 25 @*/ 26 PetscErrorCode PetscDrawSetViewPort(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr) 27 { 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(PETSC_SUCCESS); 37 } 38 39 /*@ 40 PetscDrawGetViewPort - Gets the portion of the window (page) to which draw 41 routines will write. 42 43 Collective 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 Level: advanced 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 .seealso: `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()` 62 @*/ 63 PetscErrorCode PetscDrawGetViewPort(PetscDraw draw, PetscReal *xl, PetscReal *yl, PetscReal *xr, PetscReal *yr) 64 { 65 PetscFunctionBegin; 66 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 67 PetscValidRealPointer(xl, 2); 68 PetscValidRealPointer(yl, 3); 69 PetscValidRealPointer(xr, 4); 70 PetscValidRealPointer(yr, 5); 71 *xl = draw->port_xl; 72 *yl = draw->port_yl; 73 *xr = draw->port_xr; 74 *yr = draw->port_yr; 75 PetscFunctionReturn(PETSC_SUCCESS); 76 } 77 78 /*@ 79 PetscDrawSplitViewPort - Splits a window shared by several processes into smaller 80 view ports. One for each process. 81 82 Collective 83 84 Input Parameter: 85 . draw - the drawing context 86 87 Level: advanced 88 89 .seealso: `PetscDrawDivideViewPort()`, `PetscDrawSetViewPort()` 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 129 } 130 131 /*@C 132 PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports. 133 134 Collective 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 { 152 PetscDrawViewPorts *ports; 153 PetscInt i, n; 154 PetscBool isnull; 155 PetscMPIInt rank; 156 PetscReal *xl, *xr, *yl, *yr, h; 157 158 PetscFunctionBegin; 159 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 160 PetscCheck(nports >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT, nports); 161 PetscValidPointer(newports, 3); 162 PetscCall(PetscDrawIsNull(draw, &isnull)); 163 if (isnull) { 164 *newports = NULL; 165 PetscFunctionReturn(PETSC_SUCCESS); 166 } 167 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 168 169 PetscCall(PetscNew(&ports)); 170 *newports = ports; 171 ports->draw = draw; 172 ports->nports = nports; 173 PetscCall(PetscObjectReference((PetscObject)draw)); 174 /* save previous drawport of window */ 175 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr)); 176 177 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports)); 178 while (n * n < nports) n++; 179 h = 1.0 / n; 180 181 PetscCall(PetscMalloc4(n * n, &xl, n * n, &xr, n * n, &yl, n * n, &yr)); 182 ports->xl = xl; 183 ports->xr = xr; 184 ports->yl = yl; 185 ports->yr = yr; 186 187 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0)); 188 PetscDrawCollectiveBegin(draw); 189 for (i = 0; i < n * n; i++) { 190 xl[i] = (i % n) * h; 191 xr[i] = xl[i] + h; 192 yl[i] = (i / n) * h; 193 yr[i] = yl[i] + h; 194 195 if (rank == 0) { 196 PetscCall(PetscDrawLine(draw, xl[i], yl[i], xl[i], yr[i], PETSC_DRAW_BLACK)); 197 PetscCall(PetscDrawLine(draw, xl[i], yr[i], xr[i], yr[i], PETSC_DRAW_BLACK)); 198 PetscCall(PetscDrawLine(draw, xr[i], yr[i], xr[i], yl[i], PETSC_DRAW_BLACK)); 199 PetscCall(PetscDrawLine(draw, xr[i], yl[i], xl[i], yl[i], PETSC_DRAW_BLACK)); 200 } 201 202 xl[i] += .05 * h; 203 xr[i] -= .05 * h; 204 yl[i] += .05 * h; 205 yr[i] -= .05 * h; 206 } 207 PetscDrawCollectiveEnd(draw); 208 PetscCall(PetscDrawFlush(draw)); 209 PetscFunctionReturn(PETSC_SUCCESS); 210 } 211 212 /*@C 213 PetscDrawViewPortsCreateRect - Splits a window into smaller 214 view ports. Each processor shares all the viewports. The number 215 of views in the x- and y-directions is specified. 216 217 Collective 218 219 Input Parameters: 220 + draw - the drawing context 221 . nx - the number of x divisions 222 - ny - the number of y divisions 223 224 Output Parameter: 225 . ports - a `PetscDrawViewPorts` context (C structure) 226 227 Level: advanced 228 229 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPorts` 230 @*/ 231 PetscErrorCode PetscDrawViewPortsCreateRect(PetscDraw draw, PetscInt nx, PetscInt ny, PetscDrawViewPorts **newports) 232 { 233 PetscDrawViewPorts *ports; 234 PetscReal *xl, *xr, *yl, *yr, hx, hy; 235 PetscInt i, j, k, n; 236 PetscBool isnull; 237 PetscMPIInt rank; 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 241 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); 242 PetscValidPointer(newports, 4); 243 PetscCall(PetscDrawIsNull(draw, &isnull)); 244 if (isnull) { 245 *newports = NULL; 246 PetscFunctionReturn(PETSC_SUCCESS); 247 } 248 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 249 250 n = nx * ny; 251 hx = 1.0 / nx; 252 hy = 1.0 / ny; 253 PetscCall(PetscNew(&ports)); 254 *newports = ports; 255 ports->draw = draw; 256 ports->nports = n; 257 PetscCall(PetscObjectReference((PetscObject)draw)); 258 /* save previous drawport of window */ 259 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr)); 260 261 PetscCall(PetscMalloc4(n, &xl, n, &xr, n, &yl, n, &yr)); 262 ports->xr = xr; 263 ports->xl = xl; 264 ports->yl = yl; 265 ports->yr = yr; 266 267 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0)); 268 PetscDrawCollectiveBegin(draw); 269 for (i = 0; i < nx; i++) { 270 for (j = 0; j < ny; j++) { 271 k = j * nx + i; 272 273 xl[k] = i * hx; 274 xr[k] = xl[k] + hx; 275 yl[k] = j * hy; 276 yr[k] = yl[k] + hy; 277 278 if (rank == 0) { 279 PetscCall(PetscDrawLine(draw, xl[k], yl[k], xl[k], yr[k], PETSC_DRAW_BLACK)); 280 PetscCall(PetscDrawLine(draw, xl[k], yr[k], xr[k], yr[k], PETSC_DRAW_BLACK)); 281 PetscCall(PetscDrawLine(draw, xr[k], yr[k], xr[k], yl[k], PETSC_DRAW_BLACK)); 282 PetscCall(PetscDrawLine(draw, xr[k], yl[k], xl[k], yl[k], PETSC_DRAW_BLACK)); 283 } 284 285 xl[k] += .05 * hx; 286 xr[k] -= .05 * hx; 287 yl[k] += .05 * hy; 288 yr[k] -= .05 * hy; 289 } 290 } 291 PetscDrawCollectiveEnd(draw); 292 PetscCall(PetscDrawFlush(draw)); 293 PetscFunctionReturn(PETSC_SUCCESS); 294 } 295 296 /*@C 297 PetscDrawViewPortsDestroy - frees a `PetscDrawViewPorts` object 298 299 Collective on the PetscDraw inside ports 300 301 Input Parameter: 302 . ports - the `PetscDrawViewPorts` object 303 304 Level: advanced 305 306 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsCreate()` 307 @*/ 308 PetscErrorCode PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports) 309 { 310 PetscFunctionBegin; 311 if (!ports) PetscFunctionReturn(PETSC_SUCCESS); 312 PetscValidPointer(ports, 1); 313 /* reset Drawport of Window back to previous value */ 314 PetscCall(PetscDrawSetViewPort(ports->draw, ports->port_xl, ports->port_yl, ports->port_xr, ports->port_yr)); 315 PetscCall(PetscDrawDestroy(&ports->draw)); 316 PetscCall(PetscFree4(ports->xl, ports->xr, ports->yl, ports->yr)); 317 PetscCall(PetscFree(ports)); 318 PetscFunctionReturn(PETSC_SUCCESS); 319 } 320 321 /*@C 322 PetscDrawViewPortsSet - sets a draw object to use a particular subport 323 324 Logically Collective on the `PetscDraw` inside ports 325 326 Input Parameters: 327 + ports - the `PetscDrawViewPorts` object 328 - port - the port number, from 0 to nports-1 329 330 Level: advanced 331 332 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPortsCreate()` 333 @*/ 334 PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports, PetscInt port) 335 { 336 PetscFunctionBegin; 337 if (!ports) PetscFunctionReturn(PETSC_SUCCESS); 338 PetscValidPointer(ports, 1); 339 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); 340 PetscCall(PetscDrawSetViewPort(ports->draw, ports->xl[port], ports->yl[port], ports->xr[port], ports->yr[port])); 341 PetscFunctionReturn(PETSC_SUCCESS); 342 } 343