/[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

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

Legend:
Removed from v.1743  
changed lines
  Added in v.2548

  ViewVC Help
Powered by ViewVC 1.1.26