/[escript]/trunk/finley/src/Mesh_saveVTK.c
ViewVC logotype

Diff of /trunk/finley/src/Mesh_saveVTK.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/esys2/finley/src/finleyC/Mesh_saveVTK.c revision 150 by jgs, Thu Sep 15 03:44:45 2005 UTC trunk/finley/src/Mesh_saveVTK.c revision 2141 by caltinay, Tue Dec 9 04:32:32 2008 UTC
# Line 1  Line 1 
 /*  
  ******************************************************************************  
  *                                                                            *  
  *       COPYRIGHT  ACcESS 2003,2004,2005 -  All Rights Reserved              *  
  *                                                                            *  
  * This software is the property of ACcESS. No part of this code              *  
  * may be copied in any form or by any means without the expressed written    *  
  * consent of ACcESS.  Copying, use or modification of this software          *  
  * by any unauthorised person is illegal unless that person has a software    *  
  * license agreement with ACcESS.                                             *  
  *                                                                            *  
  ******************************************************************************  
 */  
   
   
 /**************************************************************/  
1    
2  /*   writes data and mesh in a vtk file */  /*******************************************************
3    *
4    * Copyright (c) 2003-2008 by University of Queensland
5    * Earth Systems Science Computational Center (ESSCC)
6    * http://www.uq.edu.au/esscc
7    *
8    * Primary Business: Queensland, Australia
9    * Licensed under the Open Software License version 3.0
10    * http://www.opensource.org/licenses/osl-3.0.php
11    *
12    *******************************************************/
13    
14    /***************************************************************************/
15    /*   Writes data and mesh in VTK XML format to a VTU file.                 */
16    /*   Nodal data needs to be given on FINLEY_NODES or FINLEY_REDUCED_NODES  */
17    /***************************************************************************/
18    
19  /**************************************************************/  #include "Mesh.h"
20    #include "Assemble.h"
21    #include "vtkCellType.h"  /* copied from vtk source directory */
22    #include "paso/PasoUtil.h"
23    
24    #define INT_FORMAT "%d "
25    #define LEN_INT_FORMAT (9+1)
26    #define INT_NEWLINE_FORMAT "%d\n"
27    #define SCALAR_FORMAT "%12.6e\n"
28    #define VECTOR_FORMAT "%12.6e %12.6e %12.6e\n"
29    #define TENSOR_FORMAT "%12.6e %12.6e %12.6e %12.6e %12.6e %12.6e %12.6e %12.6e %12.6e\n"
30    #define LEN_TENSOR_FORMAT (9*(12+1)+1)
31    #define NEWLINE "\n"
32    #define LEN_TMP_BUFFER LEN_TENSOR_FORMAT+(MAX_numNodes*LEN_INT_FORMAT+1)+2
33    #define NCOMP_MAX 9
34    
35    #define __STRCAT(dest, chunk, dest_in_use) \
36    do {\
37        strcpy(&dest[dest_in_use], chunk);\
38        dest_in_use += strlen(chunk);\
39    } while(0)
40    
41    #ifdef PASO_MPI
42    
43    /* writes buffer to file catching the empty buffer case which causes problems
44     * with some MPI versions */
45    #define MPI_WRITE_ORDERED(BUF, LEN) \
46    do {\
47        if (LEN==0) { strcpy(BUF, " "); LEN=1; }\
48        MPI_File_write_ordered(mpi_fileHandle_p, BUF, LEN, MPI_CHAR, &mpi_status);\
49    } while(0)
50    
51    /* writes buffer to file on master only */
52    #define MPI_RANK0_WRITE_SHARED(BUF) \
53    do {\
54        if (my_mpi_rank == 0) {\
55            MPI_File_iwrite_shared(mpi_fileHandle_p, BUF, strlen(BUF), MPI_CHAR, &mpi_req);\
56            MPI_Wait(&mpi_req, &mpi_status);\
57        }\
58    } while(0)
59    
60    /* For reference only. Investigation needed as to which values may improve
61     * performance */
62    #if 0
63    void create_MPIInfo(MPI_Info& info)
64    {
65        MPI_Info_create(&info);
66        MPI_Info_set(info, "access_style", "write_once, sequential");
67        MPI_Info_set(info, "collective_buffering", "true");
68        MPI_Info_set(info, "cb_block_size",        "131072");
69        MPI_Info_set(info, "cb_buffer_size",       "1048567");
70        MPI_Info_set(info, "cb_nodes",             "8");
71        MPI_Info_set(info, "striping_factor",      "16");
72        MPI_Info_set(info, "striping_unit",        "424288");
73    }
74    #endif
75    
76  /*   Author: Paul Cochrane, cochrane@esscc.uq.edu.au */  #else
 /*   Version: $Id$ */  
77    
78  /**************************************************************/  #define MPI_WRITE_ORDERED(A, B)
79    #define MPI_RANK0_WRITE_SHARED(A)
80    
81  #include "Mesh.h"  #endif /* PASO_MPI */
 #include "vtkCellType.h"  /* copied from vtk source directory !!! */  
82    
 /**************************************************************/  
