Date: 2013-07-02T14:46:00+00:00

Actual source code: plexvtk.c
petsc-3.4.2 2013-07-02

      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:   IS             globalVertexNumbers;
     78:   const PetscInt *gvertex;
     79:   PetscInt       dim;
     80:   PetscInt       numCorners = 0, totCorners = 0, maxCorners, *corners;
     81:   PetscInt       numCells   = 0, totCells   = 0, maxCells, cellHeight;
     82:   PetscInt       numLabelCells, cMax, cStart, cEnd, c, vStart, vEnd, v;
     83:   PetscMPIInt    numProcs, rank, proc, tag;
     84:   PetscBool      hasLabel;

     88:   PetscObjectGetComm((PetscObject)dm,&comm);
     89:   PetscCommGetNewTag(comm, &tag);
     90:   MPI_Comm_size(comm, &numProcs);
     91:   MPI_Comm_rank(comm, &rank);
     92:   DMPlexGetDimension(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:   DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);

    100:   hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE;
    101:   for (c = cStart; c < cEnd; ++c) {
    102:     PetscInt *closure = NULL;
    103:     PetscInt closureSize;

    105:     if (hasLabel) {
    106:       PetscInt value;

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

    130:     for (c = cStart, numCells = 0; c < cEnd; ++c) {
    131:       PetscInt *closure = NULL;
    132:       PetscInt closureSize, nC = 0, tmp;

    134:       if (hasLabel) {
    135:         PetscInt value;

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

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

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

    178:     PetscMalloc(numSend * sizeof(PetscInt), &localVertices);
    179:     for (c = cStart, numCells = 0; c < cEnd; ++c) {
    180:       PetscInt *closure = NULL;
    181:       PetscInt closureSize, nC = 0;

    183:       if (hasLabel) {
    184:         PetscInt value;

    186:         DMPlexGetLabelValue(dm, "vtk", 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 DMPlexVTKWriteSection_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec v, FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale)
    239: {
    240:   MPI_Comm           comm;
    241:   const MPI_Datatype mpiType = MPIU_SCALAR;
    242:   PetscScalar        *array;
    243:   PetscInt           numDof = 0, maxDof;
    244:   PetscInt           numLabelCells, cellHeight, cMax, cStart, cEnd, numLabelVertices, vMax, vStart, vEnd, pStart, pEnd, p;
    245:   PetscMPIInt        numProcs, rank, proc, tag;
    246:   PetscBool          hasLabel;
    247:   PetscErrorCode     ierr;

    250:   PetscObjectGetComm((PetscObject)dm,&comm);
    253:   if (precision < 0) precision = 6;
    254:   PetscCommGetNewTag(comm, &tag);
    255:   MPI_Comm_size(comm, &numProcs);
    256:   MPI_Comm_rank(comm, &rank);
    257:   PetscSectionGetChart(section, &pStart, &pEnd);
    258:   /* VTK only wants the values at cells or vertices */
    259:   DMPlexGetVTKCellHeight(dm, &cellHeight);
    260:   DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);
    261:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
    262:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, &vMax);
    263:   if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
    264:   if (vMax >= 0) vEnd = PetscMin(vEnd, vMax);
    265:   pStart   = PetscMax(PetscMin(cStart, vStart), pStart);
    266:   pEnd     = PetscMin(PetscMax(cEnd,   vEnd),   pEnd);
    267:   DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);
    268:   DMPlexGetStratumSize(dm, "vtk", 2, &numLabelVertices);
    269:   hasLabel = numLabelCells > 0 || numLabelVertices > 0 ? PETSC_TRUE : PETSC_FALSE;
    270:   for (p = pStart; p < pEnd; ++p) {
    271:     /* Reject points not either cells or vertices */
    272:     if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
    273:     if (hasLabel) {
    274:       PetscInt value;

    276:       if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
    277:           ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
    278:         DMPlexGetLabelValue(dm, "vtk", p, &value);
    279:         if (value != 1) continue;
    280:       }
    281:     }
    282:     PetscSectionGetDof(section, p, &numDof);
    283:     if (numDof) break;
    284:   }
    285:   MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, comm);
    286:   enforceDof = PetscMax(enforceDof, maxDof);
    287:   VecGetArray(v, &array);
    288:   if (!rank) {
    289:     char formatString[8];

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

    296:       /* Reject points not either cells or vertices */
    297:       if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
    298:       if (hasLabel) {
    299:         PetscInt value;

    301:         if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
    302:             ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
    303:           DMPlexGetLabelValue(dm, "vtk", p, &value);
    304:           if (value != 1) continue;
    305:         }
    306:       }
    307:       PetscSectionGetDof(section, p, &dof);
    308:       PetscSectionGetOffset(section, p, &off);
    309:       PetscSectionGetOffset(globalSection, p, &goff);
    310:       if (dof && goff >= 0) {
    311:         for (d = 0; d < dof; d++) {
    312:           if (d > 0) {
    313:             PetscFPrintf(comm, fp, " ");
    314:           }
    315:           PetscFPrintf(comm, fp, formatString, PetscRealPart(array[off+d])*scale);
    316:         }
    317:         for (d = dof; d < enforceDof; d++) {
    318:           PetscFPrintf(comm, fp, " 0.0");
    319:         }
    320:         PetscFPrintf(comm, fp, "\n");
    321:       }
    322:     }
    323:     for (proc = 1; proc < numProcs; ++proc) {
    324:       PetscScalar *remoteValues;
    325:       PetscInt    size, d;
    326:       MPI_Status  status;

    328:       MPI_Recv(&size, 1, MPIU_INT, proc, tag, comm, &status);
    329:       PetscMalloc(size * sizeof(PetscScalar), &remoteValues);
    330:       MPI_Recv(remoteValues, size, mpiType, proc, tag, comm, &status);
    331:       for (p = 0; p < size/maxDof; ++p) {
    332:         for (d = 0; d < maxDof; ++d) {
    333:           if (d > 0) {
    334:             PetscFPrintf(comm, fp, " ");
    335:           }
    336:           PetscFPrintf(comm, fp, formatString, PetscRealPart(remoteValues[p*maxDof+d])*scale);
    337:         }
    338:         for (d = maxDof; d < enforceDof; ++d) {
    339:           PetscFPrintf(comm, fp, " 0.0");
    340:         }
    341:         PetscFPrintf(comm, fp, "\n");
    342:       }
    343:       PetscFree(remoteValues);
    344:     }
    345:   } else {
    346:     PetscScalar *localValues;
    347:     PetscInt    size, k = 0;

    349:     PetscSectionGetStorageSize(section, &size);
    350:     PetscMalloc(size * sizeof(PetscScalar), &localValues);
    351:     for (p = pStart; p < pEnd; ++p) {
    352:       PetscInt dof, off, goff, d;

    354:       /* Reject points not either cells or vertices */
    355:       if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue;
    356:       if (hasLabel) {
    357:         PetscInt value;

    359:         if (((p >= cStart) && (p < cEnd) && numLabelCells) ||
    360:             ((p >= vStart) && (p < vEnd) && numLabelVertices)) {
    361:           DMPlexGetLabelValue(dm, "vtk", p, &value);
    362:           if (value != 1) continue;
    363:         }
    364:       }
    365:       PetscSectionGetDof(section, p, &dof);
    366:       PetscSectionGetOffset(section, p, &off);
    367:       PetscSectionGetOffset(globalSection, p, &goff);
    368:       if (goff >= 0) {
    369:         for (d = 0; d < dof; ++d) {
    370:           localValues[k++] = array[off+d];
    371:         }
    372:       }
    373:     }
    374:     MPI_Send(&k, 1, MPIU_INT, 0, tag, comm);
    375:     MPI_Send(localValues, k, mpiType, 0, tag, comm);
    376:     PetscFree(localValues);
    377:   }
    378:   VecRestoreArray(v, &array);
    379:   return(0);
    380: }

    384: PetscErrorCode DMPlexVTKWriteField_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec field, const char name[], FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale)
    385: {
    386:   MPI_Comm       comm;
    387:   PetscInt       numDof = 0, maxDof;
    388:   PetscInt       pStart, pEnd, p;

    392:   PetscObjectGetComm((PetscObject)dm,&comm);
    393:   PetscSectionGetChart(section, &pStart, &pEnd);
    394:   for (p = pStart; p < pEnd; ++p) {
    395:     PetscSectionGetDof(section, p, &numDof);
    396:     if (numDof) break;
    397:   }
    398:   numDof = PetscMax(numDof, enforceDof);
    399:   MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));
    400:   if (!name) name = "Unknown";
    401:   if (maxDof == 3) {
    402:     PetscFPrintf(comm, fp, "VECTORS %s double\n", name);
    403:   } else {
    404:     PetscFPrintf(comm, fp, "SCALARS %s double %d\n", name, maxDof);
    405:     PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");
    406:   }
    407:   DMPlexVTKWriteSection_ASCII(dm, section, globalSection, field, fp, enforceDof, precision, scale);
    408:   return(0);
    409: }

    413: static PetscErrorCode DMPlexVTKWriteAll_ASCII(DM dm, PetscViewer viewer)
    414: {
    415:   MPI_Comm                 comm;
    416:   PetscViewer_VTK          *vtk = (PetscViewer_VTK*) viewer->data;
    417:   FILE                     *fp;
    418:   PetscViewerVTKObjectLink link;
    419:   PetscSection             coordSection, globalCoordSection;
    420:   PetscLayout              vLayout;
    421:   Vec                      coordinates;
    422:   PetscReal                lengthScale;
    423:   PetscInt                 vMax, totVertices, totCells;
    424:   PetscBool                hasPoint = PETSC_FALSE, hasCell = PETSC_FALSE;
    425:   PetscErrorCode           ierr;

    428:   PetscObjectGetComm((PetscObject)dm,&comm);
    429:   PetscFOpen(comm, vtk->filename, "wb", &fp);
    430:   PetscFPrintf(comm, fp, "# vtk DataFile Version 2.0\n");
    431:   PetscFPrintf(comm, fp, "Simplicial Mesh Example\n");
    432:   PetscFPrintf(comm, fp, "ASCII\n");
    433:   PetscFPrintf(comm, fp, "DATASET UNSTRUCTURED_GRID\n");
    434:   /* Vertices */
    435:   DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);
    436:   DMPlexGetCoordinateSection(dm, &coordSection);
    437:   PetscSectionCreateGlobalSection(coordSection, dm->sf, PETSC_FALSE, &globalCoordSection);
    438:   DMGetCoordinatesLocal(dm, &coordinates);
    439:   DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);
    440:   if (vMax >= 0) {
    441:     PetscInt pStart, pEnd, p, localSize = 0;

    443:     PetscSectionGetChart(globalCoordSection, &pStart, &pEnd);
    444:     pEnd = PetscMin(pEnd, vMax);
    445:     for (p = pStart; p < pEnd; ++p) {
    446:       PetscInt dof;

    448:       PetscSectionGetDof(globalCoordSection, p, &dof);
    449:       if (dof > 0) ++localSize;
    450:     }
    451:     PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &vLayout);
    452:     PetscLayoutSetLocalSize(vLayout, localSize);
    453:     PetscLayoutSetBlockSize(vLayout, 1);
    454:     PetscLayoutSetUp(vLayout);
    455:   } else {
    456:     PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalCoordSection, &vLayout);
    457:   }
    458:   PetscLayoutGetSize(vLayout, &totVertices);
    459:   PetscFPrintf(comm, fp, "POINTS %d double\n", totVertices);
    460:   DMPlexVTKWriteSection_ASCII(dm, coordSection, globalCoordSection, coordinates, fp, 3, PETSC_DETERMINE, lengthScale);
    461:   /* Cells */
    462:   DMPlexVTKWriteCells_ASCII(dm, fp, &totCells);
    463:   /* Vertex fields */
    464:   for (link = vtk->link; link; link = link->next) {
    465:     if ((link->ft == PETSC_VTK_POINT_FIELD) || (link->ft == PETSC_VTK_POINT_VECTOR_FIELD)) hasPoint = PETSC_TRUE;
    466:     if ((link->ft == PETSC_VTK_CELL_FIELD)  || (link->ft == PETSC_VTK_CELL_VECTOR_FIELD))  hasCell  = PETSC_TRUE;
    467:   }
    468:   if (hasPoint) {
    469:     PetscFPrintf(comm, fp, "POINT_DATA %d\n", totVertices);
    470:     for (link = vtk->link; link; link = link->next) {
    471:       Vec          X = (Vec) link->vec;
    472:       DM           dmX;
    473:       PetscSection section, globalSection, newSection = NULL;
    474:       const char   *name;
    475:       PetscInt     enforceDof = PETSC_DETERMINE;

    477:       if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue;
    478:       if (link->ft == PETSC_VTK_POINT_VECTOR_FIELD) enforceDof = 3;
    479:       PetscObjectGetName(link->vec, &name);
    480:       VecGetDM(X, &dmX);
    481:       if (dmX) {
    482:         DMLabel  subpointMap, subpointMapX;
    483:         PetscInt dim, dimX, pStart, pEnd, qStart, qEnd;

    485:         DMGetDefaultSection(dmX, &section);
    486:         /* Here is where we check whether dmX is a submesh of dm */
    487:         DMPlexGetDimension(dm,  &dim);
    488:         DMPlexGetDimension(dmX, &dimX);
    489:         DMPlexGetChart(dm,  &pStart, &pEnd);
    490:         DMPlexGetChart(dmX, &qStart, &qEnd);
    491:         DMPlexGetSubpointMap(dm,  &subpointMap);
    492:         DMPlexGetSubpointMap(dmX, &subpointMapX);
    493:         if (((dim != dimX) || ((pEnd-pStart) < (qEnd-qStart))) && subpointMap && !subpointMapX) {
    494:           const PetscInt *ind;
    495:           IS              subpointIS;
    496:           PetscInt        n, q;

    498:           PetscPrintf(PETSC_COMM_SELF, "Making translation PetscSection\n");
    499:           PetscSectionGetChart(section, &qStart, &qEnd);
    500:           DMPlexCreateSubpointIS(dm, &subpointIS);
    501:           ISGetLocalSize(subpointIS, &n);
    502:           ISGetIndices(subpointIS, &ind);
    503:           PetscSectionCreate(comm, &newSection);
    504:           PetscSectionSetChart(newSection, pStart, pEnd);
    505:           for (q = qStart; q < qEnd; ++q) {
    506:             PetscInt dof, off, p;

    508:             PetscSectionGetDof(section, q, &dof);
    509:             if (dof) {
    510:               PetscFindInt(q, n, ind, &p);
    511:               if (p >= pStart) {
    512:                 PetscSectionSetDof(newSection, p, dof);
    513:                 PetscSectionGetOffset(section, q, &off);
    514:                 PetscSectionSetOffset(newSection, p, off);
    515:               }
    516:             }
    517:           }
    518:           ISRestoreIndices(subpointIS, &ind);
    519:           ISDestroy(&subpointIS);
    520:           /* No need to setup section */
    521:           section = newSection;
    522:         }
    523:       } else {
    524:         PetscObjectQuery(link->vec, "section", (PetscObject*) &section);
    525:         if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
    526:       }
    527:       if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
    528:       PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);
    529:       DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);
    530:       PetscSectionDestroy(&globalSection);
    531:       if (newSection) {PetscSectionDestroy(&newSection);}
    532:     }
    533:   }
    534:   /* Cell Fields */
    535:   if (hasCell) {
    536:     PetscFPrintf(comm, fp, "CELL_DATA %d\n", totCells);
    537:     for (link = vtk->link; link; link = link->next) {
    538:       Vec          X = (Vec) link->vec;
    539:       DM           dmX;
    540:       PetscSection section, globalSection;
    541:       const char   *name;
    542:       PetscInt     enforceDof = PETSC_DETERMINE;

    544:       if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue;
    545:       if (link->ft == PETSC_VTK_CELL_VECTOR_FIELD) enforceDof = 3;
    546:       PetscObjectGetName(link->vec, &name);
    547:       VecGetDM(X, &dmX);
    548:       if (dmX) {
    549:         DMGetDefaultSection(dmX, &section);
    550:       } else {
    551:         PetscContainer c;

    553:         PetscObjectQuery(link->vec, "section", (PetscObject*) &c);
    554:         if (!c) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
    555:         PetscContainerGetPointer(c, (void**) &section);
    556:       }
    557:       if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name);
    558:       PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);
    559:       DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);
    560:       PetscSectionDestroy(&globalSection);
    561:     }
    562:   }
    563:   /* Cleanup */
    564:   PetscSectionDestroy(&globalCoordSection);
    565:   PetscLayoutDestroy(&vLayout);
    566:   PetscFClose(comm, fp);
    567:   return(0);
    568: }

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

    575:   Collective

    577:   Input Arguments:
    578: + odm - The DMPlex specifying the mesh, passed as a PetscObject
    579: - viewer - viewer of type VTK

    581:   Level: developer

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

    588: .seealso: PETSCVIEWERVTK
    589: @*/
    590: PetscErrorCode DMPlexVTKWriteAll(PetscObject odm, PetscViewer viewer)
    591: {
    592:   DM             dm = (DM) odm;
    593:   PetscBool      isvtk;

    599:   PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);
    600:   if (!isvtk) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name);
    601:   switch (viewer->format) {
    602:   case PETSC_VIEWER_ASCII_VTK:
    603:     DMPlexVTKWriteAll_ASCII(dm, viewer);
    604:     break;
    605:   case PETSC_VIEWER_VTK_VTU:
    606:     DMPlexVTKWriteAll_VTU(dm, viewer);
    607:     break;
    608:   default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]);
    609:   }
    610:   return(0);
    611: }