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