Actual source code: plexvtk.c

petsc-3.6.4 2016-04-12
Report Typos and Errors
  1: #define PETSCDM_DLL
  2: #include <petsc/private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
  3: #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h>

  7: PetscErrorCode DMPlexVTKGetCellType(DM dm, PetscInt dim, PetscInt corners, PetscInt *cellType)
  8: {
 10:   *cellType = -1;
 11:   switch (dim) {
 12:   case 0:
 13:     switch (corners) {
 14:     case 1:
 15:       *cellType = 1; /* VTK_VERTEX */
 16:       break;
 17:     default:
 18:       break;
 19:     }
 20:     break;
 21:   case 1:
 22:     switch (corners) {
 23:     case 2:
 24:       *cellType = 3; /* VTK_LINE */
 25:       break;
 26:     case 3:
 27:       *cellType = 21; /* VTK_QUADRATIC_EDGE */
 28:       break;
 29:     default:
 30:       break;
 31:     }
 32:     break;
 33:   case 2:
 34:     switch (corners) {
 35:     case 3:
 36:       *cellType = 5; /* VTK_TRIANGLE */
 37:       break;
 38:     case 4:
 39:       *cellType = 9; /* VTK_QUAD */
 40:       break;
 41:     case 6:
 42:       *cellType = 22; /* VTK_QUADRATIC_TRIANGLE */
 43:       break;
 44:     case 9:
 45:       *cellType = 23; /* VTK_QUADRATIC_QUAD */
 46:       break;
 47:     default:
 48:       break;
 49:     }
 50:     break;
 51:   case 3:
 52:     switch (corners) {
 53:     case 4:
 54:       *cellType = 10; /* VTK_TETRA */
 55:       break;
 56:     case 8:
 57:       *cellType = 12; /* VTK_HEXAHEDRON */
 58:       break;
 59:     case 10:
 60:       *cellType = 24; /* VTK_QUADRATIC_TETRA */
 61:       break;
 62:     case 27:
 63:       *cellType = 29; /* VTK_QUADRATIC_HEXAHEDRON */
 64:       break;
 65:     default:
 66:       break;
 67:     }
 68:   }
 69:   return(0);
 70: }

 74: PetscErrorCode DMPlexVTKWriteCells_ASCII(DM dm, FILE *fp, PetscInt *totalCells)
 75: {
 76:   MPI_Comm       comm;
 77:   DMLabel        label;
 78:   IS             globalVertexNumbers = NULL;
 79:   const PetscInt *gvertex;
 80:   PetscInt       dim;
 81:   PetscInt       numCorners = 0, totCorners = 0, maxCorners, *corners;
 82:   PetscInt       numCells   = 0, totCells   = 0, maxCells, cellHeight;
 83:   PetscInt       numLabelCells, maxLabelCells, cMax, cStart, cEnd, c, vStart, vEnd, v;
 84:   PetscMPIInt    numProcs, rank, proc, tag;

 88:   PetscObjectGetComm((PetscObject)dm,&comm);
 89:   PetscCommGetNewTag(comm, &tag);
 90:   MPI_Comm_size(comm, &numProcs);
 91:   MPI_Comm_rank(comm, &rank);
 92:   DMGetDimension(dm, &dim);
 93:   DMPlexGetVTKCellHeight(dm, &cellHeight);
 94:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
 95:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
 96:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
 97:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
 98:   DMPlexGetLabel(dm, "vtk", &label);
 99:   DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);
