Actual source code: dviewp.c
2: #include <petsc/private/drawimpl.h>
4: /*@
5: PetscDrawSetViewPort - Sets the portion of the window (page) to which draw
6: routines will write.
8: Collective
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
17: Level: advanced
19: Notes:
20: These numbers must always be between 0.0 and 1.0.
22: Lower left corner is (0,0).
24: .seealso: `PetscDrawGetViewPort()`, `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawViewPortsCreate()`
25: @*/
26: PetscErrorCode PetscDrawSetViewPort(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr)
27: {
28: PetscFunctionBegin;
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: }
39: /*@
40: PetscDrawGetViewPort - Gets the portion of the window (page) to which draw
41: routines will write.
43: Collective
45: Input Parameter:
46: . draw - the drawing context
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.
54: Level: advanced
56: Notes:
57: These numbers must always be between 0.0 and 1.0.
59: Lower left corner is (0,0).
61: .seealso: `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`
62: @*/
63: PetscErrorCode PetscDrawGetViewPort(PetscDraw draw, PetscReal *xl, PetscReal *yl, PetscReal *xr, PetscReal *yr)
64: {
65: PetscFunctionBegin;
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: }
78: /*@
79: PetscDrawSplitViewPort - Splits a window shared by several processes into smaller
80: view ports. One for each process.
82: Collective
84: Input Parameter:
85: . draw - the drawing context
87: Level: advanced
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;
98: PetscFunctionBegin;
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));
105: n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size));
106: while (n * n < size) n++;
108: h = 1.0 / n;
109: xl = (rank % n) * h;
110: xr = xl + h;
111: yl = (rank / n) * h;
112: yr = yl + h;
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));
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;
127: PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr);
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: /*@C
132: PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports.
134: Collective
136: Input Parameters:
137: + draw - the drawing context
138: - nports - the number of ports
140: Output Parameter:
141: . ports - a `PetscDrawViewPorts` context (C structure)
143: Options Database Key:
144: . -draw_ports - display multiple fields in the same window with PetscDrawPorts() instead of in separate windows
146: Level: advanced
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;
158: PetscFunctionBegin;
160: PetscCheck(nports >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT, nports);
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));
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));
177: n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports));
178: while (n * n < nports) n++;
179: h = 1.0 / n;
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;
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;
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: }
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: }
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.
217: Collective
219: Input Parameters:
220: + draw - the drawing context
221: . nx - the number of x divisions
222: - ny - the number of y divisions
224: Output Parameter:
225: . ports - a `PetscDrawViewPorts` context (C structure)
227: Level: advanced
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;
239: PetscFunctionBegin;
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);
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));
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));
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;
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;
273: xl[k] = i * hx;
274: xr[k] = xl[k] + hx;
275: yl[k] = j * hy;
276: yr[k] = yl[k] + hy;
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: }
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: }
296: /*@C
297: PetscDrawViewPortsDestroy - frees a `PetscDrawViewPorts` object
299: Collective on the PetscDraw inside ports
301: Input Parameter:
302: . ports - the `PetscDrawViewPorts` object
304: Level: advanced
306: .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsCreate()`
307: @*/
308: PetscErrorCode PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports)
309: {
310: PetscFunctionBegin;
311: if (!ports) PetscFunctionReturn(PETSC_SUCCESS);
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: }
321: /*@C
322: PetscDrawViewPortsSet - sets a draw object to use a particular subport
324: Logically Collective on the `PetscDraw` inside ports
326: Input Parameters:
327: + ports - the `PetscDrawViewPorts` object
328: - port - the port number, from 0 to nports-1
330: Level: advanced
332: .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPortsCreate()`
333: @*/
334: PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports, PetscInt port)
335: {
336: PetscFunctionBegin;
337: if (!ports) PetscFunctionReturn(PETSC_SUCCESS);
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: }