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