Actual source code: grglvis.c
1: /* Routines to visualize DMDAs and fields through GLVis */
3: #include <petsc/private/dmdaimpl.h>
4: #include <petsc/private/glvisviewerimpl.h>
6: typedef struct {
7: PetscBool ll;
8: } DMDAGhostedGLVisViewerCtx;
10: static PetscErrorCode DMDAGhostedDestroyGLVisViewerCtx_Private(void **vctx)
11: {
12: PetscFree(*vctx);
13: return 0;
14: }
16: typedef struct {
17: Vec xlocal;
18: } DMDAFieldGLVisViewerCtx;
20: static PetscErrorCode DMDAFieldDestroyGLVisViewerCtx_Private(void *vctx)
21: {
22: DMDAFieldGLVisViewerCtx *ctx = (DMDAFieldGLVisViewerCtx *)vctx;
24: VecDestroy(&ctx->xlocal);
25: PetscFree(vctx);
26: return 0;
27: }
29: /*
30: dactx->ll is false -> all but the last proc per dimension claim the ghosted node on the right
31: dactx->ll is true -> all but the first proc per dimension claim the ghosted node on the left
32: */
33: static PetscErrorCode DMDAGetNumElementsGhosted(DM da, PetscInt *nex, PetscInt *ney, PetscInt *nez)
34: {
35: DMDAGhostedGLVisViewerCtx *dactx;
36: PetscInt sx, sy, sz, ien, jen, ken;
38: /* Appease -Wmaybe-uninitialized */
39: if (nex) *nex = -1;
40: if (ney) *ney = -1;
41: if (nez) *nez = -1;
42: DMDAGetCorners(da, &sx, &sy, &sz, &ien, &jen, &ken);
43: DMGetApplicationContext(da, &dactx);
44: if (dactx->ll) {
45: PetscInt dim;
47: DMGetDimension(da, &dim);
48: if (!sx) ien--;
49: if (!sy && dim > 1) jen--;
50: if (!sz && dim > 2) ken--;
51: } else {
52: PetscInt M, N, P;
54: DMDAGetInfo(da, NULL, &M, &N, &P, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
55: if (sx + ien == M) ien--;
56: if (sy + jen == N) jen--;
57: if (sz + ken == P) ken--;
58: }
59: if (nex) *nex = ien;
60: if (ney) *ney = jen;
61: if (nez) *nez = ken;
62: return 0;
63: }
65: /* inherits number of vertices from DMDAGetNumElementsGhosted */
66: static PetscErrorCode DMDAGetNumVerticesGhosted(DM da, PetscInt *nvx, PetscInt *nvy, PetscInt *nvz)
67: {
68: PetscInt ien = 0, jen = 0, ken = 0, dim;
69: PetscInt tote;
71: DMGetDimension(da, &dim);
72: DMDAGetNumElementsGhosted(da, &ien, &jen, &ken);
73: tote = ien * (dim > 1 ? jen : 1) * (dim > 2 ? ken : 1);
74: if (tote) {
75: ien = ien + 1;
76: jen = dim > 1 ? jen + 1 : 1;
77: ken = dim > 2 ? ken + 1 : 1;
78: }
79: if (nvx) *nvx = ien;
80: if (nvy) *nvy = jen;
81: if (nvz) *nvz = ken;
82: return 0;
83: }
85: static PetscErrorCode DMDASampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXf[], void *vctx)
86: {
87: DM da;
88: DMDAFieldGLVisViewerCtx *ctx = (DMDAFieldGLVisViewerCtx *)vctx;
89: DMDAGhostedGLVisViewerCtx *dactx;
90: const PetscScalar *array;
91: PetscScalar **arrayf;
92: PetscInt i, f, ii, ien, jen, ken, ie, je, ke, bs, *bss;
93: PetscInt sx, sy, sz, gsx, gsy, gsz, ist, jst, kst, gm, gn, gp;
95: VecGetDM(ctx->xlocal, &da);
97: DMGetApplicationContext(da, &dactx);
98: VecGetBlockSize(ctx->xlocal, &bs);
99: DMGlobalToLocalBegin(da, (Vec)oX, INSERT_VALUES, ctx->xlocal);
100: DMGlobalToLocalEnd(da, (Vec)oX, INSERT_VALUES, ctx->xlocal);
101: DMDAGetNumVerticesGhosted(da, &ien, &jen, &ken);
102: DMDAGetGhostCorners(da, &gsx, &gsy, &gsz, &gm, &gn, &gp);
103: DMDAGetCorners(da, &sx, &sy, &sz, NULL, NULL, NULL);
104: if (dactx->ll) {
105: kst = jst = ist = 0;
106: } else {
107: kst = gsz != sz ? 1 : 0;
108: jst = gsy != sy ? 1 : 0;
109: ist = gsx != sx ? 1 : 0;
110: }
111: PetscMalloc2(nf, &arrayf, nf, &bss);
112: VecGetArrayRead(ctx->xlocal, &array);
113: for (f = 0; f < nf; f++) {
114: VecGetBlockSize((Vec)oXf[f], &bss[f]);
115: VecGetArray((Vec)oXf[f], &arrayf[f]);
116: }
117: for (ke = kst, ii = 0; ke < kst + ken; ke++) {
118: for (je = jst; je < jst + jen; je++) {
119: for (ie = ist; ie < ist + ien; ie++) {
120: PetscInt cf, b;
121: i = ke * gm * gn + je * gm + ie;
122: for (f = 0, cf = 0; f < nf; f++)
123: for (b = 0; b < bss[f]; b++) arrayf[f][bss[f] * ii + b] = array[i * bs + cf++];
124: ii++;
125: }
126: }
127: }
128: for (f = 0; f < nf; f++) VecRestoreArray((Vec)oXf[f], &arrayf[f]);
129: VecRestoreArrayRead(ctx->xlocal, &array);
130: PetscFree2(arrayf, bss);
131: return 0;
132: }
134: PETSC_INTERN PetscErrorCode DMSetUpGLVisViewer_DMDA(PetscObject oda, PetscViewer viewer)
135: {
136: DM da = (DM)oda, daview;
138: PetscObjectQuery(oda, "GLVisGraphicsDMDAGhosted", (PetscObject *)&daview);
139: if (!daview) {
140: DMDAGhostedGLVisViewerCtx *dactx;
141: DM dacoord = NULL;
142: Vec xcoor, xcoorl;
143: PetscBool hashocoord = PETSC_FALSE;
144: const PetscInt *lx, *ly, *lz;
145: PetscInt dim, M, N, P, m, n, p, dof, s, i;
147: PetscNew(&dactx);
148: dactx->ll = PETSC_TRUE; /* default to match elements layout obtained by DMDAGetElements */
149: PetscOptionsBegin(PetscObjectComm(oda), oda->prefix, "GLVis PetscViewer DMDA Options", "PetscViewer");
150: PetscOptionsBool("-viewer_glvis_dm_da_ll", "Left-looking subdomain view", NULL, dactx->ll, &dactx->ll, NULL);
151: PetscOptionsEnd();
152: /* Create a properly ghosted DMDA to visualize the mesh and the fields associated with */
153: DMDAGetInfo(da, &dim, &M, &N, &P, &m, &n, &p, &dof, &s, NULL, NULL, NULL, NULL);
154: DMDAGetOwnershipRanges(da, &lx, &ly, &lz);
155: PetscObjectQuery((PetscObject)da, "_glvis_mesh_coords", (PetscObject *)&xcoor);
156: if (!xcoor) {
157: DMGetCoordinates(da, &xcoor);
158: } else {
159: hashocoord = PETSC_TRUE;
160: }
161: PetscInfo(da, "Creating auxiliary DMDA for managing GLVis graphics\n");
162: switch (dim) {
163: case 1:
164: DMDACreate1d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, M, dof, 1, lx, &daview);
165: if (!hashocoord) DMDACreate1d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, M, 1, 1, lx, &dacoord);
166: break;
167: case 2:
168: DMDACreate2d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, M, N, m, n, dof, 1, lx, ly, &daview);
169: if (!hashocoord) DMDACreate2d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, M, N, m, n, 2, 1, lx, ly, &dacoord);
170: break;
171: case 3:
172: DMDACreate3d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, M, N, P, m, n, p, dof, 1, lx, ly, lz, &daview);
173: if (!hashocoord) DMDACreate3d(PetscObjectComm((PetscObject)da), DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_BOX, M, N, P, m, n, p, 3, 1, lx, ly, lz, &dacoord);
174: break;
175: default:
176: SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Unsupported dimension %" PetscInt_FMT, dim);
177: }
178: DMSetApplicationContext(daview, dactx);
179: DMSetApplicationContextDestroy(daview, DMDAGhostedDestroyGLVisViewerCtx_Private);
180: DMSetUp(daview);
181: if (!xcoor) {
182: DMDASetUniformCoordinates(daview, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
183: DMGetCoordinates(daview, &xcoor);
184: }
185: if (dacoord) {
186: DMSetUp(dacoord);
187: DMCreateLocalVector(dacoord, &xcoorl);
188: DMGlobalToLocalBegin(dacoord, xcoor, INSERT_VALUES, xcoorl);
189: DMGlobalToLocalEnd(dacoord, xcoor, INSERT_VALUES, xcoorl);
190: DMDestroy(&dacoord);
191: } else {
192: PetscInt ien, jen, ken, nc, nl, cdof, deg;
193: char fecmesh[64];
194: const char *name;
195: PetscBool flg;
197: DMDAGetNumElementsGhosted(daview, &ien, &jen, &ken);
198: nc = ien * (jen > 0 ? jen : 1) * (ken > 0 ? ken : 1);
200: VecGetLocalSize(xcoor, &nl);
202: VecDuplicate(xcoor, &xcoorl);
203: VecCopy(xcoor, xcoorl);
204: VecSetDM(xcoorl, NULL);
205: PetscObjectGetName((PetscObject)xcoor, &name);
206: PetscStrbeginswith(name, "FiniteElementCollection:", &flg);
207: if (!flg) {
208: deg = 0;
209: if (nc && nl) {
210: cdof = nl / (nc * dim);
211: deg = 1;
212: while (1) {
213: PetscInt degd = 1;
214: for (i = 0; i < dim; i++) degd *= (deg + 1);
216: if (degd == cdof) break;
217: deg++;
218: }
219: }
220: PetscSNPrintf(fecmesh, sizeof(fecmesh), "FiniteElementCollection: L2_T1_%" PetscInt_FMT "D_P%" PetscInt_FMT, dim, deg);
221: PetscObjectSetName((PetscObject)xcoorl, fecmesh);
222: } else PetscObjectSetName((PetscObject)xcoorl, name);
223: }
225: /* xcoorl is composed with the ghosted DMDA, the ghosted coordinate DMDA (if present) is only available through this vector */
226: PetscObjectCompose((PetscObject)daview, "GLVisGraphicsCoordsGhosted", (PetscObject)xcoorl);
227: PetscObjectDereference((PetscObject)xcoorl);
229: /* daview is composed with the original DMDA */
230: PetscObjectCompose(oda, "GLVisGraphicsDMDAGhosted", (PetscObject)daview);
231: PetscObjectDereference((PetscObject)daview);
232: }
234: /* customize the viewer if present */
235: if (viewer) {
236: DMDAFieldGLVisViewerCtx *ctx;
237: DMDAGhostedGLVisViewerCtx *dactx;
238: char fec[64];
239: Vec xlocal, *Ufield;
240: const char **dafieldname;
241: char **fec_type, **fieldname;
242: PetscInt *nlocal, *bss, *dims;
243: PetscInt dim, M, N, P, dof, s, i, nf;
244: PetscBool bsset;
246: DMDAGetInfo(daview, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL);
247: DMGetApplicationContext(daview, &dactx);
248: DMCreateLocalVector(daview, &xlocal);
249: DMDAGetFieldNames(da, (const char *const **)&dafieldname);
250: DMDAGetNumVerticesGhosted(daview, &M, &N, &P);
251: PetscSNPrintf(fec, sizeof(fec), "FiniteElementCollection: H1_%" PetscInt_FMT "D_P1", dim);
252: PetscMalloc6(dof, &fec_type, dof, &nlocal, dof, &bss, dof, &dims, dof, &fieldname, dof, &Ufield);
253: for (i = 0; i < dof; i++) bss[i] = 1;
254: nf = dof;
256: PetscOptionsBegin(PetscObjectComm(oda), oda->prefix, "GLVis PetscViewer DMDA Field options", "PetscViewer");
257: PetscOptionsIntArray("-viewer_glvis_dm_da_bs", "Block sizes for subfields; enable vector representation", NULL, bss, &nf, &bsset);
258: PetscOptionsEnd();
259: if (bsset) {
260: PetscInt t;
261: for (i = 0, t = 0; i < nf; i++) t += bss[i];
263: } else nf = dof;
265: for (i = 0, s = 0; i < nf; i++) {
266: PetscStrallocpy(fec, &fec_type[i]);
267: if (bss[i] == 1) {
268: PetscStrallocpy(dafieldname[s], &fieldname[i]);
269: } else {
270: PetscInt b;
271: size_t tlen = 9; /* "Vector-" + end */
272: for (b = 0; b < bss[i]; b++) {
273: size_t len;
274: PetscStrlen(dafieldname[s + b], &len);
275: tlen += len + 1; /* field + "-" */
276: }
277: PetscMalloc1(tlen, &fieldname[i]);
278: PetscStrcpy(fieldname[i], "Vector-");
279: for (b = 0; b < bss[i] - 1; b++) {
280: PetscStrcat(fieldname[i], dafieldname[s + b]);
281: PetscStrcat(fieldname[i], "-");
282: }
283: PetscStrcat(fieldname[i], dafieldname[s + b]);
284: }
285: dims[i] = dim;
286: nlocal[i] = M * N * P * bss[i];
287: s += bss[i];
288: }
290: /* the viewer context takes ownership of xlocal and destroys it in DMDAFieldDestroyGLVisViewerCtx_Private */
291: PetscNew(&ctx);
292: ctx->xlocal = xlocal;
294: /* create work vectors */
295: for (i = 0; i < nf; i++) {
296: VecCreateMPI(PetscObjectComm((PetscObject)da), nlocal[i], PETSC_DECIDE, &Ufield[i]);
297: PetscObjectSetName((PetscObject)Ufield[i], fieldname[i]);
298: VecSetBlockSize(Ufield[i], bss[i]);
299: VecSetDM(Ufield[i], da);
300: }
302: PetscViewerGLVisSetFields(viewer, nf, (const char **)fec_type, dims, DMDASampleGLVisFields_Private, (PetscObject *)Ufield, ctx, DMDAFieldDestroyGLVisViewerCtx_Private);
303: for (i = 0; i < nf; i++) {
304: PetscFree(fec_type[i]);
305: PetscFree(fieldname[i]);
306: VecDestroy(&Ufield[i]);
307: }
308: PetscFree6(fec_type, nlocal, bss, dims, fieldname, Ufield);
309: }
310: return 0;
311: }
313: static PetscErrorCode DMDAView_GLVis_ASCII(DM dm, PetscViewer viewer)
314: {
315: DM da, cda;
316: Vec xcoorl;
317: PetscMPIInt size;
318: const PetscScalar *array;
319: PetscContainer glvis_container;
320: PetscInt dim, sdim, i, vid[8], mid, cid, cdof;
321: PetscInt sx, sy, sz, ie, je, ke, ien, jen, ken, nel;
322: PetscInt gsx, gsy, gsz, gm, gn, gp, kst, jst, ist;
323: PetscBool enabled = PETSC_TRUE, isascii;
324: const char *fmt;
328: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
330: MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size);
332: DMGetDimension(dm, &dim);
334: /* get container: determines if a process visualizes is portion of the data or not */
335: PetscObjectQuery((PetscObject)viewer, "_glvis_info_container", (PetscObject *)&glvis_container);
337: {
338: PetscViewerGLVisInfo glvis_info;
339: PetscContainerGetPointer(glvis_container, (void **)&glvis_info);
340: enabled = glvis_info->enabled;
341: fmt = glvis_info->fmt;
342: }
343: /* this can happen if we are calling DMView outside of VecView_GLVis */
344: PetscObjectQuery((PetscObject)dm, "GLVisGraphicsDMDAGhosted", (PetscObject *)&da);
345: if (!da) DMSetUpGLVisViewer_DMDA((PetscObject)dm, NULL);
346: PetscObjectQuery((PetscObject)dm, "GLVisGraphicsDMDAGhosted", (PetscObject *)&da);
348: DMGetCoordinateDim(da, &sdim);
350: PetscViewerASCIIPrintf(viewer, "MFEM mesh v1.0\n");
351: PetscViewerASCIIPrintf(viewer, "\ndimension\n");
352: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT "\n", dim);
354: if (!enabled) {
355: PetscViewerASCIIPrintf(viewer, "\nelements\n");
356: PetscViewerASCIIPrintf(viewer, "0\n");
357: PetscViewerASCIIPrintf(viewer, "\nboundary\n");
358: PetscViewerASCIIPrintf(viewer, "0\n");
359: PetscViewerASCIIPrintf(viewer, "\nvertices\n");
360: PetscViewerASCIIPrintf(viewer, "0\n");
361: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT "\n", sdim);
362: return 0;
363: }
365: DMDAGetNumElementsGhosted(da, &ien, &jen, &ken);
366: nel = ien;
367: if (dim > 1) nel *= jen;
368: if (dim > 2) nel *= ken;
369: PetscViewerASCIIPrintf(viewer, "\nelements\n");
370: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT "\n", nel);
371: switch (dim) {
372: case 1:
373: for (ie = 0; ie < ien; ie++) {
374: vid[0] = ie;
375: vid[1] = ie + 1;
376: mid = 1; /* material id */
377: cid = 1; /* segment */
378: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", mid, cid, vid[0], vid[1]);
379: }
380: break;
381: case 2:
382: for (je = 0; je < jen; je++) {
383: for (ie = 0; ie < ien; ie++) {
384: vid[0] = je * (ien + 1) + ie;
385: vid[1] = je * (ien + 1) + ie + 1;
386: vid[2] = (je + 1) * (ien + 1) + ie + 1;
387: vid[3] = (je + 1) * (ien + 1) + ie;
388: mid = 1; /* material id */
389: cid = 3; /* quad */
390: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", mid, cid, vid[0], vid[1], vid[2], vid[3]);
391: }
392: }
393: break;
394: case 3:
395: for (ke = 0; ke < ken; ke++) {
396: for (je = 0; je < jen; je++) {
397: for (ie = 0; ie < ien; ie++) {
398: vid[0] = ke * (jen + 1) * (ien + 1) + je * (ien + 1) + ie;
399: vid[1] = ke * (jen + 1) * (ien + 1) + je * (ien + 1) + ie + 1;
400: vid[2] = ke * (jen + 1) * (ien + 1) + (je + 1) * (ien + 1) + ie + 1;
401: vid[3] = ke * (jen + 1) * (ien + 1) + (je + 1) * (ien + 1) + ie;
402: vid[4] = (ke + 1) * (jen + 1) * (ien + 1) + je * (ien + 1) + ie;
403: vid[5] = (ke + 1) * (jen + 1) * (ien + 1) + je * (ien + 1) + ie + 1;
404: vid[6] = (ke + 1) * (jen + 1) * (ien + 1) + (je + 1) * (ien + 1) + ie + 1;
405: vid[7] = (ke + 1) * (jen + 1) * (ien + 1) + (je + 1) * (ien + 1) + ie;
406: mid = 1; /* material id */
407: cid = 5; /* hex */
408: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", mid, cid, vid[0], vid[1], vid[2], vid[3], vid[4], vid[5], vid[6], vid[7]);
409: }
410: }
411: }
412: break;
413: default:
414: SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Unsupported dimension %" PetscInt_FMT, dim);
415: }
416: PetscViewerASCIIPrintf(viewer, "\nboundary\n");
417: PetscViewerASCIIPrintf(viewer, "0\n");
419: /* vertex coordinates */
420: PetscObjectQuery((PetscObject)da, "GLVisGraphicsCoordsGhosted", (PetscObject *)&xcoorl);
422: DMDAGetNumVerticesGhosted(da, &ien, &jen, &ken);
423: PetscViewerASCIIPrintf(viewer, "\nvertices\n");
424: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT "\n", ien * jen * ken);
425: if (nel) {
426: VecGetDM(xcoorl, &cda);
427: VecGetArrayRead(xcoorl, &array);
428: if (!cda) { /* HO viz */
429: const char *fecname;
430: PetscInt nc, nl;
432: PetscObjectGetName((PetscObject)xcoorl, &fecname);
433: PetscViewerASCIIPrintf(viewer, "nodes\n");
434: PetscViewerASCIIPrintf(viewer, "FiniteElementSpace\n");
435: PetscViewerASCIIPrintf(viewer, "%s\n", fecname);
436: PetscViewerASCIIPrintf(viewer, "VDim: %" PetscInt_FMT "\n", sdim);
437: PetscViewerASCIIPrintf(viewer, "Ordering: 1\n\n"); /*Ordering::byVDIM*/
438: /* L2 coordinates */
439: DMDAGetNumElementsGhosted(da, &ien, &jen, &ken);
440: VecGetLocalSize(xcoorl, &nl);
441: nc = ien * (jen > 0 ? jen : 1) * (ken > 0 ? ken : 1);
442: cdof = nc ? nl / nc : 0;
443: if (!ien) ien++;
444: if (!jen) jen++;
445: if (!ken) ken++;
446: ist = jst = kst = 0;
447: gm = ien;
448: gn = jen;
449: gp = ken;
450: } else {
451: DMDAGhostedGLVisViewerCtx *dactx;
453: DMGetApplicationContext(da, &dactx);
454: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT "\n", sdim);
455: cdof = sdim;
456: DMDAGetCorners(da, &sx, &sy, &sz, NULL, NULL, NULL);
457: DMDAGetGhostCorners(da, &gsx, &gsy, &gsz, &gm, &gn, &gp);
458: if (dactx->ll) {
459: kst = jst = ist = 0;
460: } else {
461: kst = gsz != sz ? 1 : 0;
462: jst = gsy != sy ? 1 : 0;
463: ist = gsx != sx ? 1 : 0;
464: }
465: }
466: for (ke = kst; ke < kst + ken; ke++) {
467: for (je = jst; je < jst + jen; je++) {
468: for (ie = ist; ie < ist + ien; ie++) {
469: PetscInt c;
471: i = ke * gm * gn + je * gm + ie;
472: for (c = 0; c < cdof / sdim; c++) {
473: PetscInt d;
474: for (d = 0; d < sdim; d++) PetscViewerASCIIPrintf(viewer, fmt, PetscRealPart(array[cdof * i + c * sdim + d]));
475: PetscViewerASCIIPrintf(viewer, "\n");
476: }
477: }
478: }
479: }
480: VecRestoreArrayRead(xcoorl, &array);
481: }
482: return 0;
483: }
485: PetscErrorCode DMView_DA_GLVis(DM dm, PetscViewer viewer)
486: {
487: DMView_GLVis(dm, viewer, DMDAView_GLVis_ASCII);
488: return 0;
489: }