Actual source code: plexvtu.c
petsc-3.7.7 2017-09-25
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
20: static PetscErrorCode TransferWrite(PetscViewer viewer,FILE *fp,PetscMPIInt srank,PetscMPIInt root,const void *send,void *recv,PetscMPIInt count,PetscDataType datatype,PetscMPIInt tag)
21: {
22: PetscMPIInt rank;
24: MPI_Comm comm;
25: MPI_Datatype mpidatatype;
28: PetscObjectGetComm((PetscObject)viewer,&comm);
29: MPI_Comm_rank(comm,&rank);
30: PetscDataTypeToMPIDataType(datatype,&mpidatatype);
32: if (rank == srank && rank != root) {
33: MPI_Send((void*)send,count,mpidatatype,root,tag,comm);
34: } else if (rank == root) {
35: const void *buffer;
36: if (root == srank) { /* self */
37: buffer = send;
38: } else {
39: MPI_Status status;
40: PetscMPIInt nrecv;
41: MPI_Recv(recv,count,mpidatatype,srank,tag,comm,&status);
42: MPI_Get_count(&status,mpidatatype,&nrecv);
43: if (count != nrecv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Array size mismatch");
44: buffer = recv;
45: }
46: PetscViewerVTKFWrite(viewer,fp,buffer,count,datatype);
47: }
48: return(0);
49: }
53: static PetscErrorCode DMPlexGetVTKConnectivity(DM dm,PieceInfo *piece,PetscVTKInt **oconn,PetscVTKInt **ooffsets,PetscVTKType **otypes)
54: {
56: PetscVTKInt *conn,*offsets;
57: PetscVTKType *types;
58: PetscInt dim,vStart,vEnd,cStart,cEnd,pStart,pEnd,cellHeight,cMax,numLabelCells,hasLabel,c,v,countcell,countconn;
61: PetscMalloc3(piece->nconn,&conn,piece->ncells,&offsets,piece->ncells,&types);
63: DMGetDimension(dm,&dim);
64: DMPlexGetChart(dm,&pStart,&pEnd);
65: DMPlexGetVTKCellHeight(dm, &cellHeight);
66: DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
67: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
68: DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
69: if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
70: DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
71: hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
73: countcell = 0;
74: countconn = 0;
75: for (c = cStart; c < cEnd; ++c) {
76: PetscInt *closure = NULL;
77: PetscInt closureSize,nverts,celltype,startoffset,nC=0;
79: if (hasLabel) {
80: PetscInt value;
82: DMGetLabelValue(dm, "vtk", c, &value);
83: if (value != 1) continue;
84: }
85: startoffset = countconn;
86: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
87: for (v = 0; v < closureSize*2; v += 2) {
88: if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
89: conn[countconn++] = closure[v] - vStart;
90: ++nC;
91: }
92: }
93: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
94: DMPlexInvertCell(dim, nC, &conn[countconn-nC]);
96: offsets[countcell] = countconn;
98: nverts = countconn - startoffset;
99: DMPlexVTKGetCellType(dm,dim,nverts,&celltype);
101: types[countcell] = celltype;
102: countcell++;
103: }
104: if (countcell != piece->ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent cell count");
105: if (countconn != piece->nconn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent connectivity count");
106: *oconn = conn;
107: *ooffsets = offsets;
108: *otypes = types;
109: return(0);
110: }
114: /*
115: Write all fields that have been provided to the viewer
116: Multi-block XML format with binary appended data.
117: */
118: PetscErrorCode DMPlexVTKWriteAll_VTU(DM dm,PetscViewer viewer)
119: {
120: MPI_Comm comm;
121: PetscViewer_VTK *vtk = (PetscViewer_VTK*)viewer->data;
122: PetscViewerVTKObjectLink link;
123: FILE *fp;
124: PetscMPIInt rank,size,tag;
125: PetscErrorCode ierr;
126: PetscInt dimEmbed,cellHeight,cStart,cEnd,vStart,vEnd,cMax,numLabelCells,hasLabel,c,v,r,i;
127: PieceInfo piece,*gpiece = NULL;
128: void *buffer = NULL;
131: PetscObjectGetComm((PetscObject)dm,&comm);
132: #if defined(PETSC_USE_COMPLEX)
133: SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Complex values not supported");
134: #endif
135: MPI_Comm_size(comm,&size);
136: MPI_Comm_rank(comm,&rank);
137: tag = ((PetscObject)viewer)->tag;
139: PetscFOpen(comm,vtk->filename,"wb",&fp);
140: PetscFPrintf(comm,fp,"<?xml version=\"1.0\"?>\n");
141: #if defined(PETSC_WORDS_BIGENDIAN)
142: PetscFPrintf(comm,fp,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"BigEndian\">\n");
143: #else
144: PetscFPrintf(comm,fp,"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n");
145: #endif
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: DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
153: if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
154: DMGetStratumSize(dm, "vtk", 1, &numLabelCells);
156: hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
157: piece.nvertices = vEnd - vStart;
158: piece.ncells = 0;
159: piece.nconn = 0;
160: for (c = cStart; c < cEnd; ++c) {
161: PetscInt *closure = NULL;
162: PetscInt closureSize;
164: if (hasLabel) {
165: PetscInt value;
167: DMGetLabelValue(dm, "vtk", c, &value);
168: if (value != 1) continue;
169: }
170: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
171: for (v = 0; v < closureSize*2; v += 2) {
172: if ((closure[v] >= vStart) && (closure[v] < vEnd)) piece.nconn++;
173: }
174: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
175: piece.ncells++;
176: }
177: if (!rank) {PetscMalloc1(size,&gpiece);}
178: MPI_Gather((PetscInt*)&piece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,(PetscInt*)gpiece,sizeof(piece)/sizeof(PetscInt),MPIU_INT,0,comm);
180: /*
181: * Write file header
182: */
183: if (!rank) {
184: PetscInt boffset = 0;
186: for (r=0; r<size; r++) {
187: PetscFPrintf(PETSC_COMM_SELF,fp," <Piece NumberOfPoints=\"%D\" NumberOfCells=\"%D\">\n",gpiece[r].nvertices,gpiece[r].ncells);
188: /* Coordinate positions */
189: PetscFPrintf(PETSC_COMM_SELF,fp," <Points>\n");
190: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"%s\" Name=\"Position\" NumberOfComponents=\"3\" format=\"appended\" offset=\"%D\" />\n",precision,boffset);
191: boffset += gpiece[r].nvertices*3*sizeof(PetscScalar) + sizeof(int);
192: PetscFPrintf(PETSC_COMM_SELF,fp," </Points>\n");
193: /* Cell connectivity */
194: PetscFPrintf(PETSC_COMM_SELF,fp," <Cells>\n");
195: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
196: boffset += gpiece[r].nconn*sizeof(PetscInt) + sizeof(int);
197: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
198: boffset += gpiece[r].ncells*sizeof(PetscInt) + sizeof(int);
199: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"UInt8\" Name=\"types\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
200: boffset += gpiece[r].ncells*sizeof(unsigned char) + sizeof(int);
201: PetscFPrintf(PETSC_COMM_SELF,fp," </Cells>\n");
203: /*
204: * Cell Data headers
205: */
206: PetscFPrintf(PETSC_COMM_SELF,fp," <CellData>\n");
207: PetscFPrintf(PETSC_COMM_SELF,fp," <DataArray type=\"Int32\" Name=\"Rank\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",boffset);
208: boffset += gpiece[r].ncells*sizeof(int) + sizeof(int);
209: /* all the vectors */
210: for (link=vtk->link; link; link=link->next) {
211: Vec X = (Vec)link->vec;
212: PetscInt bs,nfields,field;
213: const char *vecname = "";
214: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
215: 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. */
216: PetscObjectGetName((PetscObject)X,&vecname);
217: }
218: PetscSectionGetDof(dm->defaultSection,cStart,&bs);
219: PetscSectionGetNumFields(dm->defaultSection,&nfields);
220: for (field=0,i=0; field<(nfields?nfields:1); field++) {
221: PetscInt fbs,j;
222: PetscFV fv = NULL;
223: PetscObject f;
224: PetscClassId fClass;
225: const char *fieldname = NULL;
226: char buf[256];
227: if (nfields) { /* We have user-defined fields/components */
228: PetscSectionGetFieldDof(dm->defaultSection,cStart,field,&fbs);
229: PetscSectionGetFieldName(dm->defaultSection,field,&fieldname);
230: } else fbs = bs; /* Say we have one field with 'bs' components */
231: DMGetField(dm,field,&f);
232: PetscObjectGetClassId(f,&fClass);
233: if (fClass == PETSCFV_CLASSID) {
234: fv = (PetscFV) f;
235: }
236: if (!fieldname) {
237: PetscSNPrintf(buf,sizeof(buf),"CellField%D",field);
238: fieldname = buf;
239: }
240: for (j=0; j<fbs; j++) {
241: const char *compName = NULL;
242: if (fv) {
243: PetscFVGetComponentName(fv,j,&compName);
244: }
245: if (compName) {
246: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%s\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,compName,boffset);
247: }
248: else {
249: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
250: }
251: boffset += gpiece[r].ncells*sizeof(PetscScalar) + sizeof(int);
252: i++;
253: }
254: }
255: if (i != bs) SETERRQ2(comm,PETSC_ERR_PLIB,"Total number of field components %D != block size %D",i,bs);
256: }
257: PetscFPrintf(PETSC_COMM_SELF,fp," </CellData>\n");
259: /*
260: * Point Data headers
261: */
262: PetscFPrintf(PETSC_COMM_SELF,fp," <PointData>\n");
263: for (link=vtk->link; link; link=link->next) {
264: Vec X = (Vec)link->vec;
265: PetscInt bs,nfields,field;
266: const char *vecname = "";
267: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
268: 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. */
269: PetscObjectGetName((PetscObject)X,&vecname);
270: }
271: PetscSectionGetDof(dm->defaultSection,vStart,&bs);
272: PetscSectionGetNumFields(dm->defaultSection,&nfields);
273: for (field=0,i=0; field<(nfields?nfields:1); field++) {
274: PetscInt fbs,j;
275: const char *fieldname = NULL;
276: char buf[256];
277: if (nfields) { /* We have user-defined fields/components */
278: PetscSectionGetFieldDof(dm->defaultSection,vStart,field,&fbs);
279: PetscSectionGetFieldName(dm->defaultSection,field,&fieldname);
280: } else fbs = bs; /* Say we have one field with 'bs' components */
281: if (!fieldname) {
282: PetscSNPrintf(buf,sizeof(buf),"PointField%D",field);
283: fieldname = buf;
284: }
285: for (j=0; j<fbs; j++) {
286: PetscFPrintf(comm,fp," <DataArray type=\"%s\" Name=\"%s%s.%D\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,j,boffset);
287: boffset += gpiece[r].nvertices*sizeof(PetscScalar) + sizeof(int);
288: }
289: }
290: }
291: PetscFPrintf(PETSC_COMM_SELF,fp," </PointData>\n");
293: PetscFPrintf(PETSC_COMM_SELF,fp," </Piece>\n");
294: }
295: }
297: PetscFPrintf(comm,fp," </UnstructuredGrid>\n");
298: PetscFPrintf(comm,fp," <AppendedData encoding=\"raw\">\n");
299: PetscFPrintf(comm,fp,"_");
301: if (!rank) {
302: PetscInt maxsize = 0;
303: for (r=0; r<size; r++) {
304: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nvertices*3*sizeof(PetscScalar)));
305: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].ncells*sizeof(PetscScalar)));
306: maxsize = PetscMax(maxsize, (PetscInt) (gpiece[r].nconn*sizeof(PetscVTKInt)));
307: }
308: PetscMalloc(maxsize,&buffer);
309: }
310: for (r=0; r<size; r++) {
311: if (r == rank) {
312: PetscInt nsend;
313: { /* Position */
314: const PetscScalar *x;
315: PetscScalar *y = NULL;
316: Vec coords;
317: nsend = piece.nvertices*3;
318: DMGetCoordinatesLocal(dm,&coords);
319: VecGetArrayRead(coords,&x);
320: if (dimEmbed != 3) {
321: PetscMalloc1(piece.nvertices*3,&y);
322: for (i=0; i<piece.nvertices; i++) {
323: y[i*3+0] = x[i*dimEmbed+0];
324: y[i*3+1] = (dimEmbed > 1) ? x[i*dimEmbed+1] : 0;
325: y[i*3+2] = 0;
326: }
327: }
328: TransferWrite(viewer,fp,r,0,y ? y : x,buffer,nsend,PETSC_SCALAR,tag);
329: PetscFree(y);
330: VecRestoreArrayRead(coords,&x);
331: }
332: { /* Connectivity, offsets, types */
333: PetscVTKInt *connectivity = NULL, *offsets = NULL;
334: PetscVTKType *types = NULL;
335: DMPlexGetVTKConnectivity(dm,&piece,&connectivity,&offsets,&types);
336: TransferWrite(viewer,fp,r,0,connectivity,buffer,piece.nconn,PETSC_INT32,tag);
337: TransferWrite(viewer,fp,r,0,offsets,buffer,piece.ncells,PETSC_INT32,tag);
338: TransferWrite(viewer,fp,r,0,types,buffer,piece.ncells,PETSC_UINT8,tag);
339: PetscFree3(connectivity,offsets,types);
340: }
341: { /* Owners (cell data) */
342: PetscVTKInt *owners;
343: PetscMalloc1(piece.ncells,&owners);
344: for (i=0; i<piece.ncells; i++) owners[i] = rank;
345: TransferWrite(viewer,fp,r,0,owners,buffer,piece.ncells,PETSC_INT32,tag);
346: PetscFree(owners);
347: }
348: /* Cell data */
349: for (link=vtk->link; link; link=link->next) {
350: Vec X = (Vec)link->vec;
351: const PetscScalar *x;
352: PetscScalar *y;
353: PetscInt bs;
354: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
355: PetscSectionGetDof(dm->defaultSection,cStart,&bs);
356: VecGetArrayRead(X,&x);
357: PetscMalloc1(piece.ncells,&y);
358: for (i=0; i<bs; i++) {
359: PetscInt cnt;
360: for (c=cStart,cnt=0; c<cEnd; c++) {
361: PetscScalar *xpoint;
362: if (hasLabel) { /* Ignore some cells */
363: PetscInt value;
364: DMGetLabelValue(dm, "vtk", c, &value);
365: if (value != 1) continue;
366: }
367: DMPlexPointLocalRead(dm,c,x,&xpoint);
368: y[cnt++] = xpoint[i];
369: }
370: if (cnt != piece.ncells) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
371: TransferWrite(viewer,fp,r,0,y,buffer,piece.ncells,PETSC_SCALAR,tag);
372: }
373: PetscFree(y);
374: VecRestoreArrayRead(X,&x);
375: }
377: for (link=vtk->link; link; link=link->next) {
378: Vec X = (Vec)link->vec;
379: const PetscScalar *x;
380: PetscScalar *y;
381: PetscInt bs;
382: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
383: PetscSectionGetDof(dm->defaultSection,vStart,&bs);
384: VecGetArrayRead(X,&x);
385: PetscMalloc1(piece.nvertices,&y);
386: for (i=0; i<bs; i++) {
387: PetscInt cnt;
388: for (v=vStart,cnt=0; v<vEnd; v++) {
389: PetscScalar *xpoint;
390: DMPlexPointLocalRead(dm,v,x,&xpoint);
391: y[cnt++] = xpoint[i];
392: }
393: if (cnt != piece.nvertices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Count does not match");
394: TransferWrite(viewer,fp,r,0,y,buffer,piece.nvertices,PETSC_SCALAR,tag);
395: }
396: PetscFree(y);
397: VecRestoreArrayRead(X,&x);
398: }
399: } else if (!rank) {
400: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices*3,PETSC_SCALAR,tag); /* positions */
401: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nconn,PETSC_INT32,tag); /* connectivity */
402: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,PETSC_INT32,tag); /* offsets */
403: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,PETSC_UINT8,tag); /* types */
404: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,PETSC_INT32,tag); /* owner rank (cells) */
405: /* all cell data */
406: for (link=vtk->link; link; link=link->next) {
407: PetscInt bs;
408: if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
409: PetscSectionGetDof(dm->defaultSection,cStart,&bs);
410: for (i=0; i<bs; i++) {
411: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].ncells,PETSC_SCALAR,tag);
412: }
413: }
414: /* all point data */
415: for (link=vtk->link; link; link=link->next) {
416: PetscInt bs;
417: if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
418: PetscSectionGetDof(dm->defaultSection,vStart,&bs);
419: for (i=0; i<bs; i++) {
420: TransferWrite(viewer,fp,r,0,NULL,buffer,gpiece[r].nvertices,PETSC_SCALAR,tag);
421: }
422: }
423: }
424: }
425: PetscFree(gpiece);
426: PetscFree(buffer);
427: PetscFPrintf(comm,fp,"\n </AppendedData>\n");
428: PetscFPrintf(comm,fp,"</VTKFile>\n");
429: PetscFClose(comm,fp);
430: return(0);
431: }