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: }