83    
84  void Finley_Mesh_saveVTK(const char * filename_p, Finley_Mesh *mesh_p, escriptDataC* data_p) {  /* Returns one if the node given by coords and idx is within the quadrant
85    char error_msg[LenErrorMsg_MAX];   * indexed by q and if the element type is Rec9 or Hex27, zero otherwise */
86    /* if there is no mesh we just return */  int nodeInQuadrant(const double *coords, ElementTypeId type, int idx, int q)
87    if (mesh_p==NULL) return;  {
88    Finley_ElementFile* elements=NULL;  #define INSIDE_1D(_X_,_C_,_R_) ( ABS((_X_)-(_C_)) <= (_R_) )
89    char elemTypeStr[32];  #define INSIDE_2D(_X_,_Y_,_CX_,_CY_,_R_) ( INSIDE_1D(_X_,_CX_,_R_) && INSIDE_1D(_Y_,_CY_,_R_))
90    int i, j, k, numVTKNodesPerElement, isCellCentered=FALSE, nodetype=FINLEY_DEGREES_OF_FREEDOM;  #define INSIDE_3D(_X_,_Y_,_Z_,_CX_,_CY_,_CZ_,_R_) ( INSIDE_1D(_X_,_CX_,_R_) && INSIDE_1D(_Y_,_CY_,_R_) && INSIDE_1D(_Z_,_CZ_,_R_) )
91    index_t j2;  
92    double* values, rtmp;      int ret;
93    int nDim = mesh_p->Nodes->numDim;      if (type == Rec9) {
94    int numPoints=0;          if (q==0)
95                  ret = INSIDE_2D(coords[2*idx], coords[2*idx+1], 0.25, 0.25, 0.25);
96    if (nDim==1) {          else if (q==1)
97        Finley_setError(VALUE_ERROR,"saveVTK: 1-dimensional domains are not supported.");              ret = INSIDE_2D(coords[2*idx], coords[2*idx+1], 0.75, 0.25, 0.25);
98        return;          else if (q==2)
99    }              ret = INSIDE_2D(coords[2*idx], coords[2*idx+1], 0.25, 0.75, 0.25);
100    /* get a pointer to the relevant mesh component */          else if (q==3)
101    if (isEmpty(data_p)) {              ret = INSIDE_2D(coords[2*idx], coords[2*idx+1], 0.75, 0.75, 0.25);
102      numPoints = mesh_p->Nodes->numNodes;          else
103      elements=mesh_p->Elements;              ret = 0;
104    } else {      } else if (type == Hex27) {
105      switch(getFunctionSpaceType(data_p)) {          if (q==0)
106      case(FINLEY_DEGREES_OF_FREEDOM):              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
107        numPoints = mesh_p->Nodes->numNodes;                      0.25, 0.25, 0.25, 0.25);
108        nodetype = FINLEY_DEGREES_OF_FREEDOM;          else if (q==1)
109        isCellCentered = FALSE;              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
110        elements = mesh_p->Elements;                      0.75, 0.25, 0.25, 0.25);
111        break;          else if (q==2)
112      case(FINLEY_REDUCED_DEGREES_OF_FREEDOM):              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
113        numPoints = mesh_p->Nodes->reducedNumNodes;                      0.25, 0.75, 0.25, 0.25);
114        nodetype =FINLEY_REDUCED_DEGREES_OF_FREEDOM;          else if (q==3)
115        isCellCentered = FALSE;              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
116        elements = mesh_p->Elements;                      0.75, 0.75, 0.25, 0.25);
117        break;          else if (q==4)
118      case(FINLEY_NODES):              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
119        numPoints = mesh_p->Nodes->numNodes;                      0.25, 0.25, 0.75, 0.25);
120        nodetype=FINLEY_NODES;          else if (q==5)
121        isCellCentered=FALSE;              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
122        elements=mesh_p->Elements;                      0.75, 0.25, 0.75, 0.25);
123        break;          else if (q==6)
124      case(FINLEY_ELEMENTS):              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
125        numPoints = mesh_p->Nodes->numNodes;                      0.25, 0.75, 0.75, 0.25);
126        nodetype=FINLEY_NODES;          else if (q==7)
127        isCellCentered=TRUE;              ret = INSIDE_3D(coords[3*idx], coords[3*idx+1], coords[3*idx+2],
128        elements=mesh_p->Elements;                      0.75, 0.75, 0.75, 0.25);
129        break;          else
130      case(FINLEY_FACE_ELEMENTS):              ret = 0;
131        numPoints = mesh_p->Nodes->numNodes;      } else {
132        nodetype=FINLEY_NODES;          ret = 1;
       isCellCentered=TRUE;  
       elements=mesh_p->FaceElements;  
       break;  
     case(FINLEY_POINTS):  
       numPoints = mesh_p->Nodes->numNodes;  
       nodetype=FINLEY_NODES;  
       isCellCentered=TRUE;  
       elements=mesh_p->Points;  
       break;  
     case(FINLEY_CONTACT_ELEMENTS_1):  
     case(FINLEY_CONTACT_ELEMENTS_2):  
       numPoints = mesh_p->Nodes->numNodes;  
       nodetype=FINLEY_NODES;  
       isCellCentered=TRUE;  
       elements=mesh_p->ContactElements;  
       break;  
     default:  
       sprintf(error_msg,"saveVTK: Finley does not know anything about function space type %d",getFunctionSpaceType(data_p));  
       Finley_setError(TYPE_ERROR,error_msg);  
       return;  
133      }      }
134    }      return ret;
135    }
136    
137    /* the number of points */  void Finley_Mesh_saveVTK(const char *filename_p,
138                             Finley_Mesh *mesh_p,
139                             const dim_t num_data,
140                             char **names_p,
141                             escriptDataC **data_pp)
142    {
143    #ifdef PASO_MPI
144        MPI_File mpi_fileHandle_p;
145        MPI_Status mpi_status;
146        MPI_Request mpi_req;
147        MPI_Info mpi_info = MPI_INFO_NULL;
148    #endif
149        Paso_MPI_rank my_mpi_rank;
150        FILE *fileHandle_p = NULL;
151        char errorMsg[LenErrorMsg_MAX], *txtBuffer;
152        char tmpBuffer[LEN_TMP_BUFFER];
153        size_t txtBufferSize, txtBufferInUse, maxNameLen;
154        double *quadNodes_p = NULL;
155        dim_t dataIdx, nDim;
156        dim_t numCells=0, globalNumCells=0, numVTKNodesPerElement=0;
157        dim_t myNumPoints=0, globalNumPoints=0;
158        dim_t shape, NN=0, numCellFactor=1, myNumCells=0;
159        bool_t *isCellCentered;
160        bool_t writeCellData=FALSE, writePointData=FALSE, hasReducedElements=FALSE;
161        index_t myFirstNode=0, myLastNode=0, *globalNodeIndex=NULL;
162        index_t myFirstCell=0, k;
163        int mpi_size, i, j, l;
164        int cellType=0, nodeType=FINLEY_NODES, elementType=FINLEY_UNKNOWN;
165        Finley_ElementFile *elements = NULL;
166        ElementTypeId typeId = NoType;
167    
168        const char *vtkHeader = \
169          "<?xml version=\"1.0\"?>\n" \
170          "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\">\n" \
171          "<UnstructuredGrid>\n" \
172          "<Piece NumberOfPoints=\"%d\" NumberOfCells=\"%d\">\n" \
173          "<Points>\n" \
174          "<DataArray NumberOfComponents=\"%d\" type=\"Float64\" format=\"ascii\">\n";
175        char *vtkFooter = "</Piece>\n</UnstructuredGrid>\n</VTKFile>\n";
176        const char *tag_Float_DataArray="<DataArray Name=\"%s\" type=\"Float64\" NumberOfComponents=\"%d\" format=\"ascii\">\n";
177        char *tags_End_Points_and_Start_Conn = "</DataArray>\n</Points>\n<Cells>\n<DataArray Name=\"connectivity\" type=\"Int32\" format=\"ascii\">\n" ;
178        char *tags_End_Conn_and_Start_Offset = "</DataArray>\n<DataArray Name=\"offsets\" type=\"Int32\" format=\"ascii\">\n";
179        char *tags_End_Offset_and_Start_Type = "</DataArray>\n<DataArray Name=\"types\" type=\"UInt8\" format=\"ascii\">\n";
180        char *tag_End_DataArray = "</DataArray>\n";
181    
182        const int VTK_HEX20_INDEX[] =
183          { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 12, 13, 14, 15 };
184        const int VTK_REC9_INDEX[] =
185          { 0, 4, 8, 7,  4, 1, 5, 8,  7, 8, 6, 3,  8, 5, 2, 6 };
186        const int VTK_HEX27_INDEX[] =
187          {  0,  8, 20, 11, 12, 21, 26, 24,
188             8,  1,  9, 20, 21, 13, 22, 26,
189            11, 20, 10,  3, 24, 26, 23, 15,
190            20,  9,  2, 10, 26, 22, 14, 23,
191            12, 21, 26, 24,  4, 16, 25, 19,
192            21, 13, 22, 26, 16,  5, 17, 25,
193            24, 26, 23, 15, 19, 25, 18,  7,
194            26, 22, 14, 23, 25, 17,  6, 18 };
195    
196        /* if there is no mesh we just return */
197        if (mesh_p==NULL) return;
198    
199        nDim = mesh_p->Nodes->numDim;
200    
201        if (nDim != 2 && nDim != 3) {
202            Finley_setError(TYPE_ERROR, "saveVTK: spatial dimension 2 or 3 is supported only.");
203            return;
204        }
205        my_mpi_rank = mesh_p->Nodes->MPIInfo->rank;
206        mpi_size = mesh_p->Nodes->MPIInfo->size;
207    
208    /* the number of cells */      /************************************************************************/
209    if (elements == NULL) {      /* open the file and check handle */
     Finley_setError(VALUE_ERROR,"saveVTK: elements object is NULL; cannot proceed");  
     return;  
   }  
   int numCells = elements->numElements;    
   /* open the file and check handle */  
   FILE * fileHandle_p = fopen(filename_p, "w");  
   if (fileHandle_p==NULL) {  
     sprintf(error_msg, "saveVTK: File %s could not be opened for writing.", filename_p);  
     Finley_setError(IO_ERROR,error_msg);  
     return;  
   }  
   /* xml header */  
   fprintf(fileHandle_p, "<?xml version=\"1.0\"?>\n");  
   fprintf(fileHandle_p, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\">\n");  
   
   /* finley uses an unstructured mesh, so UnstructuredGrid *should* work */  
   fprintf(fileHandle_p, "<UnstructuredGrid>\n");  
   
   /* is there only one "piece" to the data?? */  
   fprintf(fileHandle_p, "<Piece "  
           "NumberOfPoints=\"%d\" "  
           "NumberOfCells=\"%d\">\n",  
           numPoints, numCells);  
   /* now for the points; equivalent to positions section in saveDX() */  
   /* "The points element explicitly defines coordinates for each point  
    * individually.  It contains one DataArray element describing an array  
    * with three components per value, each specifying the coordinates of one  
    * point" - from Vtk User's Guide  
    */  
   fprintf(fileHandle_p, "<Points>\n");  
   /*  
    * the reason for this if statement is explained in the long comment below  
    */  
   if (nDim < 3) {  
     fprintf(fileHandle_p, "<DataArray "  
         "NumberOfComponents=\"3\" "  
         "type=\"Float32\" "  
         "format=\"ascii\">\n");  
   } else {  
     fprintf(fileHandle_p, "<DataArray "  
         "NumberOfComponents=\"%d\" "  
         "type=\"Float32\" "  
         "format=\"ascii\">\n",  
         nDim);  
   }  
   /* vtk/mayavi doesn't like 2D data, it likes 3D data with a degenerate  
      * third dimension to handle 2D data (like a sheet of paper).  So, if  
      * nDim is 2, we have to append zeros to the array to get this third  
      * dimension, and keep the visualisers happy.  
      * Indeed, if nDim is less than 3, must pad all empty dimensions, so  
      * that the total number of dims is 3.  
   */  
   if (nodetype==FINLEY_REDUCED_DEGREES_OF_FREEDOM) {  
      for (i = 0; i < mesh_p->Nodes->numNodes; i++) {  
        if (mesh_p->Nodes->toReduced[i]>=0) {  
           for (j = 0; j < nDim; j++)  
             fprintf(fileHandle_p, " %e",mesh_p->Nodes->Coordinates[INDEX2(j, i, nDim)]);  
           for (k=0; k<3-nDim; k++) fprintf(fileHandle_p, " %e",0.);  
           fprintf(fileHandle_p, "\n");  
        }  
      }  
   } else {  
      for (i = 0; i < mesh_p->Nodes->numNodes; i++) {  
        for (j = 0; j < nDim; j++)  
          fprintf(fileHandle_p, " %e",mesh_p->Nodes->Coordinates[INDEX2(j, i, nDim)]);  
        for (k=0; k<3-nDim; k++) fprintf(fileHandle_p, " %e",0.);  
        fprintf(fileHandle_p, "\n");  
      }  
   }  
   fprintf(fileHandle_p, "</DataArray>\n");  
   fprintf(fileHandle_p, "</Points>\n");  
   
   /* connections */  
   /* now for the cells */  
   /* "The Cells element defines cells explicitly by specifying point  
    * connectivity and cell types.  It contains three DataArray elements.  The  
    * first array specifies the point connectivity.  All cells' point lists  
    * are concatenated together.  The second array specifies th eoffset into  
    * the connectivity array for the end of each cell.  The third array  
    * specifies the type of each cell.  
    */  
   /* if no element table is present jump over the connection table */  
   if (elements!=NULL) {  
     int cellType;  
     ElementTypeId TypeId;  
210    
211      if (nodetype==FINLEY_REDUCED_DEGREES_OF_FREEDOM) {      if (mpi_size > 1) {
212        TypeId = elements->LinearReferenceElement->Type->TypeId;  #ifdef PASO_MPI
213            const int amode = MPI_MODE_CREATE|MPI_MODE_WRONLY|MPI_MODE_UNIQUE_OPEN;
214            int ierr;
215            if (my_mpi_rank == 0 && Paso_fileExists(filename_p)) {
216                remove(filename_p);
217            }
218            ierr = MPI_File_open(mesh_p->Nodes->MPIInfo->comm, (char*)filename_p,
219                                 amode, mpi_info, &mpi_fileHandle_p);
220            if (ierr != MPI_SUCCESS) {
221                sprintf(errorMsg, "saveVTK: File %s could not be opened for writing in parallel.", filename_p);
222                Finley_setError(IO_ERROR, errorMsg);
223            } else {
224                MPI_File_set_view(mpi_fileHandle_p, MPI_DISPLACEMENT_CURRENT,
225                        MPI_CHAR, MPI_CHAR, "native", mpi_info);
226            }
227    #endif /* PASO_MPI */
228      } else {      } else {
229        TypeId = elements->ReferenceElement->Type->TypeId;          fileHandle_p = fopen(filename_p, "w");
230            if (fileHandle_p==NULL) {
231                sprintf(errorMsg, "saveVTK: File %s could not be opened for writing.", filename_p);
232                Finley_setError(IO_ERROR, errorMsg);
233            }
234      }      }
235        if (!Paso_MPIInfo_noError(mesh_p->Nodes->MPIInfo)) return;
236    
237      switch(TypeId) {      /* General note: From this point if an error occurs Finley_setError is
238      case Point1:       * called and subsequent steps are skipped until the end of this function
239        cellType = VTK_VERTEX;       * where allocated memory is freed and the file is closed. */
240        break;  
241      case Line2:      /************************************************************************/
242        cellType = VTK_LINE;      /* find the mesh type to be written */
243        break;  
244      case Line3:      isCellCentered = TMPMEMALLOC(num_data, bool_t);
245        cellType = VTK_QUADRATIC_EDGE;      maxNameLen = 0;
246        break;      if (!Finley_checkPtr(isCellCentered)) {
247      case Tri3:          for (dataIdx=0; dataIdx<num_data; ++dataIdx) {
248        cellType = VTK_TRIANGLE;              if (! isEmpty(data_pp[dataIdx])) {
249        break;                  switch(getFunctionSpaceType(data_pp[dataIdx]) ) {
250      case Tri6:                      case FINLEY_NODES:
251        cellType = VTK_QUADRATIC_TRIANGLE;                          nodeType = (nodeType == FINLEY_REDUCED_NODES) ? FINLEY_REDUCED_NODES : FINLEY_NODES;
252        break;                          isCellCentered[dataIdx] = FALSE;
253      case Rec4:                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_ELEMENTS) {
254        cellType = VTK_QUAD;                              elementType = FINLEY_ELEMENTS;
255        break;                          } else {
256      case Rec8:                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
257        cellType = VTK_QUADRATIC_QUAD;                          }
258        break;                      break;
259      case Tet4:                      case FINLEY_REDUCED_NODES:
260        cellType = VTK_TETRA;                          nodeType = FINLEY_REDUCED_NODES;
261        break;                          isCellCentered[dataIdx] = FALSE;
262      case Tet10:                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_ELEMENTS) {
263        cellType = VTK_QUADRATIC_TETRA;                              elementType = FINLEY_ELEMENTS;
264        break;                          } else {
265      case Hex8:                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
266        cellType = VTK_HEXAHEDRON;                      }
267        break;                      break;
268      case Hex20:                      case FINLEY_REDUCED_ELEMENTS:
269        cellType = VTK_QUADRATIC_HEXAHEDRON;                          hasReducedElements = TRUE;
270        break;                      case FINLEY_ELEMENTS:
271      case Line2Face:                          isCellCentered[dataIdx] = TRUE;
272        cellType = VTK_VERTEX;                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_ELEMENTS) {
273        break;                              elementType = FINLEY_ELEMENTS;
274      case Line3Face:                          } else {
275        cellType = VTK_VERTEX;                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
276        break;                          }
277      case Tri3Face:                      break;
278        cellType = VTK_LINE;                      case FINLEY_REDUCED_FACE_ELEMENTS:
279        break;                          hasReducedElements = TRUE;
280      case Tri6Face:                      case FINLEY_FACE_ELEMENTS:
281        cellType = VTK_QUADRATIC_EDGE;                          isCellCentered[dataIdx] = TRUE;
282        break;                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_FACE_ELEMENTS) {
283      case Rec4Face:                              elementType = FINLEY_FACE_ELEMENTS;
284        cellType = VTK_LINE;                          } else {
285        break;                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
286      case Rec8Face:                          }
287        cellType = VTK_QUADRATIC_EDGE;                      break;
288        break;                      case FINLEY_POINTS:
289      case Tet4Face:                          isCellCentered[dataIdx]=TRUE;
290        cellType = VTK_TRIANGLE;                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_POINTS) {
291        break;                              elementType = FINLEY_POINTS;
292      case Tet10Face:                          } else {
293        cellType = VTK_QUADRATIC_TRIANGLE;                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
294        break;                          }
295      case Hex8Face:                      break;
296        cellType = VTK_QUAD;                      case FINLEY_REDUCED_CONTACT_ELEMENTS_1:
297        break;                          hasReducedElements = TRUE;
298      case Hex20Face:                      case FINLEY_CONTACT_ELEMENTS_1:
299        cellType = VTK_QUADRATIC_QUAD;                          isCellCentered[dataIdx] = TRUE;
300        break;                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_CONTACT_ELEMENTS_1) {
301      case Point1_Contact:                              elementType = FINLEY_CONTACT_ELEMENTS_1;
302        cellType = VTK_VERTEX;                          } else {
303        break;                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
304      case Line2_Contact:                          }
305        cellType = VTK_LINE;                      break;
306        break;                      case FINLEY_REDUCED_CONTACT_ELEMENTS_2:
307      case Line3_Contact:                          hasReducedElements = TRUE;
308        cellType = VTK_QUADRATIC_EDGE;                      case FINLEY_CONTACT_ELEMENTS_2:
309        break;                          isCellCentered[dataIdx] = TRUE;
310      case Tri3_Contact:                          if (elementType==FINLEY_UNKNOWN || elementType==FINLEY_CONTACT_ELEMENTS_1) {
311        cellType = VTK_LINE;                              elementType = FINLEY_CONTACT_ELEMENTS_1;
312        break;                          } else {
313      case Tri6_Contact:                              Finley_setError(TYPE_ERROR, "saveVTK: cannot write given data in single file.");
314        cellType = VTK_QUADRATIC_TRIANGLE;                          }
315        break;                      break;
316      case Rec4_Contact:                      default:
317        cellType = VTK_QUAD;                          sprintf(errorMsg, "saveVTK: unknown function space type %d",getFunctionSpaceType(data_pp[dataIdx]));
318        break;                          Finley_setError(TYPE_ERROR, errorMsg);
319      case Rec8_Contact:                  }
320        cellType = VTK_QUADRATIC_QUAD;                  if (isCellCentered[dataIdx]) {
321        break;                      writeCellData = TRUE;
322      case Line2Face_Contact:                  } else {
323        cellType = VTK_VERTEX;                      writePointData = TRUE;
324        break;                  }
325      case Line3Face_Contact:                  maxNameLen = MAX(maxNameLen, strlen(names_p[dataIdx]));
326        cellType = VTK_VERTEX;              }
327        break;          }
     case Tri3Face_Contact:  
       cellType = VTK_LINE;  
       break;  
     case Tri6Face_Contact:  
       cellType = VTK_QUADRATIC_EDGE;  
       break;  
     case Rec4Face_Contact:  
       cellType = VTK_LINE;  
       break;  
     case Rec8Face_Contact:  
       cellType = VTK_QUADRATIC_EDGE;  
       break;  
     case Tet4Face_Contact:  
       cellType = VTK_TRIANGLE;  
       break;  
     case Tet10Face_Contact:  
       cellType = VTK_QUADRATIC_TRIANGLE;  
       break;  
     case Hex8Face_Contact:  
       cellType = VTK_QUAD;  
       break;  
     case Hex20Face_Contact:  
       cellType = VTK_QUADRATIC_QUAD;  
       break;  
     default:  
       sprintf(error_msg, "saveVTK: Element type %s is not supported by VTK",elements->ReferenceElement->Type->Name);  
       Finley_setError(VALUE_ERROR,error_msg);  
       return;  
     }  
   
     switch(cellType) {  
     case VTK_VERTEX:  
       numVTKNodesPerElement = 1;  
       strcpy(elemTypeStr, "VTK_VERTEX");  
       break;  
     case VTK_LINE:  
       numVTKNodesPerElement = 2;  
       strcpy(elemTypeStr, "VTK_LINE");  
       break;  
     case VTK_TRIANGLE:  
       numVTKNodesPerElement = 3;  
       strcpy(elemTypeStr, "VTK_TRIANGLE");  
       break;  
     case VTK_QUAD:  
       numVTKNodesPerElement = 4;  
       strcpy(elemTypeStr, "VTK_QUAD");  
       break;  
     case VTK_TETRA:  
       numVTKNodesPerElement = 4;  
       strcpy(elemTypeStr, "VTK_TETRA");  
       break;  
     case VTK_HEXAHEDRON:  
       numVTKNodesPerElement = 8;  
       strcpy(elemTypeStr, "VTK_HEXAHEDRON");  
       break;  
     case VTK_QUADRATIC_EDGE:  
       numVTKNodesPerElement = 3;  
       strcpy(elemTypeStr, "VTK_QUADRATIC_EDGE");  
       break;  
     case VTK_QUADRATIC_TRIANGLE:  
       numVTKNodesPerElement = 6;  
       strcpy(elemTypeStr, "VTK_QUADRATIC_TRIANGLE");  
       break;  
     case VTK_QUADRATIC_QUAD:  
       numVTKNodesPerElement = 8;  
       strcpy(elemTypeStr, "VTK_QUADRATIC_QUAD");  
       break;  
     case VTK_QUADRATIC_TETRA:  
       numVTKNodesPerElement = 10;  
       strcpy(elemTypeStr, "VTK_QUADRATIC_TETRA");  
       break;  
     case VTK_QUADRATIC_HEXAHEDRON:  
       numVTKNodesPerElement = 20;  
       strcpy(elemTypeStr, "VTK_QUADRATIC_HEXAHEDRON");  
       break;  
     default:  
       sprintf(error_msg,"saveVTK: Cell type %d is not supported by VTK", cellType);  
       Finley_setError(VALUE_ERROR,error_msg);  
       return;  
328      }      }
329    
330      /* write out the DataArray element for the connectivity */      /************************************************************************/
331      int NN = elements->ReferenceElement->Type->numNodes;      /* select number of points and the mesh component */
332      fprintf(fileHandle_p, "<Cells>\n");  
333      fprintf(fileHandle_p, "<DataArray "      if (Finley_noError()) {
334          "Name=\"connectivity\" "          if (nodeType == FINLEY_REDUCED_NODES) {
335          "type=\"Int32\" "              myFirstNode = Finley_NodeFile_getFirstReducedNode(mesh_p->Nodes);
336          "format=\"ascii\">\n");              myLastNode = Finley_NodeFile_getLastReducedNode(mesh_p->Nodes);
337      if (nodetype==FINLEY_REDUCED_DEGREES_OF_FREEDOM) {              globalNumPoints = Finley_NodeFile_getGlobalNumReducedNodes(mesh_p->Nodes);
338         for (i = 0; i < numCells; i++) {              globalNodeIndex = Finley_NodeFile_borrowGlobalReducedNodesIndex(mesh_p->Nodes);
339            for (j = 0; j < numVTKNodesPerElement; j++) {          } else {
340                 j2=elements->ReferenceElement->Type->linearNodes[j];              myFirstNode = Finley_NodeFile_getFirstNode(mesh_p->Nodes);
341                 fprintf(fileHandle_p,"%d ",mesh_p->Nodes->toReduced[elements->Nodes[INDEX2(j2, i, NN)]]);              myLastNode = Finley_NodeFile_getLastNode(mesh_p->Nodes);
342            }              globalNumPoints = Finley_NodeFile_getGlobalNumNodes(mesh_p->Nodes);
343            fprintf(fileHandle_p, "\n");              globalNodeIndex = Finley_NodeFile_borrowGlobalNodesIndex(mesh_p->Nodes);
344         }          }
345      } else if (VTK_QUADRATIC_HEXAHEDRON==cellType) {          myNumPoints = myLastNode - myFirstNode;
346            for (i = 0; i < numCells; i++) {          if (elementType==FINLEY_UNKNOWN) elementType=FINLEY_ELEMENTS;
347              fprintf(fileHandle_p,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",          switch(elementType) {
348                                 elements->Nodes[INDEX2(0, i, NN)],              case FINLEY_ELEMENTS:
349                                 elements->Nodes[INDEX2(1, i, NN)],                  elements = mesh_p->Elements;
350                                 elements->Nodes[INDEX2(2, i, NN)],              break;
351                                 elements->Nodes[INDEX2(3, i, NN)],              case FINLEY_FACE_ELEMENTS:
352                                 elements->Nodes[INDEX2(4, i, NN)],                  elements = mesh_p->FaceElements;
353                                 elements->Nodes[INDEX2(5, i, NN)],              break;
354                                 elements->Nodes[INDEX2(6, i, NN)],              case FINLEY_POINTS:
355                                 elements->Nodes[INDEX2(7, i, NN)],                  elements = mesh_p->Points;
356                                 elements->Nodes[INDEX2(8, i, NN)],              break;
357                                 elements->Nodes[INDEX2(9, i, NN)],              case FINLEY_CONTACT_ELEMENTS_1:
358                                 elements->Nodes[INDEX2(10, i, NN)],                  elements = mesh_p->ContactElements;
359                                 elements->Nodes[INDEX2(11, i, NN)],              break;
360                                 elements->Nodes[INDEX2(16, i, NN)],          }
361                                 elements->Nodes[INDEX2(17, i, NN)],          if (elements==NULL) {
362                                 elements->Nodes[INDEX2(18, i, NN)],              Finley_setError(SYSTEM_ERROR, "saveVTK: undefined element file");
363                                 elements->Nodes[INDEX2(19, i, NN)],          } else {
364                                 elements->Nodes[INDEX2(12, i, NN)],              /* map finley element type to VTK element type */
365                                 elements->Nodes[INDEX2(13, i, NN)],              numCells = elements->numElements;
366                                 elements->Nodes[INDEX2(14, i, NN)],              globalNumCells = Finley_ElementFile_getGlobalNumElements(elements);
367                                 elements->Nodes[INDEX2(15, i, NN)]);              myNumCells = Finley_ElementFile_getMyNumElements(elements);
368            }              myFirstCell = Finley_ElementFile_getFirstElement(elements);
369       } else if (numVTKNodesPerElement!=NN) {              NN = elements->numNodes;
370            for (i = 0; i < numCells; i++) {              if (nodeType==FINLEY_REDUCED_NODES) {
371              for (j = 0; j < numVTKNodesPerElement; j++) {                  typeId = elements->LinearReferenceElement->Type->TypeId;
372                   j2=elements->ReferenceElement->Type->geoNodes[j];                  if (hasReducedElements) {
373                   fprintf(fileHandle_p,"%d ", elements->Nodes[INDEX2(j2, i, NN)]);                      quadNodes_p=elements->LinearReferenceElementReducedOrder->QuadNodes;
374                    } else {
375                        quadNodes_p=elements->LinearReferenceElement->QuadNodes;
376                    }
377                } else {
378                    typeId = elements->ReferenceElement->Type->TypeId;
379                    if (hasReducedElements)
380                        quadNodes_p=elements->ReferenceElementReducedOrder->QuadNodes;
381                    else
382                        quadNodes_p=elements->ReferenceElement->QuadNodes;
383              }              }
384              fprintf(fileHandle_p, "\n");              switch (typeId) {
385            }                  case Point1:
386       } else {                  case Line2Face:
387            for (i = 0; i < numCells; i++) {                  case Line3Face:
388              for (j = 0; j < numVTKNodesPerElement; j++) fprintf(fileHandle_p,"%d ", elements->Nodes[INDEX2(j, i, NN)]);                  case Point1_Contact:
389              fprintf(fileHandle_p, "\n");                  case Line2Face_Contact:
390            }                  case Line3Face_Contact:
391       }                      cellType = VTK_VERTEX;
392      fprintf(fileHandle_p, "</DataArray>\n");                      numVTKNodesPerElement = 1;
393                    break;
394      /* write out the DataArray element for the offsets */  
395      fprintf(fileHandle_p, "<DataArray "                  case Line2:
396          "Name=\"offsets\" "                  case Tri3Face:
397          "type=\"Int32\" "                  case Rec4Face:
398          "format=\"ascii\">\n");                  case Line2_Contact:
399      for (i=numVTKNodesPerElement; i<=numCells*numVTKNodesPerElement; i+=numVTKNodesPerElement)                  case Tri3_Contact:
400          fprintf(fileHandle_p, "%d\n", i);                  case Tri3Face_Contact:
401      fprintf(fileHandle_p, "</DataArray>\n");                  case Rec4Face_Contact:
402                        cellType = VTK_LINE;
403      /* write out the DataArray element for the types */                      numVTKNodesPerElement = 2;
404      fprintf(fileHandle_p, "<DataArray "                  break;
405          "Name=\"types\" "  
406          "type=\"UInt8\" "                  case Tri3:
407          "format=\"ascii\">\n");                  case Tet4Face:
408      for (i=0; i<numCells; i++)                  case Tet4Face_Contact:
409          fprintf(fileHandle_p, "%d\n", cellType);                      cellType = VTK_TRIANGLE;
410      fprintf(fileHandle_p, "</DataArray>\n");                      numVTKNodesPerElement = 3;
411                    break;
412      /* finish off the <Cells> element */  
413      fprintf(fileHandle_p, "</Cells>\n");                  case Rec4:
414    }                  case Hex8Face:
415                    case Rec4_Contact:
416    /* data */                  case Hex8Face_Contact:
417    if (!isEmpty(data_p)) {                      cellType = VTK_QUAD;
418      int rank = getDataPointRank(data_p);                      numVTKNodesPerElement = 4;
419      int nComp = getDataPointSize(data_p);                  break;
420      /* barf if rank is greater than two */  
421      if (rank > 2) {                  case Rec9:
422        sprintf(error_msg, "saveVTK: Vtk can't handle objects with rank greater than 2. object rank = %d\n", rank);                      numCellFactor = 4;
423        Finley_setError(VALUE_ERROR,error_msg);                      cellType = VTK_QUAD;
424        return;                      numVTKNodesPerElement = 4;
425      }                  break;
426      /* if the rank == 0:   --> scalar data  
427       * if the rank == 1:   --> vector data                  case Tet4:
428       * if the rank == 2:   --> tensor data                      cellType = VTK_TETRA;
429       */                      numVTKNodesPerElement = 4;
430      char dataNameStr[31], dataTypeStr[63];                  break;
431      int nCompReqd=1;   /* the number of components required by vtk */  
432      if (rank == 0) {                  case Hex8:
433        strcpy(dataNameStr, "scalar");                      cellType = VTK_HEXAHEDRON;
434        sprintf(dataTypeStr, "Scalars=\"%s\"", dataNameStr);                      numVTKNodesPerElement = 8;
435        nCompReqd = 1;                  break;
436    
437                    case Line3:
438                    case Tri6Face:
439                    case Rec8Face:
440                    case Line3_Contact:
441                    case Tri6Face_Contact:
442                    case Rec8Face_Contact:
443                        cellType = VTK_QUADRATIC_EDGE;
444                        numVTKNodesPerElement = 3;
445                    break;
446    
447                    case Tri6:
448                    case Tet10Face:
449                    case Tri6_Contact:
450                    case Tet10Face_Contact:
451                        cellType = VTK_QUADRATIC_TRIANGLE;
452                        numVTKNodesPerElement = 6;
453                    break;
454    
455                    case Rec8:
456                    case Hex20Face:
457                    case Rec8_Contact:
458                    case Hex20Face_Contact:
459                        cellType = VTK_QUADRATIC_QUAD;
460                        numVTKNodesPerElement = 8;
461                    break;
462    
463                    case Tet10:
464                        cellType = VTK_QUADRATIC_TETRA;
465                        numVTKNodesPerElement = 10;
466                    break;
467    
468                    case Hex20:
469                        cellType = VTK_QUADRATIC_HEXAHEDRON;
470                        numVTKNodesPerElement = 20;
471                    break;
472    
473                    case Hex27:
474                        numCellFactor = 8;
475                        cellType = VTK_HEXAHEDRON;
476                        numVTKNodesPerElement = 8;
477                    break;
478    
479                    default:
480                        sprintf(errorMsg, "saveVTK: Element type %s is not supported by VTK.", elements->ReferenceElement->Type->Name);
481                        Finley_setError(VALUE_ERROR, errorMsg);
482                }
483            }
484      }      }
485      else if (rank == 1) {  
486        strcpy(dataNameStr, "vector");      /* allocate enough memory for text buffer */
487        sprintf(dataTypeStr, "Vectors=\"%s\"", dataNameStr);  
488        nCompReqd = 3;      txtBufferSize = strlen(vtkHeader) + 3*LEN_INT_FORMAT + (30+3*maxNameLen);
489    
490        if (mpi_size > 1) {
491            txtBufferSize = MAX(txtBufferSize, myNumPoints * LEN_TMP_BUFFER);
492            txtBufferSize = MAX(txtBufferSize, numCellFactor * myNumCells *
493                    (LEN_INT_FORMAT * numVTKNodesPerElement + 1));
494            txtBufferSize = MAX(txtBufferSize,
495                    numCellFactor * myNumCells * LEN_TENSOR_FORMAT);
496            txtBufferSize = MAX(txtBufferSize, myNumPoints * LEN_TENSOR_FORMAT);
497      }      }
498      else if (rank == 2) {      txtBuffer = TMPMEMALLOC(txtBufferSize+1, char);
499        strcpy(dataNameStr, "tensor");  
500        sprintf(dataTypeStr, "Tensors=\"%s\"", dataNameStr);      /* sets error if memory allocation failed */
501        nCompReqd = 9;      Finley_checkPtr(txtBuffer);
502    
503        /************************************************************************/
504        /* write number of points and the mesh component */
505    
506        if (Finley_noError()) {
507            const index_t *nodeIndex;
508            if (FINLEY_REDUCED_NODES == nodeType) {
509                nodeIndex = elements->ReferenceElement->Type->linearNodes;
510            } else if (Rec9 == typeId) {
511                nodeIndex = VTK_REC9_INDEX;
512            } else if (Hex20 == typeId) {
513                nodeIndex = VTK_HEX20_INDEX;
514            } else if (Hex27 == typeId) {
515                nodeIndex = VTK_HEX27_INDEX;
516            } else if (numVTKNodesPerElement != NN) {
517                nodeIndex = elements->ReferenceElement->Type->geoNodes;
518            } else {
519                nodeIndex = NULL;
520            }
521    
522            sprintf(txtBuffer, vtkHeader, globalNumPoints,
523                    numCellFactor*globalNumCells, 3);
524    
525            if (mpi_size > 1) {
526                /* write the nodes */
527                MPI_RANK0_WRITE_SHARED(txtBuffer);
528                txtBuffer[0] = '\0';
529                txtBufferInUse = 0;
530                if (nDim==2) {
531                    for (i = 0; i < mesh_p->Nodes->numNodes; i++) {
532                        if ( (myFirstNode <= globalNodeIndex[i]) && (globalNodeIndex[i] < myLastNode) ) {
533                            sprintf(tmpBuffer, VECTOR_FORMAT,
534                                mesh_p->Nodes->Coordinates[INDEX2(0, i, nDim)],
535                                mesh_p->Nodes->Coordinates[INDEX2(1, i, nDim)],
536                                0.);
537                            __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
538                        }
539                    }
540                } else {
541                    for (i = 0; i < mesh_p->Nodes->numNodes; i++) {
542                        if ( (myFirstNode <= globalNodeIndex[i]) && (globalNodeIndex[i] < myLastNode) ) {
543                            sprintf(tmpBuffer, VECTOR_FORMAT,
544                                mesh_p->Nodes->Coordinates[INDEX2(0, i, nDim)],
545                                mesh_p->Nodes->Coordinates[INDEX2(1, i, nDim)],
546                                mesh_p->Nodes->Coordinates[INDEX2(2, i, nDim)]);
547                            __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
548                        }
549                    }
550                } /* nDim */
551                MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
552    
553                /* write the cells */
554                MPI_RANK0_WRITE_SHARED(tags_End_Points_and_Start_Conn);
555                txtBuffer[0] = '\0';
556                txtBufferInUse = 0;
557                if (nodeIndex == NULL) {
558                    for (i = 0; i < numCells; i++) {
559                        if (elements->Owner[i] == my_mpi_rank) {
560                            for (j = 0; j < numVTKNodesPerElement; j++) {
561                                sprintf(tmpBuffer, INT_FORMAT, globalNodeIndex[elements->Nodes[INDEX2(j, i, NN)]]);
562                                __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
563                            }
564                            __STRCAT(txtBuffer, NEWLINE, txtBufferInUse);
565                        }
566                    }
567                } else {
568                    for (i = 0; i < numCells; i++) {
569                        if (elements->Owner[i] == my_mpi_rank) {
570                            for (l = 0; l < numCellFactor; l++) {
571                                const int* idx=&nodeIndex[l*numVTKNodesPerElement];
572                                for (j = 0; j < numVTKNodesPerElement; j++) {
573                                    sprintf(tmpBuffer, INT_FORMAT, globalNodeIndex[elements->Nodes[INDEX2(idx[j], i, NN)]]);
574                                    __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
575                                }
576                                __STRCAT(txtBuffer, NEWLINE, txtBufferInUse);
577                            }
578                        }
579                    }
580                } /* nodeIndex */
581                MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
582    
583                /* write the offsets */
584                MPI_RANK0_WRITE_SHARED(tags_End_Conn_and_Start_Offset);
585                txtBuffer[0] = '\0';
586                txtBufferInUse = 0;
587                for (i = numVTKNodesPerElement*(myFirstCell*numCellFactor+1);
588                        i <= (myFirstCell+myNumCells)*numVTKNodesPerElement*numCellFactor; i += numVTKNodesPerElement)
589                {
590                    sprintf(tmpBuffer, INT_NEWLINE_FORMAT, i);
591                    __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
592                }
593                MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
594    
595                /* write element type */
596                sprintf(tmpBuffer, INT_NEWLINE_FORMAT, cellType);
597                MPI_RANK0_WRITE_SHARED(tags_End_Offset_and_Start_Type);
598                txtBuffer[0] = '\0';
599                txtBufferInUse = 0;
600                for (i = numVTKNodesPerElement*(myFirstCell*numCellFactor+1);
601                        i <= (myFirstCell+myNumCells)*numVTKNodesPerElement*numCellFactor; i += numVTKNodesPerElement)
602                {
603                    __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
604                }
605                MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
606                /* finalize cell information */
607                strcpy(txtBuffer, "</DataArray>\n</Cells>\n");
608                MPI_RANK0_WRITE_SHARED(txtBuffer);
609    
610            } else { /***** mpi_size == 1 *****/
611    
612                /* write the nodes */
613                fputs(txtBuffer, fileHandle_p);
614                if (nDim==2) {
615                    for (i = 0; i < mesh_p->Nodes->numNodes; i++) {
616                        if ( (myFirstNode <= globalNodeIndex[i]) && (globalNodeIndex[i] < myLastNode) ) {
617                            fprintf(fileHandle_p, VECTOR_FORMAT,
618                                mesh_p->Nodes->Coordinates[INDEX2(0, i, nDim)],
619                                mesh_p->Nodes->Coordinates[INDEX2(1, i, nDim)],
620                                0.);
621                        }
622                    }
623                } else {
624                    for (i = 0; i < mesh_p->Nodes->numNodes; i++) {
625                        if ( (myFirstNode <= globalNodeIndex[i]) && (globalNodeIndex[i] < myLastNode) ) {
626                            fprintf(fileHandle_p, VECTOR_FORMAT,
627                                mesh_p->Nodes->Coordinates[INDEX2(0, i, nDim)],
628                                mesh_p->Nodes->Coordinates[INDEX2(1, i, nDim)],
629                                mesh_p->Nodes->Coordinates[INDEX2(2, i, nDim)]);
630                        }
631                    }
632                } /* nDim */
633    
634                /* write the cells */
635                fputs(tags_End_Points_and_Start_Conn, fileHandle_p);
636                if (nodeIndex == NULL) {
637                    for (i = 0; i < numCells; i++) {
638                        for (j = 0; j < numVTKNodesPerElement; j++) {
639                            fprintf(fileHandle_p, INT_FORMAT, globalNodeIndex[elements->Nodes[INDEX2(j, i, NN)]]);
640                        }
641                        fprintf(fileHandle_p, NEWLINE);
642                    }
643                } else {
644                    for (i = 0; i < numCells; i++) {
645                        for (l = 0; l < numCellFactor; l++) {
646                            const int* idx=&nodeIndex[l*numVTKNodesPerElement];
647                            for (j = 0; j < numVTKNodesPerElement; j++) {
648                                fprintf(fileHandle_p, INT_FORMAT, globalNodeIndex[elements->Nodes[INDEX2(idx[j], i, NN)]]);
649                            }
650                            fprintf(fileHandle_p, NEWLINE);
651                        }
652                    }
653                } /* nodeIndex */
654    
655                /* write the offsets */
656                fputs(tags_End_Conn_and_Start_Offset, fileHandle_p);
657                for (i = numVTKNodesPerElement; i <= numCells*numVTKNodesPerElement*numCellFactor; i += numVTKNodesPerElement) {
658                    fprintf(fileHandle_p, INT_NEWLINE_FORMAT, i);
659                }
660    
661                /* write element type */
662                sprintf(tmpBuffer, INT_NEWLINE_FORMAT, cellType);
663                fputs(tags_End_Offset_and_Start_Type, fileHandle_p);
664                for (i = 0; i < numCells*numCellFactor; i++)
665                    fputs(tmpBuffer, fileHandle_p);
666                /* finalize cell information */
667                fputs("</DataArray>\n</Cells>\n", fileHandle_p);
668            } /* mpi_size */
669    
670        } /* Finley_noError */
671    
672        /************************************************************************/
673        /* write cell data */
674    
675        if (writeCellData && Finley_noError()) {
676            bool_t set_scalar=FALSE, set_vector=FALSE, set_tensor=FALSE;
677            /* mark the active data arrays */
678            strcpy(txtBuffer, "<CellData");
679            for (dataIdx = 0; dataIdx < num_data; dataIdx++) {
680                if (!isEmpty(data_pp[dataIdx]) && isCellCentered[dataIdx]) {
681                    /* rank == 0 <--> scalar data */
682                    /* rank == 1 <--> vector data */
683                    /* rank == 2 <--> tensor data */
684                    switch (getDataPointRank(data_pp[dataIdx])) {
685                        case 0:
686                            if (!set_scalar) {
687                                strcat(txtBuffer, " Scalars=\"");
688                                strcat(txtBuffer, names_p[dataIdx]);
689                                strcat(txtBuffer, "\"");
690                                set_scalar = TRUE;
691                            }
692                        break;
693                        case 1:
694                            if (!set_vector) {
695                                strcat(txtBuffer, " Vectors=\"");
696                                strcat(txtBuffer, names_p[dataIdx]);
697                                strcat(txtBuffer, "\"");
698                                set_vector = TRUE;
699                            }
700                        break;
701                        case 2:
702                            if (!set_tensor) {
703                                strcat(txtBuffer, " Tensors=\"");
704                                strcat(txtBuffer, names_p[dataIdx]);
705                                strcat(txtBuffer, "\"");
706                                set_tensor = TRUE;
707                            }
708                        break;
709                        default:
710                            sprintf(errorMsg, "saveVTK: data %s: VTK supports data with rank <= 2 only.", names_p[dataIdx]);
711                            Finley_setError(VALUE_ERROR, errorMsg);
712                    }
713                }
714                if (!Finley_noError())
715                    break;
716            }
717      }      }
718      /* if have cell centred data then use CellData element,      /* only continue if no error occurred */
719       * if have node centred data, then use PointData element      if (writeCellData && Finley_noError()) {
720       */          strcat(txtBuffer, ">\n");
721      if (isCellCentered) {          if ( mpi_size > 1) {
722        /* now for the cell data */              MPI_RANK0_WRITE_SHARED(txtBuffer);
723        fprintf(fileHandle_p, "<CellData %s>\n", dataTypeStr);          } else {
724        fprintf(fileHandle_p,              fputs(txtBuffer, fileHandle_p);
725            "<DataArray "          }
726            "Name=\"%s\" "  
727            "type=\"Float32\" "          /* write the arrays */
728            "NumberOfComponents=\"%d\" "          for (dataIdx = 0; dataIdx < num_data; dataIdx++) {
729            "format=\"ascii\">\n",              if (!isEmpty(data_pp[dataIdx]) && isCellCentered[dataIdx]) {
730            dataNameStr, nCompReqd);                  dim_t numPointsPerSample=getNumDataPointsPerSample(data_pp[dataIdx]);
731        int numPointsPerSample = elements->ReferenceElement->numQuadNodes;                  dim_t rank = getDataPointRank(data_pp[dataIdx]);
732        if (numPointsPerSample) {                  dim_t nComp = getDataPointSize(data_pp[dataIdx]);
733      int shape = getDataPointShape(data_p, 0);                  dim_t nCompReqd = 1; /* number of components mpi_required */
734      if (shape > 3) {                  if (rank == 0) {
735          sprintf(error_msg,"saveVTK: shape should be 1, 2, or 3; I got %d\n", shape);                      nCompReqd = 1;
736              Finley_setError(VALUE_ERROR,error_msg);                      shape = 0;
737          return;                  } else if (rank == 1) {
738      }                      nCompReqd = 3;
739      for (i=0; i<numCells; i++) {                      shape = getDataPointShape(data_pp[dataIdx], 0);
740        values = getSampleData(data_p, i);                      if (shape > 3) {
741        double sampleAvg[nComp];                          Finley_setError(VALUE_ERROR, "saveVTK: rank 1 objects must have 3 components at most.");
742        for (k=0; k<nComp; k++) {                      }
743          /* averaging over the number of points in the sample */                  } else {
744          rtmp = 0.;                      nCompReqd = 9;
745          for (j=0; j<numPointsPerSample; j++)                      shape = getDataPointShape(data_pp[dataIdx], 0);
746            rtmp += values[INDEX2(k,j,nComp)];                      if (shape > 3 || shape != getDataPointShape(data_pp[dataIdx], 1)) {
747          sampleAvg[k] = rtmp/numPointsPerSample;                          Finley_setError(VALUE_ERROR, "saveVTK: rank 2 objects of shape 2x2 or 3x3 supported only.");
748        }                      }
749        /* if the number of required components is more than the number                  }
750         * of actual components, pad with zeros                  /* bail out if an error occurred */
751         */                  if (!Finley_noError())
752        /* probably only need to get shape of first element */                      break;
753        /* write the data different ways for scalar, vector and tensor */  
754        if (nCompReqd == 1) {                  sprintf(txtBuffer, tag_Float_DataArray, names_p[dataIdx], nCompReqd);
755          fprintf(fileHandle_p, " %e", sampleAvg[0]);                  if ( mpi_size > 1) {
756        } else if (nCompReqd == 3) {                      MPI_RANK0_WRITE_SHARED(txtBuffer);
757          /* write out the data */                  } else {
758          for (int m=0; m<shape; m++) {                      fputs(txtBuffer, fileHandle_p);
759            fprintf(fileHandle_p, " %e", sampleAvg[m]);                  }
760          }  
761          /* pad with zeros */                  txtBuffer[0] = '\0';
762          for (int m=0; m<nCompReqd-shape; m++)                  txtBufferInUse = 0;
763            fprintf(fileHandle_p, " %e", 0.);                  for (i=0; i<numCells; i++) {
764        } else if (nCompReqd == 9) {                      if (elements->Owner[i] == my_mpi_rank) {
765          /* tensor data, so have a 3x3 matrix to output as a row                          double *values = getSampleData(data_pp[dataIdx], i);
766           * of 9 data points */                          for (l = 0; l < numCellFactor; l++) {
767          int count = 0;                              double sampleAvg[NCOMP_MAX];
768          for (int m=0; m<shape; m++) {                              dim_t nCompUsed = MIN(nComp, NCOMP_MAX);
769            for (int n=0; n<shape; n++) {  
770          fprintf(fileHandle_p, " %e", sampleAvg[count]);                              /* average over number of points in the sample */
771          count++;                              if (isExpanded(data_pp[dataIdx])) {
772            }                                  dim_t hits=0, hits_old;
773            for (int n=0; n<3-shape; n++)                                  for (k=0; k<nCompUsed; k++) sampleAvg[k]=0;
774              fprintf(fileHandle_p, " %e", 0.);                                  for (j=0; j<numPointsPerSample; j++) {
775          }                                      hits_old=hits;
776          for (int m=0; m<3-shape; m++) {                                      if (nodeInQuadrant(quadNodes_p, typeId, j, l)) {
777              for (int n=0; n<3; n++)                                          hits++;
778                 fprintf(fileHandle_p, " %e", 0.);                                          for (k=0; k<nCompUsed; k++) {
779                                                sampleAvg[k] += values[INDEX2(k,j,nComp)];
780                                            }
781                                        }
782                                    }
783                                    for (k=0; k<nCompUsed; k++)
784                                        sampleAvg[k] /= MAX(hits, 1);
785                                } else {
786                                    for (k=0; k<nCompUsed; k++)
787                                        sampleAvg[k] = values[k];
788                                } /* isExpanded */
789    
790                                /* if the number of required components is more than
791                                 * the number of actual components, pad with zeros
792                                 */
793                                /* probably only need to get shape of first element */
794                                if (nCompReqd == 1) {
795                                    sprintf(tmpBuffer, SCALAR_FORMAT, sampleAvg[0]);
796                                } else if (nCompReqd == 3) {
797                                    if (shape==1) {
798                                        sprintf(tmpBuffer, VECTOR_FORMAT,
799                                            sampleAvg[0], 0.f, 0.f);
800                                    } else if (shape==2) {
801                                        sprintf(tmpBuffer, VECTOR_FORMAT,
802                                            sampleAvg[0], sampleAvg[1], 0.f);
803                                    } else if (shape==3) {
804                                        sprintf(tmpBuffer, VECTOR_FORMAT,
805                                            sampleAvg[0],sampleAvg[1],sampleAvg[2]);
806                                    }
807                                } else if (nCompReqd == 9) {
808                                    if (shape==1) {
809                                        sprintf(tmpBuffer, TENSOR_FORMAT,
810                                            sampleAvg[0], 0.f, 0.f,
811                                                     0.f, 0.f, 0.f,
812                                                     0.f, 0.f, 0.f);
813                                    } else if (shape==2) {
814                                        sprintf(tmpBuffer, TENSOR_FORMAT,
815                                            sampleAvg[0], sampleAvg[1], 0.f,
816                                            sampleAvg[2], sampleAvg[3], 0.f,
817                                                     0.f,          0.f, 0.f);
818                                    } else if (shape==3) {
819                                        sprintf(tmpBuffer, TENSOR_FORMAT,
820                                            sampleAvg[0],sampleAvg[1],sampleAvg[2],
821                                            sampleAvg[3],sampleAvg[4],sampleAvg[5],
822                                            sampleAvg[6],sampleAvg[7],sampleAvg[8]);
823                                    }
824                                }
825                                if ( mpi_size > 1) {
826                                    __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
827                                } else {
828                                    fputs(tmpBuffer, fileHandle_p);
829                                }
830                            } /* for l (numCellFactor) */
831                        } /* if I am the owner */
832                    } /* for i (numCells) */
833    
834                    if ( mpi_size > 1) {
835                        MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
836                        MPI_RANK0_WRITE_SHARED(tag_End_DataArray);
837                    } else {
838                        fputs(tag_End_DataArray, fileHandle_p);
839                    }
840                } /* !isEmpty && cellCentered */
841            } /* for dataIdx */
842    
843            strcpy(txtBuffer, "</CellData>\n");
844            if ( mpi_size > 1) {
845                MPI_RANK0_WRITE_SHARED(txtBuffer);
846            } else {
847                fputs(txtBuffer, fileHandle_p);
848            }
849        } /* if noError && writeCellData */
850    
851        /************************************************************************/
852        /* write point data */
853    
854        if (writePointData && Finley_noError()) {
855            /* mark the active data arrays */
856            bool_t set_scalar=FALSE, set_vector=FALSE, set_tensor=FALSE;
857            strcpy(txtBuffer, "<PointData");
858            for (dataIdx = 0; dataIdx<num_data; dataIdx++) {
859                if (!isEmpty(data_pp[dataIdx]) && !isCellCentered[dataIdx]) {
860                    switch (getDataPointRank(data_pp[dataIdx])) {
861                        case 0:
862                            if (!set_scalar) {
863                                strcat(txtBuffer, " Scalars=\"");
864                                strcat(txtBuffer, names_p[dataIdx]);
865                                strcat(txtBuffer, "\"");
866                                set_scalar = TRUE;
867                            }
868                        break;
869                        case 1:
870                            if (!set_vector) {
871                                strcat(txtBuffer, " Vectors=\"");
872                                strcat(txtBuffer, names_p[dataIdx]);
873                                strcat(txtBuffer, "\"");
874                                set_vector = TRUE;
875                            }
876                        break;
877                        case 2:
878                            if (!set_tensor) {
879                                strcat(txtBuffer, " Tensors=\"");
880                                strcat(txtBuffer, names_p[dataIdx]);
881                                strcat(txtBuffer, "\"");
882                                set_tensor = TRUE;
883                            }
884                        break;
885                        default:
886                            sprintf(errorMsg, "saveVTK: data %s: VTK supports data with rank <= 2 only.", names_p[dataIdx]);
887                            Finley_setError(VALUE_ERROR, errorMsg);
888                    }
889              }              }
890        }              if (!Finley_noError())
891        fprintf(fileHandle_p, "\n");                  break;
892      }          }
893        }      }
894        fprintf(fileHandle_p, "</DataArray>\n");      /* only continue if no error occurred */
895        fprintf(fileHandle_p, "</CellData>\n");      if (writePointData && Finley_noError()) {
896      } else {          strcat(txtBuffer, ">\n");
897        /* now for the point data */          if ( mpi_size > 1) {
898        fprintf(fileHandle_p, "<PointData %s>\n", dataTypeStr);              MPI_RANK0_WRITE_SHARED(txtBuffer);
899        fprintf(fileHandle_p, "<DataArray "          } else {
900            "Name=\"%s\" "              fputs(txtBuffer, fileHandle_p);
901            "type=\"Float32\" "          }
902            "NumberOfComponents=\"%d\" "  
903            "format=\"ascii\">\n",          /* write the arrays */
904            dataNameStr, nCompReqd);          for (dataIdx = 0; dataIdx < num_data; dataIdx++) {
905      /* write out the data */              if (!isEmpty(data_pp[dataIdx]) && !isCellCentered[dataIdx]) {
906      /* if the number of required components is more than the number                  Finley_NodeMapping* nodeMapping;
907       * of actual components, pad with zeros                  dim_t rank = getDataPointRank(data_pp[dataIdx]);
908         */                  dim_t nCompReqd = 1; /* number of components mpi_required */
909        bool_t do_write=TRUE;                  if (getFunctionSpaceType(data_pp[dataIdx]) == FINLEY_REDUCED_NODES) {
910        int shape = getDataPointShape(data_p, 0);                      nodeMapping = mesh_p->Nodes->reducedNodesMapping;
911        if (shape > 3) {                  } else {
912        sprintf(error_msg,"shape should be 1, 2, or 3; I got %d\n", shape);                      nodeMapping = mesh_p->Nodes->nodesMapping;
913            Finley_setError(VALUE_ERROR,error_msg);                  }
914        return;                  if (rank == 0) {
915        }                      nCompReqd = 1;
916        for (i=0; i<mesh_p->Nodes->numNodes; i++) {                      shape = 0;
917      switch (nodetype) {                  } else if (rank == 1) {
918      case(FINLEY_DEGREES_OF_FREEDOM):                      nCompReqd = 3;
919        values = getSampleData(data_p,mesh_p->Nodes->degreeOfFreedom[i]);                      shape = getDataPointShape(data_pp[dataIdx], 0);
920        break;                      if (shape > 3) {
921      case(FINLEY_REDUCED_DEGREES_OF_FREEDOM):                          Finley_setError(VALUE_ERROR, "saveVTK: rank 1 objects must have 3 components at most.");
922        if (mesh_p->Nodes->toReduced[i]>=0) {                      }
923              do_write=TRUE;                  } else {
924          values = getSampleData(data_p,mesh_p->Nodes->reducedDegreeOfFreedom[i]);                      nCompReqd = 9;
925        } else {                      shape=getDataPointShape(data_pp[dataIdx], 0);
926              do_write=FALSE;                      if (shape > 3 || shape != getDataPointShape(data_pp[dataIdx], 1)) {
927            }                          Finley_setError(VALUE_ERROR, "saveVTK: rank 2 objects of shape 2x2 or 3x3 supported only.");
928        break;                      }
929      case(FINLEY_NODES):                  }
930        values = getSampleData(data_p,i);                  /* bail out if an error occurred */
931        break;                  if (!Finley_noError())
932      }                      break;
933      /* write the data different ways for scalar, vector and tensor */  
934          if (do_write) {                  sprintf(txtBuffer, tag_Float_DataArray, names_p[dataIdx], nCompReqd);
935          if (nCompReqd == 1) {                  if ( mpi_size > 1) {
936            fprintf(fileHandle_p, " %e", values[0]);                      MPI_RANK0_WRITE_SHARED(txtBuffer);
937          }                  } else {
938          else if (nCompReqd == 3) {                      fputs(txtBuffer, fileHandle_p);
939            /* write out the data */                  }
940            for (int m=0; m<shape; m++)  
941              fprintf(fileHandle_p, " %e", values[m]);                  txtBuffer[0] = '\0';
942            /* pad with zeros */                  txtBufferInUse = 0;
943            for (int m=0; m<nCompReqd-shape; m++)                  for (i=0; i<mesh_p->Nodes->numNodes; i++) {
944                fprintf(fileHandle_p, " %e", 0.);                      k = globalNodeIndex[i];
945          }                      if ( (myFirstNode <= k) && (k < myLastNode) ) {
946          else if (nCompReqd == 9) {                          double *values = getSampleData(data_pp[dataIdx], nodeMapping->target[i]);
947            /* tensor data, so have a 3x3 matrix to output as a row                          /* if the number of mpi_required components is more than
948             * of 9 data points */                           * the number of actual components, pad with zeros.
949            int count = 0;                           * Probably only need to get shape of first element */
950            for (int m=0; m<shape; m++) {                          if (nCompReqd == 1) {
951              for (int n=0; n<shape; n++) {                              sprintf(tmpBuffer, SCALAR_FORMAT, values[0]);
952                fprintf(fileHandle_p, " %e", values[count]);                          } else if (nCompReqd == 3) {
953                count++;                              if (shape==1) {
954              }                                  sprintf(tmpBuffer, VECTOR_FORMAT,
955              for (int n=0; n<3-shape; n++)                                          values[0], 0.f, 0.f);
956                fprintf(fileHandle_p, " %e", 0.);                              } else if (shape==2) {
957            }                                  sprintf(tmpBuffer, VECTOR_FORMAT,
958            for (int m=0; m<3-shape; m++)  {                                          values[0], values[1], 0.f);
959                for (int n=0; n<3; n++)                              } else if (shape==3) {
960                    fprintf(fileHandle_p, " %e", 0.);                                  sprintf(tmpBuffer, VECTOR_FORMAT,
961                }                                          values[0], values[1], values[2]);
962          }                              }
963          fprintf(fileHandle_p, "\n");                          } else if (nCompReqd == 9) {
964           }                              if (shape==1) {
965        }                                  sprintf(tmpBuffer, TENSOR_FORMAT,
966        fprintf(fileHandle_p, "</DataArray>\n");                                      values[0], 0.f, 0.f,
967        fprintf(fileHandle_p, "</PointData>\n");                                            0.f, 0.f, 0.f,
968                                              0.f, 0.f, 0.f);
969                                } else if (shape==2) {
970                                    sprintf(tmpBuffer, TENSOR_FORMAT,
971                                        values[0], values[1], 0.f,
972                                        values[2], values[3], 0.f,
973                                              0.f,       0.f, 0.f);
974                                } else if (shape==3) {
975                                    sprintf(tmpBuffer, TENSOR_FORMAT,
976                                        values[0], values[1], values[2],
977                                        values[3], values[4], values[5],
978                                        values[6], values[7], values[8]);
979                                }
980                            }
981                            if ( mpi_size > 1) {
982                                __STRCAT(txtBuffer, tmpBuffer, txtBufferInUse);
983                            } else {
984                                fputs(tmpBuffer, fileHandle_p);
985                            }
986                        } /* if this is my node */
987                    } /* for i (numNodes) */
988    
989                    if ( mpi_size > 1) {
990                        MPI_WRITE_ORDERED(txtBuffer, txtBufferInUse);
991                        MPI_RANK0_WRITE_SHARED(tag_End_DataArray);
992                    } else {
993                        fputs(tag_End_DataArray, fileHandle_p);
994                    }
995                } /* !isEmpty && !isCellCentered */
996            } /* for dataIdx */
997    
998            strcpy(txtBuffer, "</PointData>\n");
999            if ( mpi_size > 1) {
1000                MPI_RANK0_WRITE_SHARED(txtBuffer);
1001            } else {
1002                fputs(txtBuffer, fileHandle_p);
1003            }
1004        } /* if noError && writePointData */
1005    
1006        /* Final write to VTK file */
1007        if (Finley_noError()) {
1008            if (mpi_size > 1) {
1009                MPI_RANK0_WRITE_SHARED(vtkFooter);
1010            } else {
1011                fputs(vtkFooter, fileHandle_p);
1012            }
1013      }      }
   }  
   
   /* finish off the piece */  
   fprintf(fileHandle_p, "</Piece>\n");  
