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