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