Actual source code: plexvtu.c
petsc-3.12.5 2020-03-29
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,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: DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
64: hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
66: countcell = 0;
67: countconn = 0;
68: for (c = cStart; c < cEnd; ++c) {
69: PetscInt nverts,dof = 0,celltype,startoffset,nC=0;
71: if (hasLabel) {
72: PetscInt value;
74: DMGetLabelValue(dm, "vtk", c, &value);
75: if (value != 1) continue;
76: }
77: startoffset = countconn;
78: if (localized) {
79: PetscSectionGetDof(coordSection, c, &dof);
80: }
81: if (!dof) {
82: PetscInt *closure = NULL;
83: PetscInt closureSize;
85: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
86: for (v = 0; v < closureSize*2; v += 2) {
87: if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
88: if (!localized) conn[countconn++] = closure[v] - vStart;
89: else conn[countconn++] = startoffset + nC;
90: ++nC;
91: }
92: }
93: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
94: } else {
95: for (nC = 0; nC < dof/dim; nC++) conn[countconn++] = startoffset + nC;
96: }
97: DMPlexInvertCell(dim, nC, &conn[countconn-nC]);
99: offsets[countcell] = countconn;
101: nverts = countconn - startoffset;
102: DMPlexVTKGetCellType_Internal(dm,dim,nverts,&celltype);
104: types[countcell] = celltype;
105: countcell++;
106: }
107: if (countcell != piece->ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent cell count");
108: if (countconn != piece->nconn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent connectivity count");
109: *oconn = conn;
110: *ooffsets = offsets;
111: *otypes = types;
112: return(0);
113: }
115: /*
116: Write all fields that have been provided to the viewer
117: Multi-block XML format with binary appended data.
118: */
119: PetscErrorCode DMPlexVTKWriteAll_VTU(DM dm,PetscViewer viewer)
120: {
121: MPI_Comm comm;
122: PetscSection coordSection;
123: PetscViewer_VTK *vtk = (PetscViewer_VTK*)viewer->data;
124: PetscViewerVTKObjectLink link;
125: FILE *fp;
126: PetscMPIInt rank,size,tag;
127: PetscErrorCode ierr;
128: PetscInt dimEmbed,cellHeight,cStart,cEnd,vStart,vEnd,numLabelCells,hasLabel,c,v,r,i;
129: PetscBool localized;
130: PieceInfo piece,*gpiece = NULL;
131: void *buffer = NULL;
132: const char *byte_order = PetscBinaryBigEndian() ? "BigEndian" : "LittleEndian";
135: PetscObjectGetComm((PetscObject)dm,&comm);
136: #if defined(PETSC_USE_COMPLEX)
137: SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Complex values not supported");
138: #endif
139: MPI_Comm_size(comm,&size);
140: MPI_Comm_rank(comm,&rank);
141: tag = ((PetscObject)viewer)->tag;
143: PetscFOpen(comm,vtk->filename,"wb",&fp);
144: PetscFPrintf(comm,fp,"<?xml version=\"1.0\"?>\n");
145: PetscFPrintf(comm,fp,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"%s\">\n", byte_order);
146: PetscFPrintf(comm,fp," <UnstructuredGrid>\n");
148: DMGetCoordinateDim(dm, &dimEmbed);
149: DMPlexGetVTKCellHeight(dm, &cellHeight);
150: DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
151: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
152: DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
153: DMGetCoordinatesLocalized(dm, &localized);
154: DMGetCoordinateSection(dm, &coordSection);
156: hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
157: piece.nvertices = 0;
158: piece.ncells = 0;
159: piece.nconn = 0;
160: if (!localized) piece.nvertices = vEnd - vStart;
161: for (c = cStart; c < cEnd; ++c) {
162: PetscInt dof = 0;
163: if (hasLabel) {
164: PetscInt value;
166: DMGetLabelValue(dm, "vtk", c, &value);
167: if (value != 1) continue;
168: }
169: if (localized) {
170: PetscSectionGetDof(coordSection, c, &dof);
171: }
172: if (!dof) {
173: PetscInt *closure = NULL;
174: PetscInt closureSize;
176: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
177: for (v = 0; v < closureSize*2; v += 2) {
178: if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
179: piece.nconn++;
180: if (localized) piece.nvertices++;
181: }
182: }
183: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
184: } else {
185: piece.nvertices += dof/dimEmbed;
186: piece.nconn += dof/dimEmbed;
187: }
188: piece.ncells++;
189: }
190: if (!rank) {PetscMalloc1(size,&gpiece);}
191: MPI_Gather((PetscInt*)&piece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,(PetscInt*)gpiece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,0,comm);
193: /*
194: * Write file header
195: */
196: if (!rank) {
197: PetscInt boffset = 0;
199: for (r=0; r<size; r++) {
200: PetscFPrintf(PETSC_COMM_SELF,fp," <Piece NumberOfPoints=\"%D\" NumberOfCells=\"%D\">\n",gpiece[r].nvertices,gpiece[r].ncells);
201: /* Coordinate positions */
202: PetscFPrintf(PETSC_COMM_SELF,fp," <Points>\n");
203: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"%s\" Name=\"Position\" NumberOfComponents=\"3\" format=\"appended\" offset=\"%D\" />\n",precision,boffset);
204: boffset += gpiece[r].nvertices*3*sizeof(PetscScalar) + sizeof(int);
205: PetscFPrintf(PETSC_COMM_SELF,fp," </Points>\n");
206: /* Cell connectivity */
207: PetscFPrintf(PETSC_COMM_SELF,fp," <Cells>\n");
208: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
209: boffset += gpiece[r].nconn*sizeof(PetscInt) + sizeof(int);
210: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
211: boffset += gpiece[r].ncells*sizeof(PetscInt) + sizeof(int);
212: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"UInt8\" Name=\"types\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
213: boffset += gpiece[r].ncells*sizeof(unsigned char) + sizeof(int);
214: PetscFPrintf(PETSC_COMM_SELF,fp," </Cells>\n");
216: /*
217: * Cell Data headers
218: */
219: PetscFPrintf(PETSC_COMM_SELF,fp," <CellData>\n");
220: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"Rank\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
221: boffset += gpiece[r].ncells*sizeof(int) + sizeof(int);
222: /* all the vectors */
223: for (link=vtk->link; link; link=link->next) {
224: Vec X = (Vec)link->vec;
225: PetscInt bs,nfields,field;
226: const char *vecname = "";
227: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
228: 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. */
229: PetscObjectGetName((PetscObject)X,&vecname);
230: }
231: PetscSectionGetDof(dm->localSection,cStart,&bs);
232: PetscSectionGetNumFields(dm->localSection,&nfields);
233: for (field=0,i=0; field<(nfields?nfields:1); field++) {
234: PetscInt fbs,j;
235: PetscFV fv = NULL;
236: PetscObject f;
237: PetscClassId fClass;
238: const char *fieldname = NULL;
239: char buf[256];
240: if (nfields) { /* We have user-defined fields/components */
241: PetscSectionGetFieldDof(dm->localSection,cStart,field,&fbs);
242: PetscSectionGetFieldName(dm->localSection,field,&fieldname);
243: } else fbs = bs; /* Say we have one field with 'bs' components */
244: DMGetField(dm,field,NULL,&f);
245: PetscObjectGetClassId(f,&fClass);
246: if (fClass == PETSCFV_CLASSID) {
247: fv = (PetscFV) f;
248: }
249: if (!fieldname) {
250: PetscSNPrintf(buf,sizeof(buf),"CellField%D",field);
251: fieldname = buf;
252: }
253: for (j=0; j<fbs; j++) {
254: const char *compName = NULL;
255: if (fv) {
256: PetscFVGetComponentName(fv,j,&compName);
257: }
258: if (compName) {
259: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%s\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,compName,boffset);
260: }
261: else {
262: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
263: }
264: boffset += gpiece[r].ncells*sizeof(PetscScalar) + sizeof(int);
265: i++;
266: }
267: }
268: if (i != bs) SETERRQ2(comm,PETSC_ERR_PLIB,"Total number of field components %D != block size %D",i,bs);
269: }
270: PetscFPrintf(PETSC_COMM_SELF,fp," </CellData>\n");
272: /*
273: * Point Data headers
274: */
275: PetscFPrintf(PETSC_COMM_SELF,fp," <PointData>\n");
276: for (link=vtk->link; link; link=link->next) {
277: Vec X = (Vec)link->vec;
278: PetscInt bs,nfields,field;
279: const char *vecname = "";
280: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
281: 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. */
282: PetscObjectGetName((PetscObject)X,&vecname);
283: }
284: PetscSectionGetDof(dm->localSection,vStart,&bs);
285: PetscSectionGetNumFields(dm->localSection,&nfields);
286: for (field=0,i=0; field<(nfields?nfields:1); field++) {
287: PetscInt fbs,j;
288: const char *fieldname = NULL;
289: char buf[256];
290: if (nfields) { /* We have user-defined fields/components */
291: PetscSectionGetFieldDof(dm->localSection,vStart,field,&fbs);
292: PetscSectionGetFieldName(dm->localSection,field,&fieldname);
293: } else fbs = bs; /* Say we have one field with 'bs' components */
294: if (!fieldname) {
295: PetscSNPrintf(buf,sizeof(buf),"PointField%D",field);
296: fieldname = buf;
297: }
298: for (j=0; j<fbs; j++) {
299: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
300: boffset += gpiece[r].nvertices*sizeof(PetscScalar) + sizeof(int);
301: }
302: }
303: }
304: PetscFPrintf(PETSC_COMM_SELF,fp," </PointData>\n");
306: PetscFPrintf(PETSC_COMM_SELF,fp," </Piece>\n");
307: }
308: }
310: PetscFPrintf(comm,fp," </UnstructuredGrid>\n");
311: PetscFPrintf(comm,fp," <AppendedData encoding=\"raw\">\n");
312: PetscFPrintf(comm,fp,"_");
314: if (!rank) {
315: PetscInt maxsize = 0;
316: for (r=0; r<size; r++) {
317: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nvertices*3*sizeof(PetscScalar)));
318: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].ncells*sizeof(PetscScalar)));
319: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nconn*sizeof(PetscVTKInt)));
320: }
321: PetscMalloc(maxsize,&buffer);
322: }
323: for (r=0; r<size; r++) {
324: if (r == rank) {
325: PetscInt nsend;
326: { /* Position */
327: const PetscScalar *x;
328: PetscScalar *y = NULL;
329: Vec coords;
331: DMGetCoordinatesLocal(dm,&coords);
332: VecGetArrayRead(coords,&x);
333: if (dimEmbed != 3 || localized) {
334: PetscMalloc1(piece.nvertices*3,&y);
335: if (localized) {
336: PetscInt cnt;
337: for (c=cStart,cnt=0; c<cEnd; c++) {
338: PetscInt off, dof;
340: PetscSectionGetDof(coordSection, c, &dof);
341: if (!dof) {
342: PetscInt *closure = NULL;
343: PetscInt closureSize;
345: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
346: for (v = 0; v < closureSize*2; v += 2) {
347: if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
348: PetscSectionGetOffset(coordSection, closure[v], &off);
349: if (dimEmbed != 3) {
350: y[cnt*3+0] = x[off+0];
351: y[cnt*3+1] = (dimEmbed > 1) ? x[off+1] : 0.0;
352: y[cnt*3+2] = 0.0;
353: } else {
354: y[cnt*3+0] = x[off+0];
355: y[cnt*3+1] = x[off+1];
356: y[cnt*3+2] = x[off+2];
357: }
358: cnt++;
359: }
360: }
361: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
362: } else {
363: PetscSectionGetOffset(coordSection, c, &off);
364: if (dimEmbed != 3) {
365: for (i=0; i<dof/dimEmbed; i++) {
366: y[cnt*3+0] = x[off + i*dimEmbed + 0];
367: y[cnt*3+1] = (dimEmbed > 1) ? x[off + i*dimEmbed + 1] : 0.0;
368: y[cnt*3+2] = 0.0;
369: cnt++;
370: }
371: } else {
372: for (i=0; i<dof; i ++) {
373: y[cnt*3+i] = x[off + i];
374: }
375: cnt += dof/dimEmbed;
376: }
377: }
378: }
379: if (cnt != piece.nvertices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
380: } else {
381: for (i=0; i<piece.nvertices; i++) {
382: y[i*3+0] = x[i*dimEmbed+0];
383: y[i*3+1] = (dimEmbed > 1) ? x[i*dimEmbed+1] : 0;
384: y[i*3+2] = 0.0;
385: }
386: }
387: }
388: nsend = piece.nvertices*3;
389: TransferWrite(viewer,fp,r,0,y ? y : x,buffer,nsend,MPIU_SCALAR,tag);
390: PetscFree(y);
391: VecRestoreArrayRead(coords,&x);
392: }
393: { /* Connectivity, offsets, types */
394: PetscVTKInt *connectivity = NULL, *offsets = NULL;
395: PetscVTKType *types = NULL;
396: DMPlexGetVTKConnectivity(dm,localized,&piece,&connectivity,&offsets,&types);
397: TransferWrite(viewer,fp,r,0,connectivity,buffer,piece.nconn,MPI_INT,tag);
398: TransferWrite(viewer,fp,r,0,offsets,buffer,piece.ncells,MPI_INT,tag);
399: TransferWrite(viewer,fp,r,0,types,buffer,piece.ncells,MPI_CHAR,tag);
400: PetscFree3(connectivity,offsets,types);
401: }
402: { /* Owners (cell data) */
403: PetscVTKInt *owners;
404: PetscMalloc1(piece.ncells,&owners);
405: for (i=0; i<piece.ncells; i++) owners[i] = rank;
406: TransferWrite(viewer,fp,r,0,owners,buffer,piece.ncells,MPI_INT,tag);
407: PetscFree(owners);
408: }
409: /* Cell data */
410: for (link=vtk->link; link; link=link->next) {
411: Vec X = (Vec)link->vec;
412: const PetscScalar *x;
413: PetscScalar *y;
414: PetscInt bs;
415: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
416: PetscSectionGetDof(dm->localSection,cStart,&bs);
417: VecGetArrayRead(X,&x);
418: PetscMalloc1(piece.ncells,&y);
419: for (i=0; i<bs; i++) {
420: PetscInt cnt;
421: for (c=cStart,cnt=0; c<cEnd; c++) {
422: PetscScalar *xpoint;
423: if (hasLabel) { /* Ignore some cells */
424: PetscInt value;
425: DMGetLabelValue(dm, "vtk", c, &value);
426: if (value != 1) continue;
427: }
428: DMPlexPointLocalRead(dm,c,x,&xpoint);
429: y[cnt++] = xpoint[i];
430: }
431: if (cnt != piece.ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
432: TransferWrite(viewer,fp,r,0,y,buffer,piece.ncells,MPIU_SCALAR,tag);
433: }
434: PetscFree(y);
435: VecRestoreArrayRead(X,&x);
436: }
438: for (link=vtk->link; link; link=link->next) {
439: Vec X = (Vec)link->vec;
440: const PetscScalar *x;
441: PetscScalar *y;
442: PetscInt bs;
443: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
444: PetscSectionGetDof(dm->localSection,vStart,&bs);
445: VecGetArrayRead(X,&x);
446: PetscMalloc1(piece.nvertices,&y);
447: for (i=0; i<bs; i++) {
448: PetscInt cnt;
449: if (!localized) {
450: for (v=vStart,cnt=0; v<vEnd; v++) {
451: PetscScalar *xpoint;
452: DMPlexPointLocalRead(dm,v,x,&xpoint);
453: y[cnt++] = xpoint[i];
454: }
455: } else {
456: for (c=cStart,cnt=0; c<cEnd; c++) {
457: PetscInt *closure = NULL;
458: PetscInt closureSize, off;
460: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
461: for (v = 0, off = 0; v < closureSize*2; v += 2) {
462: if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
463: PetscScalar *xpoint;
465: DMPlexPointLocalRead(dm,closure[v],x,&xpoint);
466: y[cnt + off++] = xpoint[i];
467: }
468: }
469: cnt += off;
470: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
471: }
472: }
473: if (cnt != piece.nvertices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
474: TransferWrite(viewer,fp,r,0,y,buffer,piece.nvertices,MPIU_SCALAR,tag);
475: }
476: PetscFree(y);
477: VecRestoreArrayRead(X,&x);
478: }
479: } else if (!rank) {
480: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices*3,MPIU_SCALAR,tag); /* positions */
481: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nconn,MPI_INT,tag); /* connectivity */
482: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_INT,tag); /* offsets */
483: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_CHAR,tag); /* types */
484: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPI_INT,tag); /* owner rank (cells) */
485: /* all cell data */
486: for (link=vtk->link; link; link=link->next) {
487: PetscInt bs;
488: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
489: PetscSectionGetDof(dm->localSection,cStart,&bs);
490: for (i=0; i<bs; i++) {
491: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,MPIU_SCALAR,tag);
492: }
493: }
494: /* all point data */
495: for (link=vtk->link; link; link=link->next) {
496: PetscInt bs;
497: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
498: PetscSectionGetDof(dm->localSection,vStart,&bs);
499: for (i=0; i<bs; i++) {
500: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices,MPIU_SCALAR,tag);
501: }
502: }
503: }
504: }
505: PetscFree(gpiece);
506: PetscFree(buffer);
507: PetscFPrintf(comm,fp,"\n </AppendedData>\n");
508: PetscFPrintf(comm,fp,"</VTKFile>\n");
509: PetscFClose(comm,fp);
510: return(0);
511: }