1014    
1015    fprintf(fileHandle_p, "</UnstructuredGrid>\n");      if ( mpi_size > 1) {
1016    /* write the xml footer */  #ifdef PASO_MPI
1017    fprintf(fileHandle_p, "</VTKFile>\n");          MPI_File_close(&mpi_fileHandle_p);
1018    /* close the file */  #endif
1019    fclose(fileHandle_p);      } else {
1020    return;          fclose(fileHandle_p);
1021        }
1022        TMPMEMFREE(isCellCentered);
1023        TMPMEMFREE(txtBuffer);
1024  }  }
1025    
 /*  
  * Revision 1.6  2005/08/12 01:45:43  jgs  
  * erge of development branch dev-02 back to main trunk on 2005-08-12  
  *  
  * Revision 1.5.2.4  2005/09/09 08:15:17  gross  
  * bugs in vtk and dx writer fixed  
  *  
  * Revision 1.5.2.3  2005/09/08 08:28:39  gross  
  * some cleanup in savevtk  
  *  
  * Revision 1.5.2.2  2005/09/07 06:26:20  gross  
  * the solver from finley are put into the standalone package paso now  
  *  
  * Revision 1.5.2.1  2005/08/10 06:14:37  gross  
  * QUADRATIC HEXAHEDRON elements fixed  
  *  
  * Revision 1.5  2005/07/08 04:07:55  jgs  
  * Merge of development branch back to main trunk on 2005-07-08  
  *  
  * Revision 1.4  2005/05/06 04:26:15  jgs  
  * Merge of development branch back to main trunk on 2005-05-06  
  *  
  * Revision 1.1.2.7  2005/06/29 02:34:54  gross  
  * some changes towards 64 integers in finley  
  *  
  * Revision 1.1.2.6  2005/05/06 01:17:19  cochrane  
  * Fixed incorrect reporting of number of components in PointData arrays for  
  * vector data.  
  *  
  * Revision 1.1.2.5  2005/05/05 05:38:44  cochrane  
  * Improved formatting of VTK file output.  
  *  
  * Revision 1.1.2.4  2005/02/22 10:03:54  cochrane  
  * Implementation of writing of vtk xml files from finley.  This function will  
  * require more testing, but on the cases that I have tried (and with the help  
  * of Lutz and mayavi), it looks like it's producing the correct output.  Testing  
  * with more realistic data would be good.  I'm at least confident enough to  
  * commit my changes.  
  *  
  * Revision 1.1.2.3  2005/02/17 05:53:26  gross  
  * some bug in saveDX fixed: in fact the bug was in  
  * DataC/getDataPointShape  
  *  
  * Revision 1.1.2.2  2005/02/10 01:34:22  cochrane  
  * Quick fix to make sure that saveVTK compiles so that finley is still buildable.  Apologies to those this has affected.  
  *  
  * Revision 1.1.2.1  2005/02/09 06:53:15  cochrane  
  * Initial import to repository.  This is the file to implement saving finley/escript meshes out to vtk formatted files.  It is basically just a hack of the opendx equivalent, with a lot of the opendx stuff still in the file, so it doesn't actually work just yet, but it probably needs to be added to the cvs.  
  *  
  * Revision 1.1.1.1  2004/10/26 06:53:57  jgs  
  * initial import of project esys2  
  *  
  * Revision 1.1  2004/07/27 08:27:11  gross  
  * Finley: saveDX added: now it is possible to write data on boundary and contact elements  
  *  
  */  

Legend:
Removed from v.150  
changed lines
  Added in v.2141

  ViewVC Help
Powered by ViewVC 1.1.26