100:   MPI_Allreduce(&numLabelCells, &maxLabelCells, 1, MPIU_INT, MPI_MAX, comm);
101:   if (!maxLabelCells) label = NULL;
102:   for (c = cStart; c < cEnd; ++c) {
103:     PetscInt *closure = NULL;
104:     PetscInt closureSize, value;

106:     if (label) {
107:       DMLabelGetValue(label, c, &value);
108:       if (value != 1) continue;
109:     }
110:     DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
111:     for (v = 0; v < closureSize*2; v += 2) {
112:       if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++numCorners;
113:     }
114:     DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
115:     ++numCells;
116:   }
117:   maxCells = numCells;
118:   MPI_Reduce(&numCells, &totCells, 1, MPIU_INT, MPI_SUM, 0, comm);
119:   MPI_Reduce(&numCells, &maxCells, 1, MPIU_INT, MPI_MAX, 0, comm);
120:   MPI_Reduce(&numCorners, &totCorners, 1, MPIU_INT, MPI_SUM, 0, comm);
121:   MPI_Reduce(&numCorners, &maxCorners, 1, MPIU_INT, MPI_MAX, 0, comm);
122:   DMPlexGetVertexNumbering(dm, &globalVertexNumbers);
123:   ISGetIndices(globalVertexNumbers, &gvertex);
124:   PetscMalloc1(maxCells, &corners);
125:   PetscFPrintf(comm, fp, "CELLS %d %d\n", totCells, totCorners+totCells);
126:   if (!rank) {
127:     PetscInt *remoteVertices;
128:     int      *vertices;

130:     PetscMalloc1(maxCorners, &vertices);
131:     for (c = cStart, numCells = 0; c < cEnd; ++c) {
132:       PetscInt *closure = NULL;
133:       PetscInt closureSize, value, nC = 0;

135:       if (label) {
136:         DMLabelGetValue(label, c, &value);
137:         if (value != 1) continue;
138:       }
139:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
140:       for (v = 0; v < closureSize*2; v += 2) {
141:         if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
142:           const PetscInt gv = gvertex[closure[v] - vStart];
143:           vertices[nC++] = gv < 0 ? -(gv+1) : gv;
144:         }
145:       }
146:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
147:       corners[numCells++] = nC;
148:       PetscFPrintf(comm, fp, "%d ", nC);
149:       DMPlexInvertCell(dim, nC, vertices);
150:       for (v = 0; v < nC; ++v) {
151:         PetscFPrintf(comm, fp, " %d", vertices[v]);
152:       }
153:       PetscFPrintf(comm, fp, "\n");
154:     }
155:     if (numProcs > 1) {PetscMalloc1(maxCorners+maxCells, &remoteVertices);}
156:     for (proc = 1; proc < numProcs; ++proc) {
157:       MPI_Status status;

159:       MPI_Recv(&numCorners, 1, MPIU_INT, proc, tag, comm, &status);
160:       MPI_Recv(remoteVertices, numCorners, MPIU_INT, proc, tag, comm, &status);
161:       for (c = 0; c < numCorners;) {
162:         PetscInt nC = remoteVertices[c++];

164:         for (v = 0; v < nC; ++v, ++c) {
165:           vertices[v] = remoteVertices[c];
166:         }
167:         DMPlexInvertCell(dim, nC, vertices);
168:         PetscFPrintf(comm, fp, "%d ", nC);
169:         for (v = 0; v < nC; ++v) {
170:           PetscFPrintf(comm, fp, " %d", vertices[v]);
171:         }
172:         PetscFPrintf(comm, fp, "\n");
173:       }
174:     }
175:     if (numProcs > 1) {PetscFree(remoteVertices);}
176:     PetscFree(vertices);
177:   } else {
178:     PetscInt *localVertices, numSend = numCells+numCorners, k = 0;

180:     PetscMalloc1(numSend, &localVertices);
181:     for (c = cStart, numCells = 0; c < cEnd; ++c) {
182:       PetscInt *closure = NULL;
183:       PetscInt closureSize, value, nC = 0;

185:       if (label) {
186:         DMLabelGetValue(label, c, &value);
187:         if (value != 1) continue;
188:       }
189:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
190:       for (v = 0; v < closureSize*2; v += 2) {
191:         if ((closure[v] >= vStart) && (closure[v] < vEnd)) {
192:           const PetscInt gv = gvertex[closure[v] - vStart];
193:           closure[nC++] = gv < 0 ? -(gv+1) : gv;
194:         }
195:       }
196:       corners[numCells++] = nC;
197:       localVertices[k++]  = nC;
198:       for (v = 0; v < nC; ++v, ++k) {
199:         localVertices[k] = closure[v];
200:       }
201:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
202:     }
203:     if (k != numSend) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numSend);
204:     MPI_Send(&numSend, 1, MPIU_INT, 0, tag, comm);
205:     MPI_Send(localVertices, numSend, MPIU_INT, 0, tag, comm);
206:     PetscFree(localVertices);
207:   }
208:   ISRestoreIndices(globalVertexNumbers, &gvertex);
209:   PetscFPrintf(comm, fp, "CELL_TYPES %d\n", totCells);
210:   if (!rank) {
211:     PetscInt cellType;

213:     for (c = 0; c < numCells; ++c) {
214:       DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);
215:       PetscFPrintf(comm, fp, "%d\n", cellType);
216:     }
217:     for (proc = 1; proc < numProcs; ++proc) {
218:       MPI_Status status;

220:       MPI_Recv(&numCells, 1, MPIU_INT, proc, tag, comm, &status);
221:       MPI_Recv(corners, numCells, MPIU_INT, proc, tag, comm, &status);
222:       for (c = 0; c < numCells; ++c) {
223:         DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);
224:         PetscFPrintf(comm, fp, "%d\n", cellType);
225:       }
226:     }
227:   } else {
228:     MPI_Send(&numCells, 1, MPIU_INT, 0, tag, comm);
229:     MPI_Send(corners, numCells, MPIU_INT, 0, tag, comm);
230:   }
231:   PetscFree(corners);
232:   *totalCells = totCells;
233:   return(0);
234: }

