Actual source code: plexvtu.c

petsc-3.9.4 2018-09-11
Report Typos and Errors
  1:  #include <petsc/private/dmpleximpl.h>
  2:  #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h>

  4: typedef struct {
  5:   PetscInt nvertices;
  6:   PetscInt ncells;
  7:   PetscInt nconn;               /* number of entries in cell->vertex connectivity array */
  8: } PieceInfo;

 10: #if defined(PETSC_USE_REAL_SINGLE)
 11: static const char precision[] = "Float32";
 12: #elif defined(PETSC_USE_REAL_DOUBLE)
 13: static const char precision[] = "Float64";
 14: #else
 15: static const char precision[] = "UnknownPrecision";
 16: #endif

 18: static PetscErrorCode TransferWrite(PetscViewer viewer,FILE *fp,PetscMPIInt srank,PetscMPIInt root,const void *send,void *recv,PetscMPIInt count,MPI_Datatype mpidatatype,PetscMPIInt tag)
 19: {
 20:   PetscMPIInt    rank;
 22:   MPI_Comm       comm;

 25:   PetscObjectGetComm((PetscObject)viewer,&comm);
 26:   MPI_Comm_rank(comm,&rank);

 28:   if (rank == srank && rank != root) {
 29:     MPI_Send((void*)send,count,mpidatatype,root,tag,comm);
 30:   } else if (rank == root) {
 31:     const void *buffer;
 32:     if (root == srank) {        /* self */
 33:       buffer = send;
 34:     } else {
 35:       MPI_Status  status;
 36:       PetscMPIInt nrecv;
 37:       MPI_Recv(recv,count,mpidatatype,srank,tag,comm,&status);
 38:       MPI_Get_count(&status,mpidatatype,&nrecv);
 39:       if (count != nrecv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Array size mismatch");
 40:       buffer = recv;
 41:     }
 42:     PetscViewerVTKFWrite(viewer,fp,buffer,count,mpidatatype);
 43:   }
 44:   return(0);
 45: }

 47: static PetscErrorCode DMPlexGetVTKConnectivity(DM dm, PetscBool localized, PieceInfo *piece,PetscVTKInt **oconn,PetscVTKInt **ooffsets,PetscVTKType **otypes)
 48: {
 50:   PetscSection   coordSection;
 51:   PetscVTKInt    *conn,*offsets;
 52:   PetscVTKType   *types;
 53:   PetscInt       dim,vStart,vEnd,cStart,cEnd,pStart,pEnd,cellHeight,cMax,numLabelCells,hasLabel,c,v,countcell,countconn;

 56:   PetscMalloc3(piece->nconn,&conn,piece->ncells,&offsets,piece->ncells,&types);
 57:   DMGetCoordinateSection(dm, &coordSection);
 58:   DMGetDimension(dm,&dim);
 59:   DMPlexGetChart(dm,&pStart,&pEnd);
 60:   DMPlexGetVTKCellHeight(dm, &cellHeight);
 61:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
 62:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
 63:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
 64:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
 65:   DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
 66:   hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;

 68:   countcell = 0;
 69:   countconn = 0;
 70:   for (c = cStart; c < cEnd; ++c) {
 71:     PetscInt nverts,dof = 0,celltype,startoffset,nC=0;

 73:     if (hasLabel) {
 74:       PetscInt value;

 76:       DMGetLabelValue(dm, "vtk", c, &value);
 77:       if (value != 1) continue;
 78:     }
 79:     startoffset = countconn;
 80:     if (localized) {
 81:       PetscSectionGetDof(coordSection, c, &dof);
 82:     }
 83:     if (!dof) {
 84:       PetscInt *closure = NULL;
 85:       PetscInt  closureSize;

 87:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
 88:       for (v = 0; v < closureSize*2; v += 2) {
 89:         if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
 90:           if (!localized) conn[countconn++] = closure[v] - vStart;
 91:           else conn[countconn++] = startoffset + nC;
 92:           ++nC;
 93:         }
 94:       }
 95:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
 96:     } else {
 97:       for (nC = 0; nC < dof/dim; nC++) conn[countconn++] = startoffset + nC;
 98:     }
 99:     DMPlexInvertCell(dim, nC, &conn[countconn-nC]);

101:     offsets[countcell] = countconn;

103:     nverts = countconn - startoffset;
104:     DMPlexVTKGetCellType_Internal(dm,dim,nverts,&celltype);

106:     types[countcell] = celltype;
107:     countcell++;
108:   }
109:   if (countcell != piece->ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent cell count");
110:   if (countconn != piece->nconn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent connectivity count");
111:   *oconn    = conn;
112:   *ooffsets = offsets;
113:   *otypes   = types;
114:   return(0);
115: }

117: /*
118:   Write all fields that have been provided to the viewer
119:   Multi-block XML format with binary appended data.
120: */
121: PetscErrorCode DMPlexVTKWriteAll_VTU(DM dm,PetscViewer viewer)
122: {
123:   MPI_Comm                 comm;
124:   PetscSection             coordSection;
125:   PetscViewer_VTK          *vtk = (PetscViewer_VTK*)viewer->data;
126:   PetscViewerVTKObjectLink link;
127:   FILE                     *fp;
128:   PetscMPIInt              rank,size,tag;
129:   PetscErrorCode           ierr;
130:   PetscInt                 dimEmbed,cellHeight,cStart,cEnd,vStart,vEnd,cMax,numLabelCells,hasLabel,c,v,r,i;
131:   PetscBool                localized;
132:   PieceInfo                piece,*gpiece = NULL;
133:   void                     *buffer = NULL;

136:   PetscObjectGetComm((PetscObject)dm,&comm);
137: #if defined(PETSC_USE_COMPLEX)
138:   SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Complex values not supported");
139: #endif
140:   MPI_Comm_size(comm,&size);
141:   MPI_Comm_rank(comm,&rank);
142:   tag  = ((PetscObject)viewer)->tag;

144:   PetscFOpen(comm,vtk->filename,"wb",&fp);
145:   PetscFPrintf(comm,fp,"<?xml version=\"1.0\"?>\n");
146: #if defined(PETSC_WORDS_BIGENDIAN)
147:   PetscFPrintf(comm,fp,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"BigEndian\">\n");
148: #else
149:   PetscFPrintf(comm,fp,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n");
150: #endif
151:   PetscFPrintf(comm,fp,"  <UnstructuredGrid>\n");

153:   DMGetCoordinateDim(dm, &dimEmbed);
154:   DMPlexGetVTKCellHeight(dm, &cellHeight);
155:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
156:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
157:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
158:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
159:   DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
160:   DMGetCoordinatesLocalized(dm, &localized);
161:   DMGetCoordinateSection(dm, &coordSection);

163:   hasLabel        = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
164:   piece.nvertices = 0;
165:   piece.ncells    = 0;
166:   piece.nconn     = 0;
167:   if (!localized) piece.nvertices = vEnd - vStart;
168:   for (c = cStart; c < cEnd; ++c) {
169:     PetscInt dof = 0;
170:     if (hasLabel) {
171:       PetscInt value;

173:       DMGetLabelValue(dm, "vtk", c, &value);
174:       if (value != 1) continue;
175:     }
176:     if (localized) {
177:       PetscSectionGetDof(coordSection, c, &dof);
178:     }
179:     if (!dof) {
180:       PetscInt *closure = NULL;
181:       PetscInt closureSize;

183:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
184:       for (v = 0; v < closureSize*2; v += 2) {
185:         if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
186:           piece.nconn++;
187:           if (localized) piece.nvertices++;
188:         }
189:       }
190:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
191:     } else {
192:       piece.nvertices += dof/dimEmbed;
193:       piece.nconn     += dof/dimEmbed;
194:     }
195:     piece.ncells++;
196:   }
197:   if (!rank) {PetscMalloc1(size,&gpiece);}
198:   MPI_Gather((PetscInt*)&piece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,(PetscInt*)gpiece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,0,comm);

200:   /*
201:    * Write file header
202:    */
203:   if (!rank) {
204:     PetscInt boffset = 0;

206:     for (r=0; r<size; r++) {
207:       PetscFPrintf(PETSC_COMM_SELF,fp,"    <Piece NumberOfPoints=\"%D\" NumberOfCells=\"%D\">\n",gpiece[r].nvertices,gpiece[r].ncells);
208:       /* Coordinate positions */
209:       PetscFPrintf(PETSC_COMM_SELF,fp,"      <Points>\n");
210:       PetscFPrintf(PETSC_COMM_SELF,fp,"        <DataArray type=\"%s\" Name=\"Position\" NumberOfComponents=\"3\" format=\"appended\" offset=\"%D\" />\n",precision,boffset);
211:       boffset += gpiece[r].nvertices*3*sizeof(PetscScalar) + sizeof(int);
212:       PetscFPrintf(PETSC_COMM_SELF,fp,"      </Points>\n");
213:       /* Cell connectivity */
214:       PetscFPrintf(PETSC_COMM_SELF,fp,"      <Cells>\n");
215:       PetscFPrintf(PETSC_COMM_SELF,fp,"        <DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
216:       boffset += gpiece[r].nconn*sizeof(PetscInt) + sizeof(int);
217:       PetscFPrintf(PETSC_COMM_SELF,fp,"        <DataArray type=\"Int32\" Name=\"offsets\"      NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
218:       boffset += gpiece[r].ncells*sizeof(PetscInt) + sizeof(int);
219:       PetscFPrintf(PETSC_COMM_SELF,fp,"        <DataArray type=\"UInt8\" Name=\"types\"        NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
220:       boffset += gpiece[r].ncells*sizeof(unsigned char) + sizeof(int);
221:       PetscFPrintf(PETSC_COMM_SELF,fp,"      </Cells>\n");

223:       /*
224:        * Cell Data headers
225:        */
226:       PetscFPrintf(PETSC_COMM_SELF,fp,"      <CellData>\n");
227:       PetscFPrintf(PETSC_COMM_SELF,fp,"        <DataArray type=\"Int32\" Name=\"Rank\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
228:       boffset += gpiece[r].ncells*sizeof(int) + sizeof(int);
229:       /* all the vectors */
230:       for (link=vtk->link; link; link=link->next) {
231:         Vec        X = (Vec)link->vec;
232:         PetscInt   bs,nfields,field;
233:         const char *vecname = "";
234:         if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
235:         if (((PetscObject)X)->name || link != vtk->link) { /* If the object is already named, use it. If it is past the first link, name it to disambiguate. */
236:           PetscObjectGetName((PetscObject)X,&vecname);
237:         }
238:         PetscSectionGetDof(dm->defaultSection,cStart,&bs);
239:         PetscSectionGetNumFields(dm->defaultSection,&nfields);
240:         for (field=0,i=0; field<(nfields?nfields:1); field++) {
241:           PetscInt     fbs,j;
242:           PetscFV      fv = NULL;
243:           PetscObject  f;
244:           PetscClassId fClass;
245:           const char *fieldname = NULL;
246:           char       buf[256];
247:           if (nfields) {        /* We have user-defined fields/components */
248:             PetscSectionGetFieldDof(dm->defaultSection,cStart,field,&fbs);
249:             PetscSectionGetFieldName(dm->defaultSection,field,&fieldname);
250:           } else fbs = bs;      /* Say we have one field with 'bs' components */
251:           DMGetField(dm,field,&f);
252:           PetscObjectGetClassId(f,&fClass);
253:           if (fClass == PETSCFV_CLASSID) {
254:             fv = (PetscFV) f;
255:           }
256:           if (!fieldname) {
257:             PetscSNPrintf(buf,sizeof(buf),"CellField%D",field);
258:             fieldname = buf;
259:           }
260:           for (j=0; j<fbs; j++) {
261:             const char *compName = NULL;
262:             if (fv) {
263:               PetscFVGetComponentName(fv,j,&compName);
264:             }
265:             if (compName) {
266:               PetscFPrintf(comm,fp,"        <DataArray type=\"%s\" Name=\"%s%s.%s\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,compName,boffset);
267:             }
268:             else {
269:               PetscFPrintf(comm,fp,"        <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
270:             }
271:             boffset += gpiece[r].ncells*sizeof(PetscScalar) + sizeof(int);
272:             i++;
273:           }
274:         }
275:         if (i != bs) SETERRQ2(comm,PETSC_ERR_PLIB,"Total number of field components %D != block size %D",i,bs);
276:       }
277:       PetscFPrintf(PETSC_COMM_SELF,fp,"      </CellData>\n");

279:       /*
280:        * Point Data headers
281:        */
282:       PetscFPrintf(PETSC_COMM_SELF,fp,"      <PointData>\n");
283:       for (link=vtk->link; link; link=link->next) {
284:         Vec        X = (Vec)link->vec;
285:         PetscInt   bs,nfields,field;
286:         const char *vecname = "";
287:         if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
288:         if (((PetscObject)X)->name || link != vtk->link) { /* If the object is already named, use it. If it is past the first link, name it to disambiguate. */
289:           PetscObjectGetName((PetscObject)X,&vecname);
290:         }
291:         PetscSectionGetDof(dm->defaultSection,vStart,&bs);
292:         PetscSectionGetNumFields(dm->defaultSection,&nfields);
293:         for (field=0,i=0; field<(nfields?nfields:1); field++) {
294:           PetscInt   fbs,j;
295:           const char *fieldname = NULL;
296:           char       buf[256];
297:           if (nfields) {        /* We have user-defined fields/components */
298:             PetscSectionGetFieldDof(dm->defaultSection,vStart,field,&fbs);
299:             PetscSectionGetFieldName(dm->defaultSection,field,&fieldname);
300:           } else fbs = bs;      /* Say we have one field with 'bs' components */
301:           if (!fieldname) {
302:             PetscSNPrintf(buf,sizeof(buf),"PointField%D",field);
303:             fieldname = buf;
304:           }
305:           for (j=0; j<fbs; j++) {
306:             PetscFPrintf(comm,fp,"        <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
307:             boffset += gpiece[r].nvertices*sizeof(PetscScalar) + sizeof(int);
308:           }
309:         }
310:       }
311:       PetscFPrintf(PETSC_COMM_SELF,fp,"      </PointData>\n");

313:       PetscFPrintf(PETSC_COMM_SELF,fp,"    </Piece>\n");
314:     }
315:   }

317:   PetscFPrintf(comm,fp,"  </UnstructuredGrid>\n");
318:   PetscFPrintf(comm,fp,"  <AppendedData encoding=\"raw\">\n");
319:   PetscFPrintf(comm,fp,"_");

321:   if (!rank) {
322:     PetscInt maxsize = 0;
323:     for (r=0; r<size; r++) {
324:       maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nvertices*3*sizeof(PetscScalar)));
325:       maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].ncells*sizeof(PetscScalar)));
326:       maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nconn*sizeof(PetscVTKInt)));
327:     }
328:     PetscMalloc(maxsize,&buffer);
329:   }
330:   for (r=0; r<size; r++) {
331:     if (r == rank) {
332:       PetscInt nsend;
333:       {                         /* Position */
334:         const PetscScalar *x;
335:         PetscScalar       *y = NULL;
336:         Vec               coords;

338:         DMGetCoordinatesLocal(dm,&coords);
339:         VecGetArrayRead(coords,&x);
340:         if (dimEmbed != 3 || localized) {
341:           PetscMalloc1(piece.nvertices*3,&y);
342:           if (localized) {
343:             PetscInt cnt;
344:             for (c=cStart,cnt=0; c<cEnd; c++) {
345:               PetscInt off, dof;

347:               PetscSectionGetDof(coordSection, c, &dof);
348:               if (!dof) {
349:                 PetscInt *closure = NULL;
350:                 PetscInt closureSize;

352:                 DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
353:                 for (v = 0; v < closureSize*2; v += 2) {
354:                   if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
355:                     PetscSectionGetOffset(coordSection, closure[v], &off);
356:                     if (dimEmbed != 3) {
357:                       y[cnt*3+0] = x[off+0];
358:                       y[cnt*3+1] = (dimEmbed > 1) ? x[off+1] : 0.0;
359:                       y[cnt*3+2] = 0.0;
360:                     } else {
361:                       y[cnt*3+0] = x[off+0];
362:                       y[cnt*3+1] = x[off+1];
363:                       y[cnt*3+2] = x[off+2];
364:                     }
365:                     cnt++;
366:                   }
367:                 }
368:                 DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
369:               } else {
370:                 PetscSectionGetOffset(coordSection, c, &off);
371:                 if (dimEmbed != 3) {
372:                   for (i=0; i<dof/dimEmbed; i++) {
373:                     y[cnt*3+0] = x[off + i*dimEmbed + 0];
374:                     y[cnt*3+1] = (dimEmbed > 1) ? x[off + i*dimEmbed + 1] : 0.0;
375:                     y[cnt*3+2] = 0.0;
376:                     cnt++;
377:                   }
378:                 } else {
379:                   for (i=0; i<dof; i ++) {
380:                     y[cnt*3+i] = x[off + i];
381:                   }
382:                   cnt += dof/dimEmbed;
383:                 }
384:               }
385:             }
386:             if (cnt != piece.nvertices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
387:           } else {
388:             for (i=0; i<piece.nvertices; i++) {
389:               y[i*3+0] = x[i*dimEmbed+0];
390:               y[i*3+1] = (dimEmbed > 1) ? x[i*dimEmbed+1] : 0;
391:               y[i*3+2] = 0.0;
392:             }
393:           }
394:         }
395:         nsend = piece.nvertices*3;
396:         TransferWrite(viewer,fp,r,0,y ? y : x,buffer,nsend,MPIU_SCALAR,tag);
397:         PetscFree(y);
398:         VecRestoreArrayRead(coords,&x);
399:       }
400:       {                           /* Connectivity, offsets, types */
401:         PetscVTKInt  *connectivity = NULL, *offsets = NULL;
402:         PetscVTKType *types = NULL;
403:         DMPlexGetVTKConnectivity(dm,localized,&piece,&connectivity,&offsets,&types);
404:         TransferWrite(viewer,fp,r,0,connectivity,buffer,piece.nconn,MPI_INT,tag);
405:         TransferWrite(viewer,fp,r,0,offsets,buffer,piece.ncells,MPI_INT,tag);
406:         TransferWrite(viewer,fp,r,0,types,buffer,piece.ncells,MPI_CHAR,tag);
407:         PetscFree3(connectivity,offsets,types);
408:       }
409:       {                         /* Owners (cell data) */
410:         PetscVTKInt *owners;
411:         PetscMalloc1(piece.ncells,&owners);
412:         for (i=0; i<piece.ncells; i++) owners[i] = rank;
413:         TransferWrite(viewer,fp,r,0,owners,buffer,piece.ncells,MPI_INT,tag);
414:         PetscFree(owners);
415:       }
416:       /* Cell data */
417:       for (link=vtk->link; link; link=link->next) {
418:         Vec               X = (Vec)link->vec;
419:         const PetscScalar *x;
420:         PetscScalar       *y;
421:         PetscInt          bs;
422:         if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
423:         PetscSectionGetDof(dm->defaultSection,cStart,&bs);
424:         VecGetArrayRead(X,&x);
425:         PetscMalloc1(piece.ncells,&y);
426:         for (i=0; i<bs; i++) {
427:           PetscInt cnt;
428:           for (c=cStart,cnt=0; c<cEnd; c++) {
429:             PetscScalar *xpoint;
430:             if (hasLabel) {     /* Ignore some cells */
431:               PetscInt value;
432:               DMGetLabelValue(dm, "vtk", c, &value);
433:               if (value != 1) continue;
434:             }
435:             DMPlexPointLocalRead(dm,c,x,&xpoint);
436:             y[cnt++] = xpoint[i];
437:           }
438:           if (cnt != piece.ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
439:           TransferWrite(viewer,fp,r,0,y,buffer,piece.ncells,MPIU_SCALAR,tag);
440:         }
441:         PetscFree(y);
442:         VecRestoreArrayRead(X,&x);
443:       }

445:       for (link=vtk->link; link; link=link->next) {
446:         Vec               X = (Vec)link->vec;
447:         const PetscScalar *x;
448:         PetscScalar       *y;
449:         PetscInt          bs;
450:         if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
451:         PetscSectionGetDof(dm->defaultSection,vStart,&bs);
452:         VecGetArrayRead(X,&x);
453:         PetscMalloc1(piece.nvertices,&y);
454:         for (i=0; i<bs; i++) {
455:           PetscInt cnt;
456:           if (!localized) {
457:             for (v=vStart,cnt=0; v<vEnd; v++) {
458:               PetscScalar *xpoint;
459:               DMPlexPointLocalRead(dm,v,x,&xpoint);
460:               y[cnt++] = xpoint[i];
461:             }
462:           } else {
463:             for (c=cStart,cnt=0; c<cEnd; c++) {
464:               PetscInt *closure = NULL;
465:               PetscInt  closureSize, off;

467:               DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
468:               for (v = 0, off = 0; v < closureSize*2; v += 2) {
469:                 if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
470:                   PetscScalar *xpoint;

472:                   DMPlexPointLocalRead(dm,v,x,&xpoint);
473:                   y[cnt + off++] = xpoint[i];
474:                 }
475:               }
476:               DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
477:             }
478:           }
479:           if (cnt != piece.nvertices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
480:           TransferWrite(viewer,fp,r,0,y,buffer,piece.nvertices,MPIU_SCALAR,tag);
481:         }
482:         PetscFree(y);
483:         VecRestoreArrayRead(X,&x);
484:       }
485:     } else if (!rank) {
486:       TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices*3,MPIU_SCALAR,tag); /* positions */
487:       TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nconn,MPI_INT,tag); /* connectivity */
488:       TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_INT,tag); /* offsets */
489:       TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_CHAR,tag); /* types */
490:       TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_INT,tag); /* owner rank (cells) */
491:       /* all cell data */
492:       for (link=vtk->link; link; link=link->next) {
493:         PetscInt bs;
494:         if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
495:         PetscSectionGetDof(dm->defaultSection,cStart,&bs);
496:         for (i=0; i<bs; i++) {
497:           TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPIU_SCALAR,tag);
498:         }
499:       }
500:       /* all point data */
501:       for (link=vtk->link; link; link=link->next) {
502:         PetscInt bs;
503:         if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
504:         PetscSectionGetDof(dm->defaultSection,vStart,&bs);
505:         for (i=0; i<bs; i++) {
506:           TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices,MPIU_SCALAR,tag);
507:         }
508:       }
509:     }
510:   }
511:   PetscFree(gpiece);
512:   PetscFree(buffer);
513:   PetscFPrintf(comm,fp,"\n  </AppendedData>\n");
514:   PetscFPrintf(comm,fp,"</VTKFile>\n");
515:   PetscFClose(comm,fp);
516:   return(0);
517: }