xref: /petsc/src/dm/impls/da/grvtk.c (revision b45d2f2cb7e031d9c0de5873eca80614ca7b863b)
1*b45d2f2cSJed Brown #include <petsc-private/daimpl.h>
24061b8bfSJed Brown #include <../src/sys/viewer/impls/vtk/vtkvimpl.h>
34061b8bfSJed Brown 
44061b8bfSJed Brown #if defined(PETSC_HAVE_STDINT_H) /* The VTK format requires a 32-bit integer */
54061b8bfSJed Brown typedef int32_t PetscVTKInt;
64061b8bfSJed Brown #else
74061b8bfSJed Brown typedef int PetscVTKInt;
84061b8bfSJed Brown #endif
94061b8bfSJed Brown #define PETSC_VTK_INT_MAX  2147483647
104061b8bfSJed Brown #define PETSC_VTK_INT_MIN -2147483647
114061b8bfSJed Brown #if defined(PETSC_USE_64BIT_INDICES)
124061b8bfSJed Brown #  define PetscVTKIntCheck(a)  if ((a) > PETSC_VTK_INT_MAX) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Array too long for 32-bit VTK binary format")
134061b8bfSJed Brown #  define PetscVTKIntCast(a) (PetscVTKInt)(a);PetscVTKIntCheck(a)
144061b8bfSJed Brown #else
154061b8bfSJed Brown #  define PetscVTKIntCheck(a)
164061b8bfSJed Brown #  define PetscVTKIntCast(a) a
174061b8bfSJed Brown #endif
184061b8bfSJed Brown 
194061b8bfSJed Brown #undef __FUNCT__
204061b8bfSJed Brown #define __FUNCT__ "PetscFWrite_VTK"
214061b8bfSJed Brown /* Write binary data preceded by 32-bit int length (in bytes), does not do byte swapping. */
224061b8bfSJed Brown static PetscErrorCode PetscFWrite_VTK(MPI_Comm comm,FILE *fp,void *data,PetscInt n,PetscDataType dtype)
234061b8bfSJed Brown {
244061b8bfSJed Brown   PetscErrorCode ierr;
254061b8bfSJed Brown   PetscMPIInt rank;
264061b8bfSJed Brown 
274061b8bfSJed Brown   PetscFunctionBegin;
284061b8bfSJed Brown   if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
294061b8bfSJed Brown   if (!n) PetscFunctionReturn(0);
304061b8bfSJed Brown   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
314061b8bfSJed Brown   if (!rank) {
324061b8bfSJed Brown     size_t count;
334061b8bfSJed Brown     PetscInt size;
344061b8bfSJed Brown     PetscVTKInt bytes;
354061b8bfSJed Brown     switch (dtype) {
364061b8bfSJed Brown     case PETSC_DOUBLE:
374061b8bfSJed Brown       size = sizeof(double);
384061b8bfSJed Brown       break;
394061b8bfSJed Brown     case PETSC_FLOAT:
404061b8bfSJed Brown       size = sizeof(float);
414061b8bfSJed Brown       break;
424061b8bfSJed Brown     case PETSC_INT:
434061b8bfSJed Brown       size = sizeof(PetscInt);
444061b8bfSJed Brown       break;
454061b8bfSJed Brown     case PETSC_CHAR:
464061b8bfSJed Brown       size = sizeof(char);
474061b8bfSJed Brown       break;
484061b8bfSJed Brown     default: SETERRQ(comm,PETSC_ERR_SUP,"Data type not supported");
494061b8bfSJed Brown     }
504061b8bfSJed Brown     bytes = PetscVTKIntCast(size*n);
514061b8bfSJed Brown 
524061b8bfSJed Brown     count = fwrite(&bytes,sizeof(int),1,fp);
534061b8bfSJed Brown     if (count != 1) {
544061b8bfSJed Brown       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing byte count");
554061b8bfSJed Brown     }
564061b8bfSJed Brown     count = fwrite(data,size,(size_t)n,fp);
574061b8bfSJed Brown     if ((PetscInt)count != n) {
584061b8bfSJed Brown       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Wrote %D/%D array members of size %D",(PetscInt)count,n,(PetscInt)size);
594061b8bfSJed Brown     }
604061b8bfSJed Brown   }
614061b8bfSJed Brown   PetscFunctionReturn(0);
624061b8bfSJed Brown }
634061b8bfSJed Brown 
644061b8bfSJed Brown #undef __FUNCT__
654061b8bfSJed Brown #define __FUNCT__ "DMDAVTKWriteAll_VTS"
664061b8bfSJed Brown static PetscErrorCode DMDAVTKWriteAll_VTS(DM da,PetscViewer viewer)
674061b8bfSJed Brown {
684061b8bfSJed Brown #if defined(PETSC_USE_REAL_SINGLE)
694061b8bfSJed Brown   const char precision[]  = "Float32";
704061b8bfSJed Brown #elif defined(PETSC_USE_REAL_DOUBLE)
714061b8bfSJed Brown   const char precision[]  = "Float64";
724061b8bfSJed Brown #else
734061b8bfSJed Brown   const char precision[]  = "UnknownPrecision";
744061b8bfSJed Brown #endif
754061b8bfSJed Brown   MPI_Comm                 comm = ((PetscObject)da)->comm;
764061b8bfSJed Brown   PetscViewer_VTK          *vtk = (PetscViewer_VTK*)viewer->data;
774061b8bfSJed Brown   PetscViewerVTKObjectLink link;
784061b8bfSJed Brown   FILE                     *fp;
794061b8bfSJed Brown   PetscMPIInt              rank,size,tag;
804061b8bfSJed Brown   DMDALocalInfo            info;
814061b8bfSJed Brown   PetscInt                 dim,mx,my,mz,bs,boffset,maxnnodes,i,j,k,f,r;
824061b8bfSJed Brown   PetscInt                 rloc[6],(*grloc)[6] = PETSC_NULL;
834061b8bfSJed Brown   PetscScalar              *array,*array2;
844061b8bfSJed Brown   PetscReal                gmin[3],gmax[3];
854061b8bfSJed Brown   PetscErrorCode           ierr;
864061b8bfSJed Brown 
874061b8bfSJed Brown   PetscFunctionBegin;
884061b8bfSJed Brown #if defined(PETSC_USE_COMPLEX)
894061b8bfSJed Brown   SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Complex values not supported");
904061b8bfSJed Brown #endif
914061b8bfSJed Brown 
924061b8bfSJed Brown   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
934061b8bfSJed Brown   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
944061b8bfSJed Brown   ierr = DMDAGetInfo(da,&dim, &mx,&my,&mz, 0,0,0, &bs,0,0,0,0,0);CHKERRQ(ierr);
954061b8bfSJed Brown   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
964061b8bfSJed Brown   ierr = DMDAGetBoundingBox(da,gmin,gmax);CHKERRQ(ierr);
974061b8bfSJed Brown 
984061b8bfSJed Brown   ierr = PetscFOpen(comm,vtk->filename,"wb",&fp);CHKERRQ(ierr);
994061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"<?xml version=\"1.0\"?>\n");CHKERRQ(ierr);
1004061b8bfSJed Brown #ifdef PETSC_WORDS_BIGENDIAN
1014061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"<VTKFile type=\"StructuredGrid\" version=\"0.1\" byte_order=\"BigEndian\">\n");CHKERRQ(ierr);
1024061b8bfSJed Brown #else
1034061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"<VTKFile type=\"StructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n");CHKERRQ(ierr);
1044061b8bfSJed Brown #endif
1054061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"  <StructuredGrid WholeExtent=\"%D %D %D %D %D %D\">\n",0,mx-1,0,my-1,0,mz-1);CHKERRQ(ierr);
1064061b8bfSJed Brown 
1074061b8bfSJed Brown   if (!rank) {ierr = PetscMalloc(size*6*sizeof(PetscInt),&grloc);CHKERRQ(ierr);}
1084061b8bfSJed Brown   rloc[0] = info.xs;
1094061b8bfSJed Brown   rloc[1] = info.xm;
1104061b8bfSJed Brown   rloc[2] = info.ys;
1114061b8bfSJed Brown   rloc[3] = info.ym;
1124061b8bfSJed Brown   rloc[4] = info.zs;
1134061b8bfSJed Brown   rloc[5] = info.zm;
1144061b8bfSJed Brown   ierr = MPI_Gather(rloc,6,MPIU_INT,&grloc[0][0],6,MPIU_INT,0,comm);CHKERRQ(ierr);
1154061b8bfSJed Brown 
1164061b8bfSJed Brown   /* Write XML header */
1174061b8bfSJed Brown   maxnnodes = 0;                /* Used for the temporary array size on rank 0 */
1184061b8bfSJed Brown   boffset = 0;                  /* Offset into binary file */
1194061b8bfSJed Brown   for (r=0; r<size; r++) {
1204061b8bfSJed Brown     PetscInt xs=-1,xm=-1,ys=-1,ym=-1,zs=-1,zm=-1,nnodes = 0;
1214061b8bfSJed Brown     if (!rank) {
1224061b8bfSJed Brown       xs = grloc[r][0];
1234061b8bfSJed Brown       xm = grloc[r][1];
1244061b8bfSJed Brown       ys = grloc[r][2];
1254061b8bfSJed Brown       ym = grloc[r][3];
1264061b8bfSJed Brown       zs = grloc[r][4];
1274061b8bfSJed Brown       zm = grloc[r][5];
1284061b8bfSJed Brown       nnodes = xm*ym*zm;
1294061b8bfSJed Brown     }
1304061b8bfSJed Brown     maxnnodes = PetscMax(maxnnodes,nnodes);
1314061b8bfSJed Brown #if 0
1324061b8bfSJed Brown     switch (dim) {
1334061b8bfSJed Brown     case 1:
1344061b8bfSJed Brown       ierr = PetscFPrintf(comm,fp,"    <Piece Extent=\"%D %D %D %D %D %D\">\n",xs,xs+xm-1,0,0,0,0);CHKERRQ(ierr);
1354061b8bfSJed Brown       break;
1364061b8bfSJed Brown     case 2:
1374061b8bfSJed Brown       ierr = PetscFPrintf(comm,fp,"    <Piece Extent=\"%D %D %D %D %D %D\">\n",xs,xs+xm,ys+ym-1,xs,xs+xm-1,0,0);CHKERRQ(ierr);
1384061b8bfSJed Brown       break;
1394061b8bfSJed Brown     case 3:
1404061b8bfSJed Brown       ierr = PetscFPrintf(comm,fp,"    <Piece Extent=\"%D %D %D %D %D %D\">\n",xs,xs+xm-1,ys,ys+ym-1,zs,zs+zm-1);CHKERRQ(ierr);
1414061b8bfSJed Brown       break;
1424061b8bfSJed Brown     default: SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"No support for dimension %D",dim);
1434061b8bfSJed Brown     }
1444061b8bfSJed Brown #endif
1454061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"    <Piece Extent=\"%D %D %D %D %D %D\">\n",xs,xs+xm-1,ys,ys+ym-1,zs,zs+zm-1);CHKERRQ(ierr);
1464061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"      <Points>\n");CHKERRQ(ierr);
1474061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"        <DataArray type=\"%s\" Name=\"Position\" NumberOfComponents=\"3\" format=\"appended\" offset=\"%D\" />\n",precision,boffset);CHKERRQ(ierr);
1484061b8bfSJed Brown     boffset += 3*nnodes*sizeof(PetscScalar) + sizeof(int);
1494061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"      </Points>\n");CHKERRQ(ierr);
1504061b8bfSJed Brown 
1514061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"      <PointData Scalars=\"ScalarPointData\">\n");CHKERRQ(ierr);
1524061b8bfSJed Brown     for (link=vtk->link; link; link=link->next) {
1534061b8bfSJed Brown       Vec X = (Vec)link->vec;
1544061b8bfSJed Brown       const char *vecname = "";
1554061b8bfSJed Brown       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. */
1564061b8bfSJed Brown         ierr = PetscObjectGetName((PetscObject)X,&vecname);CHKERRQ(ierr);
1574061b8bfSJed Brown       }
1584061b8bfSJed Brown       for (i=0; i<bs; i++) {
1594061b8bfSJed Brown         char buf[256];
1604061b8bfSJed Brown         const char *fieldname;
1614061b8bfSJed Brown         ierr = DMDAGetFieldName(da,i,&fieldname);CHKERRQ(ierr);
1624061b8bfSJed Brown         if (!fieldname) {
1634061b8bfSJed Brown           ierr = PetscSNPrintf(buf,sizeof buf,"Unnamed%D",i);CHKERRQ(ierr);
1644061b8bfSJed Brown           fieldname = buf;
1654061b8bfSJed Brown         }
1664061b8bfSJed Brown         ierr = PetscFPrintf(comm,fp,"        <DataArray type=\"%s\" Name=\"%s%s\" NumberOfComponents=\"1\" format=\"appended\" offset=\"%D\" />\n",precision,vecname,fieldname,boffset);CHKERRQ(ierr);
1674061b8bfSJed Brown         boffset += nnodes*sizeof(PetscScalar) + sizeof(int);
1684061b8bfSJed Brown       }
1694061b8bfSJed Brown     }
1704061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"      </PointData>\n");CHKERRQ(ierr);
1714061b8bfSJed Brown     ierr = PetscFPrintf(comm,fp,"    </Piece>\n");CHKERRQ(ierr);
1724061b8bfSJed Brown   }
1734061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"  </StructuredGrid>\n");CHKERRQ(ierr);
1744061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"  <AppendedData encoding=\"raw\">\n");CHKERRQ(ierr);
1754061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"_");CHKERRQ(ierr);
1764061b8bfSJed Brown 
1774061b8bfSJed Brown   /* Now write the arrays. */
1784061b8bfSJed Brown   tag  = ((PetscObject)viewer)->tag;
1794061b8bfSJed Brown   ierr = PetscMalloc2(maxnnodes*PetscMax(3,bs),PetscScalar,&array,maxnnodes*3,PetscScalar,&array2);CHKERRQ(ierr);
1804061b8bfSJed Brown   for (r=0; r<size; r++) {
1814061b8bfSJed Brown     MPI_Status status;
1824061b8bfSJed Brown     PetscInt xs=-1,xm=-1,ys=-1,ym=-1,zs=-1,zm=-1,nnodes = 0;
1834061b8bfSJed Brown     if (!rank) {
1844061b8bfSJed Brown       xs = grloc[r][0];
1854061b8bfSJed Brown       xm = grloc[r][1];
1864061b8bfSJed Brown       ys = grloc[r][2];
1874061b8bfSJed Brown       ym = grloc[r][3];
1884061b8bfSJed Brown       zs = grloc[r][4];
1894061b8bfSJed Brown       zm = grloc[r][5];
1904061b8bfSJed Brown       nnodes = xm*ym*zm;
1914061b8bfSJed Brown     } else if (r == rank) {
1924061b8bfSJed Brown       nnodes = info.xm*info.ym*info.zm;
1934061b8bfSJed Brown     }
1944061b8bfSJed Brown 
1954061b8bfSJed Brown     {                           /* Write the coordinates */
1964061b8bfSJed Brown       Vec Coords;
1974061b8bfSJed Brown       ierr = DMDAGetCoordinates(da,&Coords);CHKERRQ(ierr);
1984061b8bfSJed Brown       if (Coords) {
1994061b8bfSJed Brown         const PetscScalar *coords;
2004061b8bfSJed Brown         ierr = VecGetArrayRead(Coords,&coords);CHKERRQ(ierr);
2014061b8bfSJed Brown         if (!rank) {
2024061b8bfSJed Brown           if (r) {
2036622f924SJed Brown             PetscMPIInt nn;
20444a7239dSJed Brown             ierr = MPI_Recv(array,nnodes*dim,MPIU_SCALAR,r,tag,comm,&status);CHKERRQ(ierr);
2054061b8bfSJed Brown             ierr = MPI_Get_count(&status,MPIU_SCALAR,&nn);CHKERRQ(ierr);
20644a7239dSJed Brown             if (nn != nnodes*dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Array size mismatch");
2074061b8bfSJed Brown           } else {
20844a7239dSJed Brown             ierr = PetscMemcpy(array,coords,nnodes*dim*sizeof(PetscScalar));CHKERRQ(ierr);
2094061b8bfSJed Brown           }
2104061b8bfSJed Brown           /* Transpose coordinates to VTK (C-style) ordering */
2114061b8bfSJed Brown           for (k=0; k<zm; k++) {
2124061b8bfSJed Brown             for (j=0; j<ym; j++) {
2134061b8bfSJed Brown               for (i=0; i<xm; i++) {
2144061b8bfSJed Brown                 PetscInt Iloc = i+xm*(j+ym*k);
2154061b8bfSJed Brown                 array2[Iloc*3+0] = array[Iloc*dim + 0];
2164061b8bfSJed Brown                 array2[Iloc*3+1] = dim > 1 ? array[Iloc*dim + 1] : 0;
2174061b8bfSJed Brown                 array2[Iloc*3+2] = dim > 2 ? array[Iloc*dim + 2] : 0;
2184061b8bfSJed Brown               }
2194061b8bfSJed Brown             }
2204061b8bfSJed Brown           }
2214061b8bfSJed Brown         } else if (r == rank) {
22244a7239dSJed Brown           ierr = MPI_Send((void*)coords,nnodes*dim,MPIU_SCALAR,0,tag,comm);CHKERRQ(ierr);
2234061b8bfSJed Brown         }
2244061b8bfSJed Brown         ierr = VecRestoreArrayRead(Coords,&coords);CHKERRQ(ierr);
2254061b8bfSJed Brown       } else {       /* Fabricate some coordinates using grid index */
2264061b8bfSJed Brown         for (k=0; k<zm; k++) {
2274061b8bfSJed Brown           for (j=0; j<ym; j++) {
2284061b8bfSJed Brown             for (i=0; i<xm; i++) {
2294061b8bfSJed Brown               PetscInt Iloc = i+xm*(j+ym*k);
2304061b8bfSJed Brown               array2[Iloc*3+0] = xs+i;
2314061b8bfSJed Brown               array2[Iloc*3+1] = ys+j;
2324061b8bfSJed Brown               array2[Iloc*3+2] = zs+k;
2334061b8bfSJed Brown             }
2344061b8bfSJed Brown           }
2354061b8bfSJed Brown         }
2364061b8bfSJed Brown       }
2374061b8bfSJed Brown       ierr = PetscFWrite_VTK(comm,fp,array2,nnodes*3,PETSC_SCALAR);CHKERRQ(ierr);
2384061b8bfSJed Brown     }
2394061b8bfSJed Brown 
2404061b8bfSJed Brown     /* Write each of the objects queued up for this file */
2414061b8bfSJed Brown     for (link=vtk->link; link; link=link->next) {
2424061b8bfSJed Brown       Vec X = (Vec)link->vec;
2434061b8bfSJed Brown       const PetscScalar *x;
2444061b8bfSJed Brown 
2454061b8bfSJed Brown       ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
2464061b8bfSJed Brown       if (!rank) {
2474061b8bfSJed Brown         if (r) {
2486622f924SJed Brown           PetscMPIInt nn;
2494061b8bfSJed Brown           ierr = MPI_Recv(array,nnodes*bs,MPIU_SCALAR,r,tag,comm,&status);CHKERRQ(ierr);
2504061b8bfSJed Brown           ierr = MPI_Get_count(&status,MPIU_SCALAR,&nn);CHKERRQ(ierr);
2514061b8bfSJed Brown           if (nn != nnodes*bs) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Array size mismatch receiving from rank %D",r);
2524061b8bfSJed Brown         } else {
2534061b8bfSJed Brown           ierr = PetscMemcpy(array,x,nnodes*bs*sizeof(PetscScalar));CHKERRQ(ierr);
2544061b8bfSJed Brown         }
2554061b8bfSJed Brown         for (f=0; f<bs; f++) {
2564061b8bfSJed Brown           /* Extract and transpose the f'th field */
2574061b8bfSJed Brown           for (k=0; k<zm; k++) {
2584061b8bfSJed Brown             for (j=0; j<ym; j++) {
2594061b8bfSJed Brown               for (i=0; i<xm; i++) {
2604061b8bfSJed Brown                 PetscInt Iloc = i+xm*(j+ym*k);
2614061b8bfSJed Brown                 array2[Iloc] = array[Iloc*bs + f];
2624061b8bfSJed Brown               }
2634061b8bfSJed Brown             }
2644061b8bfSJed Brown           }
2654061b8bfSJed Brown           ierr = PetscFWrite_VTK(comm,fp,array2,nnodes,PETSC_SCALAR);CHKERRQ(ierr);
2664061b8bfSJed Brown         }
2674061b8bfSJed Brown       } else if (r == rank) {
2684061b8bfSJed Brown         ierr = MPI_Send((void*)x,nnodes*bs,MPIU_SCALAR,0,tag,comm);CHKERRQ(ierr);
2694061b8bfSJed Brown       }
2704061b8bfSJed Brown       ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
2714061b8bfSJed Brown     }
2724061b8bfSJed Brown   }
2734061b8bfSJed Brown   ierr = PetscFree2(array,array2);CHKERRQ(ierr);
2744061b8bfSJed Brown   ierr = PetscFree(grloc);CHKERRQ(ierr);
2754061b8bfSJed Brown 
2764061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"\n </AppendedData>\n");CHKERRQ(ierr);
2774061b8bfSJed Brown   ierr = PetscFPrintf(comm,fp,"</VTKFile>\n");CHKERRQ(ierr);
2784061b8bfSJed Brown   ierr = PetscFClose(comm,fp);CHKERRQ(ierr);
2794061b8bfSJed Brown   PetscFunctionReturn(0);
2804061b8bfSJed Brown }
2814061b8bfSJed Brown 
2824061b8bfSJed Brown 
2834061b8bfSJed Brown #undef __FUNCT__
2844061b8bfSJed Brown #define __FUNCT__ "DMDAVTKWriteAll"
2854061b8bfSJed Brown /*@C
2864061b8bfSJed Brown    DMDAVTKWriteAll - Write a file containing all the fields that have been provided to the viewer
2874061b8bfSJed Brown 
2884061b8bfSJed Brown    Collective
2894061b8bfSJed Brown 
2904061b8bfSJed Brown    Input Arguments:
2914061b8bfSJed Brown    odm - DM specifying the grid layout, passed as a PetscObject
2924061b8bfSJed Brown    viewer - viewer of type VTK
2934061b8bfSJed Brown 
2944061b8bfSJed Brown    Level: developer
2954061b8bfSJed Brown 
2964061b8bfSJed Brown    Note:
2974061b8bfSJed Brown    This function is a callback used by the VTK viewer to actually write the file.
2984061b8bfSJed Brown    The reason for this odd model is that the VTK file format does not provide any way to write one field at a time.
2994061b8bfSJed Brown    Instead, metadata for the entire file needs to be available up-front before you can start writing the file.
3004061b8bfSJed Brown 
3014061b8bfSJed Brown .seealso: PETSCVIEWERVTK
3024061b8bfSJed Brown @*/
3034061b8bfSJed Brown PetscErrorCode DMDAVTKWriteAll(PetscObject odm,PetscViewer viewer)
3044061b8bfSJed Brown {
3054061b8bfSJed Brown   DM              dm   = (DM)odm;
3064061b8bfSJed Brown   PetscBool       isvtk;
3074061b8bfSJed Brown   PetscErrorCode  ierr;
3084061b8bfSJed Brown 
3094061b8bfSJed Brown   PetscFunctionBegin;
3104061b8bfSJed Brown   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3114061b8bfSJed Brown   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3124061b8bfSJed Brown   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);CHKERRQ(ierr);
3134061b8bfSJed Brown   if (!isvtk) SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_ARG_INCOMP,"Cannot use viewer type %s",((PetscObject)viewer)->type_name);
3144061b8bfSJed Brown   switch (viewer->format) {
3154061b8bfSJed Brown   case PETSC_VIEWER_VTK_VTS:
3164061b8bfSJed Brown     ierr = DMDAVTKWriteAll_VTS(dm,viewer);CHKERRQ(ierr);
3174061b8bfSJed Brown     break;
3184061b8bfSJed Brown   default: SETERRQ1(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No support for format '%s'",PetscViewerFormats[viewer->format]);
3194061b8bfSJed Brown   }
3204061b8bfSJed Brown   PetscFunctionReturn(0);
3214061b8bfSJed Brown }
322