238: PetscErrorCode DMPlexVTKWritePartition_ASCII(DM dm, FILE *fp)
239: {
240:   MPI_Comm       comm;
241:   PetscInt       numCells = 0, cellHeight;
242:   PetscInt       numLabelCells, cMax, cStart, cEnd, c;
243:   PetscMPIInt    numProcs, rank, proc, tag;
244:   PetscBool      hasLabel;

248:   PetscObjectGetComm((PetscObject)dm,&comm);
249:   PetscCommGetNewTag(comm, &tag);
250:   MPI_Comm_size(comm, &numProcs);
251:   MPI_Comm_rank(comm, &rank);
252:   DMPlexGetVTKCellHeight(dm, &cellHeight);
253:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
254:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
255:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
256:   DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);
257:   hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
258:   for (c = cStart; c < cEnd; ++c) {
259:     if (hasLabel) {
260:       PetscInt value;

262:       DMPlexGetLabelValue(dm, "vtk", c, &value);
263:       if (value != 1) continue;
264:     }
265:     ++numCells;
266:   }
267:   if (!rank) {
268:     for (c = 0; c < numCells; ++c) {PetscFPrintf(comm, fp, "%d\n", rank);}
269:     for (proc = 1; proc < numProcs; ++proc) {
270:       MPI_Status status;

272:       MPI_Recv(&numCells, 1, MPIU_INT, proc, tag, comm, &status);
273:       for (c = 0; c < numCells; ++c) {PetscFPrintf(comm, fp, "%d\n", proc);}
274:     }
275:   } else {
276:     MPI_Send(&numCells, 1, MPIU_INT, 0, tag, comm);
277:   }
278:   return(0);
279: }

283: PetscErrorCode DMPlexVTKWriteSection_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec v, FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale)
284: {
285:   MPI_Comm           comm;
286:   const MPI_Datatype mpiType = MPIU_SCALAR;
287:   PetscScalar        *array;
288:   PetscInt           numDof = 0, maxDof;
289:   PetscInt           numLabelCells, cellHeight, cMax, cStart, cEnd, numLabelVertices, vMax, vStart, vEnd, pStart, pEnd, p;
290:   PetscMPIInt        numProcs, rank, proc, tag;
291:   PetscBool          hasLabel;
292:   PetscErrorCode     ierr;

295:   PetscObjectGetComm((PetscObject)dm,&comm);
298:   if (precision < 0) precision = 6;
299:   PetscCommGetNewTag(comm, &tag);
300:   MPI_Comm_size(comm, &numProcs);
301:   MPI_Comm_rank(comm, &rank);
302:   PetscSectionGetChart(section, &pStart, &pEnd);
303:   /* VTK only wants the values at cells or vertices */
304:   DMPlexGetVTKCellHeight(dm, &cellHeight);
305:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
306:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
307:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, &vMax);
308:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
309:   if (vMax >= 0) vEnd = PetscMin(vEnd, vMax);
310:   pStart   = PetscMax(PetscMin(cStart, vStart), pStart);
311:   pEnd     = PetscMin(PetscMax(cEnd,   vEnd),   pEnd);
312:   DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);
313:   DMPlexGetStratumSize(dm, "vtk", 2, &numLabelVertices);
314:   hasLabel = numLabelCells > 0 || numLabelVertices > 0 ? PETSC_TRUE : PETSC_FALSE;
315:   for (p = pStart; p < pEnd; ++p) {
316:     /* Reject points not either cells or vertices */
317:     if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
318:     if (hasLabel) {
319:       PetscInt value;

321:       if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
322:           ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
323:         DMPlexGetLabelValue(dm, "vtk", p, &value);
324:         if (value != 1) continue;
325:       }
326:     }
327:     PetscSectionGetDof(section, p, &numDof);
328:     if (numDof) break;
329:   }
330:   MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, comm);
331:   enforceDof = PetscMax(enforceDof, maxDof);
332:   VecGetArray(v, &array);
333:   if (!rank) {
334:     char formatString[8];

336:     PetscSNPrintf(formatString, 8, "%%.%de", precision);
337:     for (p = pStart; p < pEnd; ++p) {
338:       /* Here we lose a way to filter points by keeping them out of the Numbering */
339:       PetscInt dof, off, goff, d;

341:       /* Reject points not either cells or vertices */
342:       if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
343:       if (hasLabel) {
344:         PetscInt value;

346:         if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
347:             ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
348:           DMPlexGetLabelValue(dm, "vtk", p, &value);
349:           if (value != 1) continue;
350:         }
351:       }
352:       PetscSectionGetDof(section, p, &dof);
353:       PetscSectionGetOffset(section, p, &off);
354:       PetscSectionGetOffset(globalSection, p, &goff);
355:       if (dof && goff >= 0) {
356:         for (d = 0; d < dof; d++) {
357:           if (d > 0) {
358:             PetscFPrintf(comm, fp, " ");
359:           }
360:           PetscFPrintf(comm, fp, formatString, PetscRealPart(array[off+d])*scale);
361:         }
362:         for (d = dof; d < enforceDof; d++) {
363:           PetscFPrintf(comm, fp, " 0.0");
364:         }
365:         PetscFPrintf(comm, fp, "\n");
366:       }
367:     }
368:     for (proc = 1; proc < numProcs; ++proc) {
369:       PetscScalar *remoteValues;
370:       PetscInt    size = 0, d;
371:       MPI_Status  status;

373:       MPI_Recv(&size, 1, MPIU_INT, proc, tag, comm, &status);
374:       PetscMalloc1(size, &remoteValues);
375:       MPI_Recv(remoteValues, size, mpiType, proc, tag, comm, &status);
376:       for (p = 0; p < size/maxDof; ++p) {
377:         for (d = 0; d < maxDof; ++d) {
378:           if (d > 0) {
379:             PetscFPrintf(comm, fp, " ");
380:           }
381:           PetscFPrintf(comm, fp, formatString, PetscRealPart(remoteValues[p*maxDof+d])*scale);
382:         }
383:         for (d = maxDof; d < enforceDof; ++d) {
384:           PetscFPrintf(comm, fp, " 0.0");
385:         }
386:         PetscFPrintf(comm, fp, "\n");
387:       }
388:       PetscFree(remoteValues);
389:     }
390:   } else {
391:     PetscScalar *localValues;
392:     PetscInt    size, k = 0;

394:     PetscSectionGetStorageSize(section, &size);
395:     PetscMalloc1(size, &localValues);
396:     for (p = pStart; p < pEnd; ++p) {
397:       PetscInt dof, off, goff, d;

399:       /* Reject points not either cells or vertices */
400:       if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
401:       if (hasLabel) {
402:         PetscInt value;

404:         if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
405:             ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
406:           DMPlexGetLabelValue(dm, "vtk", p, &value);
407:           if (value != 1) continue;
408:         }
409:       }
410:       PetscSectionGetDof(section, p, &dof);
411:       PetscSectionGetOffset(section, p, &off);
412:       PetscSectionGetOffset(globalSection, p, &goff);
413:       if (goff >= 0) {
414:         for (d = 0; d < dof; ++d) {
415:           localValues[k++] = array[off+d];
416:         }
417:       }
418:     }
419:     MPI_Send(&k, 1, MPIU_INT, 0, tag, comm);
420:     MPI_Send(localValues, k, mpiType, 0, tag, comm);
421:     PetscFree(localValues);
422:   }
423:   VecRestoreArray(v, &array);
424:   return(0);
425: }

429: PetscErrorCode DMPlexVTKWriteField_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec field, const char name[], FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale)
430: {
431:   MPI_Comm       comm;
432:   PetscInt       numDof = 0, maxDof;
433:   PetscInt       pStart, pEnd, p;

437:   PetscObjectGetComm((PetscObject)dm,&comm);
438:   PetscSectionGetChart(section, &pStart, &pEnd);
439:   for (p = pStart; p < pEnd; ++p) {
440:     PetscSectionGetDof(section, p, &numDof);
441:     if (numDof) break;
442:   }
443:   numDof = PetscMax(numDof, enforceDof);
444:   MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));
445:   if (!name) name = "Unknown";
446:   if (maxDof == 3) {
447:     PetscFPrintf(comm, fp, "VECTORS %s double\n", name);
448:   } else {
449:     PetscFPrintf(comm, fp, "SCALARS %s double %d\n", name, maxDof);
450:     PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");
451:   }
452:   DMPlexVTKWriteSection_ASCII(dm, section, globalSection, field, fp, enforceDof, precision, scale);
453:   return(0);
454: }

458: static PetscErrorCode DMPlexVTKWriteAll_ASCII(DM dm, PetscViewer viewer)
459: {
460:   MPI_Comm                 comm;
461:   PetscViewer_VTK          *vtk = (PetscViewer_VTK*) viewer->data;
462:   FILE                     *fp;
463:   PetscViewerVTKObjectLink link;
464:   PetscSection             coordSection, globalCoordSection;
465:   PetscLayout              vLayout;
466:   Vec                      coordinates;
467:   PetscReal                lengthScale;
468:   PetscInt                 vMax, totVertices, totCells;
469:   PetscBool                hasPoint = PETSC_FALSE, hasCell = PETSC_FALSE, writePartition = PETSC_FALSE;
470:   PetscErrorCode           ierr;

473:   PetscObjectGetComm((PetscObject)dm,&comm);
474:   PetscFOpen(comm, vtk->filename, "wb", &fp);
475:   PetscFPrintf(comm, fp, "# vtk DataFile Version 2.0\n");
476:   PetscFPrintf(comm, fp, "Simplicial Mesh Example\n");
477:   PetscFPrintf(comm, fp, "ASCII\n");
478:   PetscFPrintf(comm, fp, "DATASET UNSTRUCTURED_GRID\n");
479:   /* Vertices */
480:   DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);
481:   DMGetCoordinateSection(dm, &coordSection);
482:   PetscSectionCreateGlobalSection(coordSection, dm->sf, PETSC_FALSE, &globalCoordSection);
483:   DMGetCoordinatesLocal(dm, &coordinates);
484:   DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);
485:   if (vMax >= 0) {
486:     PetscInt pStart, pEnd, p, localSize = 0;

488:     PetscSectionGetChart(globalCoordSection, &pStart, &pEnd);
489:     pEnd = PetscMin(pEnd, vMax);
490:     for (p = pStart; p < pEnd; ++p) {
491:       PetscInt dof;

493:       PetscSectionGetDof(globalCoordSection, p, &dof);
494:       if (dof > 0) ++localSize;
495:     }
496:     PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &vLayout);
497:     PetscLayoutSetLocalSize(vLayout, localSize);
498:     PetscLayoutSetBlockSize(vLayout, 1);
499:     PetscLayoutSetUp(vLayout);
500:   } else {
501:     PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalCoordSection, &vLayout);
502:   }
503:   PetscLayoutGetSize(vLayout, &totVertices);
504:   PetscFPrintf(comm, fp, "POINTS %d double\n", totVertices);
505:   DMPlexVTKWriteSection_ASCII(dm, coordSection, globalCoordSection, coordinates, fp, 3, PETSC_DETERMINE, lengthScale);
506:   /* Cells */
507:   DMPlexVTKWriteCells_ASCII(dm, fp, &totCells);
508:   /* Vertex fields */
509:   for (link = vtk->link; link; link = link->next) {
510:     if ((link->ft == PETSC_VTK_POINT_FIELD) || (link->ft == PETSC_VTK_POINT_VECTOR_FIELD)) hasPoint = PETSC_TRUE;
511:     if ((link->ft == PETSC_VTK_CELL_FIELD)  || (link->ft == PETSC_VTK_CELL_VECTOR_FIELD))  hasCell  = PETSC_TRUE;
512:   }
513:   if (hasPoint) {
514:     PetscFPrintf(comm, fp, "POINT_DATA %d\n", totVertices);
515:     for (link = vtk->link; link; link = link->next) {
516:       Vec          X = (Vec) link->vec;
517:       DM           dmX;
518:       PetscSection section, globalSection, newSection = NULL;
519:       const char   *name;
520:       PetscInt     enforceDof = PETSC_DETERMINE;

522:       if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
523:       if (link->ft == PETSC_VTK_POINT_VECTOR_FIELD) enforceDof = 3;
524:       PetscObjectGetName(link->vec, &name);
525:       VecGetDM(X, &dmX);
526:       if (dmX) {
527:         DMLabel  subpointMap, subpointMapX;
528:         PetscInt dim, dimX, pStart, pEnd, qStart, qEnd;

530:         DMGetDefaultSection(dmX, &section);
531:         /* Here is where we check whether dmX is a submesh of dm */
532:         DMGetDimension(dm,  &dim);
533:         DMGetDimension(dmX, &dimX);
534:         DMPlexGetChart(dm,  &pStart, &pEnd);
535:         DMPlexGetChart(dmX, &qStart, &qEnd);
536:         DMPlexGetSubpointMap(dm,  &subpointMap);
537:         DMPlexGetSubpointMap(dmX, &subpointMapX);
538:         if (((dim != dimX) || ((pEnd-pStart) < (qEnd-qStart))) && subpointMap && !subpointMapX) {
539:           const PetscInt *ind = NULL;
540:           IS              subpointIS;
541:           PetscInt        n = 0, q;

543:           PetscSectionGetChart(section, &qStart, &qEnd);
544:           DMPlexCreateSubpointIS(dm, &subpointIS);
545:           if (subpointIS) {
546:             ISGetLocalSize(subpointIS, &n);
547:             ISGetIndices(subpointIS, &ind);
548:           }
549:           PetscSectionCreate(comm, &newSection);
550:           PetscSectionSetChart(newSection, pStart, pEnd);
551:           for (q = qStart; q < qEnd; ++q) {
552:             PetscInt dof, off, p;

554:             PetscSectionGetDof(section, q, &dof);
555:             if (dof) {
556:               PetscFindInt(q, n, ind, &p);
557:               if (p >= pStart) {
558:                 PetscSectionSetDof(newSection, p, dof);
559:                 PetscSectionGetOffset(section, q, &off);
560:                 PetscSectionSetOffset(newSection, p, off);
561:               }
562:             }
563:           }
564:           if (subpointIS) {
565:             ISRestoreIndices(subpointIS, &ind);
566:             ISDestroy(&subpointIS);
567:           }
568:           /* No need to setup section */
569:           section = newSection;
570:         }
571:       } else {
572:         PetscObjectQuery(link->vec, "section", (PetscObject*) &section);
573:         if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
574:       }
575:       if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
576:       PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);
577:       DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);
578:       PetscSectionDestroy(&globalSection);
579:       if (newSection) {PetscSectionDestroy(&newSection);}
580:     }
581:   }
582:   /* Cell Fields */
583:   PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_view_partition", &writePartition, NULL);
584:   if (hasCell || writePartition) {
585:     PetscFPrintf(comm, fp, "CELL_DATA %d\n", totCells);
586:     for (link = vtk->link; link; link = link->next) {
587:       Vec          X = (Vec) link->vec;
588:       DM           dmX;
589:       PetscSection section, globalSection;
590:       const char   *name;
591:       PetscInt     enforceDof = PETSC_DETERMINE;

593:       if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
594:       if (link->ft == PETSC_VTK_CELL_VECTOR_FIELD) enforceDof = 3;
595:       PetscObjectGetName(link->vec, &name);
596:       VecGetDM(X, &dmX);
597:       if (dmX) {
598:         DMGetDefaultSection(dmX, &section);
599:       } else {
600:         PetscContainer c;

602:         PetscObjectQuery(link->vec, "section", (PetscObject*) &c);
603:         if (!c) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
604:         PetscContainerGetPointer(c, (void**) &section);
605:       }
606:       if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
607:       PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);
608:       DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);
609:       PetscSectionDestroy(&globalSection);
610:     }
611:     if (writePartition) {
612:       PetscFPrintf(comm, fp, "SCALARS partition int 1\n");
613:       PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");
614:       DMPlexVTKWritePartition_ASCII(dm, fp);
615:     }
616:   }
617:   /* Cleanup */
618:   PetscSectionDestroy(&globalCoordSection);
619:   PetscLayoutDestroy(&vLayout);
620:   PetscFClose(comm, fp);
621:   return(0);
622: }

626: /*@C
627:   DMPlexVTKWriteAll - Write a file containing all the fields that have been provided to the viewer

629:   Collective

631:   Input Arguments:
632: + odm - The DMPlex specifying the mesh, passed as a PetscObject
633: - viewer - viewer of type VTK

635:   Level: developer

637:   Note:
638:   This function is a callback used by the VTK viewer to actually write the file.
639:   The reason for this odd model is that the VTK file format does not provide any way to write one field at a time.
640:   Instead, metadata for the entire file needs to be available up-front before you can start writing the file.

642: .seealso: PETSCVIEWERVTK
643: @*/
644: PetscErrorCode DMPlexVTKWriteAll(PetscObject odm, PetscViewer viewer)
645: {
646:   DM             dm = (DM) odm;
647:   PetscBool      isvtk;

653:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);
654:   if (!isvtk) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name);
655:   switch (viewer->format) {
656:   case PETSC_VIEWER_ASCII_VTK:
657:     DMPlexVTKWriteAll_ASCII(dm, viewer);
658:     break;
659:   case PETSC_VIEWER_VTK_VTU:
660:     DMPlexVTKWriteAll_VTU(dm, viewer);
661:     break;
662:   default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]);
663:   }
664:   return(0);
665: }