LCOV - code coverage report
Current view: top level - src/mesquite/Mesh - MeshImpl.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 489 1027 47.6 %
Date: 2020-07-18 00:09:26 Functions: 41 68 60.3 %
Branches: 841 4002 21.0 %

           Branch data     Line data    Source code
       1                 :            : /* *****************************************************************
       2                 :            :     MESQUITE -- The Mesh Quality Improvement Toolkit
       3                 :            : 
       4                 :            :     Copyright 2004 Sandia Corporation and Argonne National
       5                 :            :     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
       6                 :            :     with Sandia Corporation, the U.S. Government retains certain
       7                 :            :     rights in this software.
       8                 :            : 
       9                 :            :     This library is free software; you can redistribute it and/or
      10                 :            :     modify it under the terms of the GNU Lesser General Public
      11                 :            :     License as published by the Free Software Foundation; either
      12                 :            :     version 2.1 of the License, or (at your option) any later version.
      13                 :            : 
      14                 :            :     This library is distributed in the hope that it will be useful,
      15                 :            :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :            :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17                 :            :     Lesser General Public License for more details.
      18                 :            : 
      19                 :            :     You should have received a copy of the GNU Lesser General Public License
      20                 :            :     (lgpl.txt) along with this library; if not, write to the Free Software
      21                 :            :     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      22                 :            : 
      23                 :            :     [email protected], [email protected], [email protected],
      24                 :            :     [email protected], [email protected], [email protected],
      25                 :            :     [email protected]
      26                 :            : 
      27                 :            :   ***************************************************************** */
      28                 :            : //
      29                 :            : //   SUMMARY:
      30                 :            : //     USAGE:
      31                 :            : //
      32                 :            : // ORIG-DATE: 16-May-02 at 10:26:21
      33                 :            : //  LAST-MOD: 15-Nov-04 by [email protected]
      34                 :            : //
      35                 :            : /*! \file MeshImpl.cpp
      36                 :            : 
      37                 :            : \brief This files contains a mesh database implementation that can be used
      38                 :            : to run mesquite by default.
      39                 :            : 
      40                 :            :     \author Thomas Leurent
      41                 :            :     \author Darryl Melander
      42                 :            :     \author Jason Kraftcheck
      43                 :            :     \date 2004-11-15
      44                 :            :  */
      45                 :            : 
      46                 :            : #include "MeshImpl.hpp"
      47                 :            : #include "FileTokenizer.hpp"
      48                 :            : #include "Vector3D.hpp"
      49                 :            : #include "MsqVertex.hpp"
      50                 :            : #include "MeshImplData.hpp"
      51                 :            : #include "MeshImplTags.hpp"
      52                 :            : #include "MsqDebug.hpp"
      53                 :            : #include "MsqError.hpp"
      54                 :            : #include "VtkTypeInfo.hpp"
      55                 :            : 
      56                 :            : #include <string>
      57                 :            : #include <vector>
      58                 :            : #include <algorithm>
      59                 :            : #include <functional>
      60                 :            : #include <map>
      61                 :            : using std::string;
      62                 :            : using std::vector;
      63                 :            : 
      64                 :            : #include <fstream>
      65                 :            : #include <iomanip>
      66                 :            : using std::endl;
      67                 :            : using std::ifstream;
      68                 :            : using std::ofstream;
      69                 :            : 
      70                 :            : #ifdef MSQ_USING_EXODUS
      71                 :            : #include "exodusII.h"
      72                 :            : #endif
      73                 :            : 
      74                 :            : #include "MsqDebug.hpp"
      75                 :            : namespace MBMesquite
      76                 :            : {
      77                 :            : 
      78                 :            : const char* MESQUITE_FIELD_TAG = "MesquiteTags";
      79                 :            : 
      80 [ +  - ][ +  - ]:        143 : MeshImpl::MeshImpl() : numCoords( 0 ), myMesh( new MeshImplData ), myTags( new MeshImplTags ) {}
         [ +  - ][ +  - ]
      81                 :            : 
      82                 :        295 : MeshImpl::~MeshImpl()
      83                 :            : {
      84         [ +  - ]:        143 :     delete myMesh;
      85         [ +  - ]:        143 :     delete myTags;
      86         [ -  + ]:        152 : }
      87                 :            : 
      88                 :          0 : MeshImpl::MeshImpl( int num_nodes, int num_elem, EntityTopology entity_topology, const bool* fixed,
      89                 :            :                     const double* coords, const int* connectivity )
      90 [ #  # ][ #  # ]:          0 :     : numCoords( 3 ), myMesh( new MeshImplData ), myTags( new MeshImplTags )
         [ #  # ][ #  # ]
      91                 :            : {
      92         [ #  # ]:          0 :     MsqError err;
      93 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( num_nodes, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      94 [ #  # ][ #  # ]:          0 :     myMesh->allocate_elements( num_elem, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      95                 :            : 
      96                 :            :     // Fill in the data
      97         [ #  # ]:          0 :     if( fixed )
      98                 :            :     {
      99         [ #  # ]:          0 :         for( int i = 0; i < num_nodes; ++i )
     100                 :            :         {
     101 [ #  # ][ #  # ]:          0 :             myMesh->reset_vertex( i, Vector3D( coords + 3 * i ), fixed[i], err );
     102                 :            :         }
     103                 :            :     }
     104                 :            :     else
     105                 :            :     {
     106         [ #  # ]:          0 :         for( int i = 0; i < num_nodes; ++i )
     107                 :            :         {
     108 [ #  # ][ #  # ]:          0 :             myMesh->reset_vertex( i, Vector3D( coords + 3 * i ), false, err );
     109                 :            :         }
     110                 :            :     }
     111                 :            : 
     112         [ #  # ]:          0 :     const int verts_per_elem = TopologyInfo::corners( entity_topology );
     113                 :            : 
     114 [ #  # ][ #  # ]:          0 :     std::vector< long > connect( verts_per_elem );
     115                 :          0 :     const int* conn_iter = connectivity;
     116         [ #  # ]:          0 :     for( int i = 0; i < num_elem; i++, conn_iter += verts_per_elem )
     117                 :            :     {
     118         [ #  # ]:          0 :         std::copy( conn_iter, conn_iter + verts_per_elem, connect.begin() );
     119         [ #  # ]:          0 :         myMesh->reset_element( i, connect, entity_topology, err );
     120                 :          0 :     }
     121                 :            : }
     122                 :            : 
     123                 :          0 : MeshImpl::MeshImpl( int num_nodes, int num_elem, const EntityTopology* element_topologies, const bool* fixed,
     124                 :            :                     const double* coords, const int* connectivity )
     125 [ #  # ][ #  # ]:          0 :     : numCoords( 3 ), myMesh( new MeshImplData ), myTags( new MeshImplTags )
         [ #  # ][ #  # ]
     126                 :            : {
     127         [ #  # ]:          0 :     MsqError err;
     128 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( num_nodes, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     129 [ #  # ][ #  # ]:          0 :     myMesh->allocate_elements( num_elem, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     130                 :            : 
     131                 :            :     // Fill in the data
     132         [ #  # ]:          0 :     if( fixed )
     133                 :            :     {
     134         [ #  # ]:          0 :         for( int i = 0; i < num_nodes; ++i )
     135                 :            :         {
     136 [ #  # ][ #  # ]:          0 :             myMesh->reset_vertex( i, Vector3D( coords + 3 * i ), fixed[i], err );
     137                 :            :         }
     138                 :            :     }
     139                 :            :     else
     140                 :            :     {
     141         [ #  # ]:          0 :         for( int i = 0; i < num_nodes; ++i )
     142                 :            :         {
     143 [ #  # ][ #  # ]:          0 :             myMesh->reset_vertex( i, Vector3D( coords + 3 * i ), false, err );
     144                 :            :         }
     145                 :            :     }
     146                 :            : 
     147                 :          0 :     int num_indices = 0;
     148 [ #  # ][ #  # ]:          0 :     std::vector< long > connect;
     149                 :            : 
     150                 :            :     // Count the number of indices
     151                 :          0 :     const int* conn_iter = connectivity;
     152         [ #  # ]:          0 :     for( int i = 0; i < num_elem; ++i )
     153                 :            :     {
     154         [ #  # ]:          0 :         num_indices = TopologyInfo::corners( element_topologies[i] );
     155         [ #  # ]:          0 :         connect.resize( num_indices );
     156         [ #  # ]:          0 :         std::copy( conn_iter, conn_iter + num_indices, connect.begin() );
     157         [ #  # ]:          0 :         myMesh->reset_element( i, connect, element_topologies[i], err );
     158                 :          0 :         conn_iter += num_indices;
     159                 :          0 :     }
     160                 :            : }
     161                 :            : 
     162                 :        168 : void MeshImpl::clear()
     163                 :            : {
     164                 :        168 :     myMesh->clear();
     165                 :        168 :     myTags->clear();
     166                 :        168 : }
     167                 :            : 
     168                 :          0 : void MeshImpl::set_all_fixed_flags( bool value, MsqError& err )
     169                 :            : {
     170         [ #  # ]:          0 :     for( size_t i = 0; i < myMesh->max_vertex_index(); ++i )
     171                 :            :     {
     172         [ #  # ]:          0 :         if( myMesh->is_vertex_valid( i ) )
     173                 :            :         {
     174 [ #  # ][ #  # ]:          0 :             myMesh->fix_vertex( i, value, err );MSQ_ERRRTN( err );
                 [ #  # ]
     175                 :            :         }
     176                 :            :     }
     177                 :            : }
     178                 :            : 
     179                 :          0 : void MeshImpl::set_all_slaved_flags( bool, MsqError& err )
     180                 :            : {
     181         [ #  # ]:          0 :     for( size_t e = 0; e < myMesh->max_element_index(); ++e )
     182                 :            :     {
     183         [ #  # ]:          0 :         if( !myMesh->is_element_valid( e ) ) continue;
     184                 :            : 
     185                 :            :         // Get element connectivity
     186 [ #  # ][ #  # ]:          0 :         const std::vector< size_t >& verts = myMesh->element_connectivity( e, err );MSQ_ERRRTN( err );
                 [ #  # ]
     187                 :            : 
     188                 :            :         // Get element properties
     189 [ #  # ][ #  # ]:          0 :         EntityTopology type = myMesh->element_topology( e, err );MSQ_ERRRTN( err );
                 [ #  # ]
     190                 :          0 :         unsigned ncorner = TopologyInfo::corners( type );
     191                 :            : 
     192         [ #  # ]:          0 :         for( unsigned i = 0; i < ncorner; ++i )
     193                 :            :         {
     194 [ #  # ][ #  # ]:          0 :             myMesh->slave_vertex( verts[i], false, err );MSQ_ERRRTN( err );
                 [ #  # ]
     195                 :            :         }
     196         [ #  # ]:          0 :         for( unsigned i = ncorner; i < verts.size(); ++i )
     197                 :            :         {
     198 [ #  # ][ #  # ]:          0 :             myMesh->slave_vertex( verts[i], false, err );MSQ_ERRRTN( err );
                 [ #  # ]
     199                 :            :         }
     200                 :            :     }
     201                 :            : }
     202                 :            : 
     203                 :            : /**\brief Helper function for MeshImpl::mark_skin_fixed */
     204                 :          0 : static bool is_side_boundary( MeshImplData* myMesh, size_t elem, unsigned side_dim, unsigned side_num, MsqError& err )
     205                 :            : {
     206                 :            :     // Get the vertices of the side as indices into the above 'verts' list.
     207         [ #  # ]:          0 :     const EntityTopology type = myMesh->element_topology( elem, err );
     208 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     209                 :            :     unsigned n;  // number of vertices
     210         [ #  # ]:          0 :     const unsigned* conn = TopologyInfo::side_vertices( type, side_dim, side_num, n, err );
     211 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     212                 :            : 
     213                 :            :     // start with the assumption that the side is on the bounary
     214                 :          0 :     bool boundary = true;
     215                 :            : 
     216                 :            :     // get vertices in element connectivity
     217         [ #  # ]:          0 :     const std::vector< size_t >& verts = myMesh->element_connectivity( elem, err );
     218 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     219                 :            : 
     220                 :            :     // Choose one vertex in face, and get adjacent elements to that vertex
     221 [ #  # ][ #  # ]:          0 :     const std::vector< size_t >& elems = myMesh->vertex_adjacencies( verts[conn[0]], err );
     222 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     223                 :            : 
     224                 :            :     // For each adjacent element
     225         [ #  # ]:          0 :     for( unsigned i = 0; i < elems.size(); ++i )
     226                 :            :     {
     227                 :            :         // we want *other* adjacent elements
     228 [ #  # ][ #  # ]:          0 :         if( elems[i] == elem ) continue;
     229                 :            : 
     230                 :            :         // skip elements of smaller dimension
     231 [ #  # ][ #  # ]:          0 :         EntityTopology type2 = myMesh->element_topology( elems[i], err );
     232 [ #  # ][ #  # ]:          0 :         if( TopologyInfo::dimension( type2 ) <= side_dim ) continue;
     233                 :            : 
     234                 :            :         // get number of 'sides' of the appropriate dimension.
     235 [ #  # ][ #  # ]:          0 :         const std::vector< size_t >& verts2 = myMesh->element_connectivity( elems[i], err );
     236 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     237         [ #  # ]:          0 :         int sides2 = TopologyInfo::adjacent( type2, side_dim );
     238         [ #  # ]:          0 :         for( int j = 0; j < sides2; ++j )
     239                 :            :         {
     240 [ #  # ][ #  # ]:          0 :             if( TopologyInfo::compare_sides( (const size_t*)arrptr( verts ), type, side_num,
                 [ #  # ]
     241         [ #  # ]:          0 :                                              (const size_t*)arrptr( verts2 ), type2, j, side_dim, err ) )
     242                 :          0 :                 boundary = false;
     243 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
     244                 :            :         }
     245                 :            :     }
     246                 :            : 
     247                 :          0 :     return boundary;
     248                 :            : }
     249                 :            : 
     250                 :          0 : void MeshImpl::set_skin_flags( bool corner_fixed_flag, bool midnode_fixed_flag, bool midnode_slaved_flag,
     251                 :            :                                MsqError& err )
     252                 :            : {
     253                 :            :     // For each element, for each side of that element, check for
     254                 :            :     // an adjacent element.
     255         [ #  # ]:          0 :     for( size_t i = 0; i < myMesh->max_element_index(); ++i )
     256                 :            :     {
     257 [ #  # ][ #  # ]:          0 :         if( !myMesh->is_element_valid( i ) ) continue;
     258                 :            : 
     259                 :            :         // Get element connectivity
     260         [ #  # ]:          0 :         const std::vector< size_t >& verts = myMesh->element_connectivity( i, err );
     261                 :            : 
     262                 :            :         // Get element properties
     263         [ #  # ]:          0 :         EntityTopology type = myMesh->element_topology( i, err );
     264         [ #  # ]:          0 :         unsigned dim        = TopologyInfo::dimension( type );
     265         [ #  # ]:          0 :         int sides           = TopologyInfo::adjacent( type, dim - 1 );
     266                 :            :         bool midedge, midface, midvol;
     267 [ #  # ][ #  # ]:          0 :         TopologyInfo::higher_order( type, verts.size(), midedge, midface, midvol, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     268 [ #  # ][ #  # ]:          0 :         const bool midside    = ( dim == 2 && midedge ) || ( dim == 3 && midface );
         [ #  # ][ #  # ]
     269 [ #  # ][ #  # ]:          0 :         const bool midsubside = dim == 3 && midedge;
     270                 :            : 
     271                 :            :         // For each side of the element (each edge for surface elems,
     272                 :            :         // each face for volume elements)..
     273         [ #  # ]:          0 :         for( int j = 0; j < sides; ++j )
     274                 :            :         {
     275                 :            :             // Get the vertices of the side as indices into the above 'verts' list.
     276                 :            :             unsigned n;  // number of vertices
     277 [ #  # ][ #  # ]:          0 :             const unsigned* conn = TopologyInfo::side_vertices( type, dim - 1, j, n, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     278                 :            : 
     279                 :            :             // if side is on boundary, mark side vertices appropriately
     280 [ #  # ][ #  # ]:          0 :             bool boundary = is_side_boundary( myMesh, i, dim - 1, j, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     281         [ #  # ]:          0 :             if( boundary )
     282                 :            :             {
     283                 :            :                 // mark corner vertices as fixed
     284         [ #  # ]:          0 :                 for( unsigned k = 0; k < n; ++k )
     285                 :            :                 {
     286 [ #  # ][ #  # ]:          0 :                     myMesh->fix_vertex( verts[conn[k]], corner_fixed_flag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     287                 :            :                 }
     288                 :            : 
     289                 :            :                 // mark higher-order node in center of side as fixed
     290         [ #  # ]:          0 :                 if( midside )
     291                 :            :                 {
     292 [ #  # ][ #  # ]:          0 :                     unsigned idx = TopologyInfo::higher_order_from_side( type, verts.size(), dim - 1, j, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     293 [ #  # ][ #  # ]:          0 :                     myMesh->fix_vertex( verts[idx], midnode_fixed_flag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     294 [ #  # ][ #  # ]:          0 :                     myMesh->slave_vertex( verts[idx], midnode_slaved_flag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     295                 :            :                 }
     296                 :            : 
     297                 :            :                 // if side is a face, mark nodes on edges of face as fixed
     298         [ #  # ]:          0 :                 if( midsubside )
     299                 :            :                 {
     300         [ #  # ]:          0 :                     for( unsigned k = 0; k < n; ++k )
     301                 :            :                     {
     302                 :          0 :                         unsigned edge[2] = { conn[k], conn[( k + 1 ) % n] };
     303                 :            :                         bool r;
     304 [ #  # ][ #  # ]:          0 :                         unsigned edge_num = TopologyInfo::find_edge( type, edge, r, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     305                 :            : 
     306 [ #  # ][ #  # ]:          0 :                         unsigned idx = TopologyInfo::higher_order_from_side( type, verts.size(), 1, edge_num, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     307 [ #  # ][ #  # ]:          0 :                         myMesh->fix_vertex( verts[idx], midnode_fixed_flag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     308 [ #  # ][ #  # ]:          0 :                         myMesh->slave_vertex( verts[idx], midnode_slaved_flag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     309                 :            :                     }
     310                 :            :                 }
     311                 :            :             }
     312                 :            :         }  // for (j in sides)
     313                 :            :     }      // for (i in elems)
     314                 :            : }
     315                 :            : 
     316                 :          0 : void MeshImpl::mark_skin_fixed( MsqError& err, bool clear_existing )
     317                 :            : {
     318         [ #  # ]:          0 :     if( clear_existing )
     319                 :            :     {
     320 [ #  # ][ #  # ]:          0 :         set_all_fixed_flags( false, err );MSQ_ERRRTN( err );
                 [ #  # ]
     321                 :            :     }
     322                 :            : 
     323 [ #  # ][ #  # ]:          0 :     set_skin_flags( true, true, false, err );MSQ_ERRRTN( err );
                 [ #  # ]
     324                 :            : }
     325                 :            : 
     326                 :         15 : static void get_field_names( const TagDescription& tag, std::string& field_out, std::string& member_out, MsqError& err )
     327                 :            : {
     328                 :            :     std::string::size_type idx;
     329                 :            : 
     330         [ +  + ]:         15 :     if( tag.vtkType != TagDescription::FIELD )
     331                 :            :     {
     332                 :         11 :         field_out  = tag.name;
     333                 :         11 :         member_out = "";
     334                 :            :     }
     335         [ +  - ]:          4 :     else if( !tag.member.empty() )
     336                 :            :     {
     337                 :          4 :         field_out  = tag.name;
     338                 :          4 :         member_out = tag.member;
     339                 :            :     }
     340                 :            :     // If field is a struct, then the Mesquite tag name is a contcatenation
     341                 :            :     // of the field name and the struct member name.  Extract them.
     342                 :            :     else
     343                 :            :     {
     344                 :          0 :         idx = tag.name.find( " " );
     345         [ #  # ]:          0 :         if( idx == std::string::npos )
     346                 :            :         {
     347                 :          0 :             field_out  = tag.name;
     348                 :          0 :             member_out = MESQUITE_FIELD_TAG;
     349                 :            :         }
     350                 :            :         else
     351                 :            :         {
     352         [ #  # ]:          0 :             field_out  = tag.name.substr( 0, idx );
     353         [ #  # ]:          0 :             member_out = tag.name.substr( idx + 1 );
     354                 :            :         }
     355                 :            :     }
     356                 :            : 
     357                 :         15 :     idx = field_out.find( " " );
     358         [ -  + ]:         15 :     if( idx != std::string::npos ) MSQ_SETERR( err )
     359         [ #  # ]:          0 :     ( MsqError::FILE_FORMAT, "Cannot write tag name \"%s\" containing spaces to VTK file.", field_out.c_str() );
     360                 :            : 
     361                 :         15 :     idx = member_out.find( " " );
     362         [ -  + ]:         15 :     if( idx != std::string::npos ) MSQ_SETERR( err )
     363                 :            :     ( MsqError::FILE_FORMAT, "Cannot write field member name \"%s\" containing spaces to VTK file.",
     364         [ #  # ]:          0 :       member_out.c_str() );
     365                 :         15 : }
     366                 :            : 
     367                 :         61 : void MeshImpl::write_vtk( const char* out_filename, MsqError& err )
     368                 :            : {
     369 [ +  - ][ +  - ]:         61 :     ofstream file( out_filename );
     370 [ +  - ][ -  + ]:         61 :     if( !file )
     371                 :            :     {
     372 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( MsqError::FILE_ACCESS );
     373                 :          0 :         return;
     374                 :            :     }
     375                 :            : 
     376         [ +  - ]:         61 :     file.precision( 10 );
     377                 :            : 
     378                 :            :     // Write a header
     379         [ +  - ]:         61 :     file << "# vtk DataFile Version 3.0\n";
     380         [ +  - ]:         61 :     file << "Mesquite Mesh\n";
     381         [ +  - ]:         61 :     file << "ASCII\n";
     382         [ +  - ]:         61 :     file << "DATASET UNSTRUCTURED_GRID\n";
     383                 :            : 
     384                 :            :     // Write vertex coordinates
     385 [ +  - ][ +  - ]:         61 :     file << "POINTS " << myMesh->num_vertices() << " double\n";
         [ +  - ][ +  - ]
     386                 :            : 
     387 [ +  - ][ +  - ]:        122 :     std::vector< size_t > vertex_indices( myMesh->max_vertex_index() );
                 [ +  + ]
     388                 :         61 :     size_t i, count = 0;
     389 [ +  - ][ +  + ]:      14593 :     for( i = 0; i < myMesh->max_vertex_index(); ++i )
     390                 :            :     {
     391 [ +  - ][ +  - ]:      14532 :         if( myMesh->is_vertex_valid( i ) )
     392                 :            :         {
     393 [ +  - ][ +  - ]:      14532 :             Vector3D coords = myMesh->get_vertex_coords( i, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
     394 [ +  - ][ +  - ]:      14532 :             file << coords[0] << ' ' << coords[1] << ' ' << coords[2] << '\n';
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     395         [ +  - ]:      14532 :             vertex_indices[i] = count++;
     396                 :            :         }
     397                 :            :         else
     398                 :            :         {
     399 [ #  # ][ #  # ]:          0 :             vertex_indices[i] = myMesh->max_vertex_index();
     400                 :            :         }
     401                 :            :     }
     402                 :            : 
     403                 :            :     // Write out the connectivity table
     404                 :            :     size_t elem_idx;
     405 [ +  - ][ +  - ]:         61 :     size_t connectivity_size = myMesh->num_elements() + myMesh->num_vertex_uses();
     406 [ +  - ][ +  - ]:         61 :     file << "CELLS " << myMesh->num_elements() << ' ' << connectivity_size << '\n';
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     407 [ +  - ][ +  + ]:      48991 :     for( elem_idx = 0; elem_idx < myMesh->max_element_index(); ++elem_idx )
     408                 :            :     {
     409 [ +  - ][ -  + ]:      48930 :         if( !myMesh->is_element_valid( elem_idx ) ) continue;
     410                 :            : 
     411 [ +  - ][ +  - ]:      48930 :         std::vector< size_t > conn = myMesh->element_connectivity( elem_idx, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
     412 [ +  - ][ +  - ]:      48930 :         EntityTopology topo = myMesh->element_topology( elem_idx, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     413                 :            : 
     414                 :            :         // If necessary, convert from Exodus to VTK node-ordering.
     415 [ +  - ][ +  - ]:      48930 :         const VtkTypeInfo* info = VtkTypeInfo::find_type( topo, conn.size(), err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     416 [ +  - ][ +  - ]:      48930 :         if( info->msqType != POLYGON ) info->mesquiteToVtkOrder( conn );
     417                 :            : 
     418         [ +  - ]:      48930 :         file << conn.size();
     419         [ +  + ]:     242400 :         for( i = 0; i < conn.size(); ++i )
     420 [ +  - ][ +  - ]:     193470 :             file << ' ' << vertex_indices[(size_t)conn[i]];
         [ +  - ][ +  - ]
     421 [ +  - ][ +  - ]:      48930 :         file << '\n';
     422                 :      48930 :     }
     423                 :            : 
     424                 :            :     // Write out the element types
     425 [ +  - ][ +  - ]:         61 :     file << "CELL_TYPES " << myMesh->num_elements() << '\n';
         [ +  - ][ +  - ]
     426 [ +  - ][ +  + ]:      48991 :     for( elem_idx = 0; elem_idx < myMesh->max_element_index(); ++elem_idx )
     427                 :            :     {
     428 [ +  - ][ -  + ]:      48930 :         if( !myMesh->is_element_valid( elem_idx ) ) continue;
     429                 :            : 
     430 [ +  - ][ +  - ]:      48930 :         EntityTopology topo = myMesh->element_topology( elem_idx, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     431 [ +  - ][ +  - ]:      48930 :         count = myMesh->element_connectivity( elem_idx, err ).size();MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     432 [ +  - ][ +  - ]:      48930 :         const VtkTypeInfo* info = VtkTypeInfo::find_type( topo, count, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     433 [ +  - ][ +  - ]:      48930 :         file << info->vtkType << '\n';
     434                 :            :     }
     435                 :            : 
     436                 :            :     // Write out which points are fixed.
     437 [ +  - ][ +  - ]:         61 :     file << "POINT_DATA " << myMesh->num_vertices() << "\nSCALARS fixed int\nLOOKUP_TABLE default\n";
         [ +  - ][ +  - ]
     438 [ +  - ][ +  + ]:      14593 :     for( i = 0; i < myMesh->max_vertex_index(); ++i )
     439 [ +  - ][ +  - ]:      14532 :         if( myMesh->is_vertex_valid( i ) ) file << ( myMesh->vertex_is_fixed( i, err ) ? "1" : "0" ) << "\n";
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
     440                 :            : 
     441 [ +  - ][ -  + ]:         61 :     if( myMesh->have_slaved_flags() )
     442                 :            :     {
     443         [ #  # ]:          0 :         file << "SCALARS slaved int\nLOOKUP_TABLE default\n";
     444 [ #  # ][ #  # ]:          0 :         for( i = 0; i < myMesh->max_vertex_index(); ++i )
     445 [ #  # ][ #  # ]:          0 :             if( myMesh->is_vertex_valid( i ) ) file << ( myMesh->vertex_is_slaved( i, err ) ? "1" : "0" ) << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     446                 :            :     }
     447                 :            : 
     448                 :            :     // Make pass over the list of tags to:
     449                 :            :     // - Check if there are any tags on elements.
     450                 :            :     // - Get the list of field names by which to group tag data.
     451                 :            :     // - Assign VTK types for tags that have an unknown VTK type.
     452         [ +  - ]:         61 :     MeshImplTags::TagIterator tagiter;
     453 [ +  - ][ +  + ]:        122 :     std::multimap< std::string, size_t > fields;
     454                 :         61 :     bool have_elem_data = false;
     455 [ +  - ][ +  - ]:         74 :     for( tagiter = myTags->tag_begin(); tagiter != myTags->tag_end(); ++tagiter )
         [ +  - ][ +  - ]
                 [ +  + ]
     456                 :            :     {
     457 [ +  - ][ +  - ]:         13 :         bool haveelem = myTags->tag_has_element_data( *tagiter, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
     458         [ +  - ]:         13 :         if( haveelem ) have_elem_data = true;
     459                 :            : 
     460 [ +  - ][ +  - ]:         13 :         const TagDescription& desc = myTags->properties( *tagiter, err );
     461 [ +  - ][ +  - ]:         26 :         std::string field, member;
                 [ +  - ]
     462 [ +  - ][ +  - ]:         13 :         get_field_names( desc, field, member, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
     463 [ +  - ][ +  - ]:         13 :         fields.insert( std::multimap< std::string, size_t >::value_type( field, *tagiter ) );
         [ +  - ][ +  - ]
     464                 :         13 :     }
     465                 :            : 
     466                 :            :     // Write vertex tag data to vtk attributes, group by field.
     467                 :            :     // We already wrote the header line for the POINT_DATA block
     468                 :            :     // with the fixed flag, so just write the rest of the tags now.
     469 [ +  - ][ +  - ]:         61 :     std::multimap< std::string, size_t >::iterator f, e;
     470                 :         61 :     f = fields.begin();
     471 [ +  - ][ +  + ]:         74 :     while( f != fields.end() )
     472                 :            :     {
     473 [ +  - ][ +  - ]:         13 :         if( !myTags->tag_has_vertex_data( f->second, err ) )
                 [ +  + ]
     474                 :            :         {
     475         [ +  - ]:          4 :             ++f;
     476                 :          4 :             continue;
     477                 :            :         }
     478                 :            : 
     479                 :          9 :         int pcount = 0;
     480 [ +  - ][ +  - ]:         18 :         for( e = f; e != fields.end() && e->first == f->first; ++e )
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ +  +  #  # ]
     481 [ +  - ][ +  - ]:          9 :             if( myTags->tag_has_vertex_data( e->second, err ) ) ++pcount;
                 [ +  - ]
     482         [ -  + ]:          9 :         if( !pcount ) continue;
     483                 :            : 
     484 [ +  - ][ +  - ]:          9 :         if( myTags->properties( f->second, err ).vtkType == TagDescription::FIELD )
                 [ -  + ]
     485 [ #  # ][ #  # ]:          0 :             file << "FIELD " << f->first << " " << pcount << std::endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     486         [ -  + ]:          9 :         else if( pcount > 1 )
     487                 :            :         {
     488                 :            :             MSQ_SETERR( err )
     489                 :            :             ( MsqError::INTERNAL_ERROR, "Tag name \"%s\" conflicts with VTK field name in tag \"%s\"\n",
     490 [ #  # ][ #  # ]:          0 :               f->first.c_str(), myTags->properties( ( ++f )->second, err ).name.c_str() );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     491                 :          0 :             return;
     492                 :            :         }
     493                 :            : 
     494 [ +  - ][ +  - ]:         18 :         for( ; f != e; ++f )
                 [ +  + ]
     495                 :            :         {
     496 [ +  - ][ +  - ]:          9 :             if( !myTags->tag_has_vertex_data( f->second, err ) ) continue;
                 [ -  + ]
     497                 :            : 
     498 [ +  - ][ +  - ]:          9 :             const TagDescription& desc = myTags->properties( f->second, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
     499 [ +  - ][ +  - ]:          9 :             std::vector< char > tagdata( myMesh->num_vertices() * desc.size );
     500                 :          9 :             std::vector< char >::iterator iter = tagdata.begin();
     501 [ +  - ][ +  + ]:       1323 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
     502                 :            :             {
     503 [ +  - ][ +  - ]:       1314 :                 if( myMesh->is_vertex_valid( i ) )
     504                 :            :                 {
     505 [ +  - ][ +  - ]:       1314 :                     myTags->get_vertex_data( f->second, 1, &i, &*iter, err );
                 [ +  - ]
     506 [ +  - ][ -  + ]:       1314 :                     if( err.error_code() == MsqError::TAG_NOT_FOUND )
     507                 :            :                     {
     508         [ #  # ]:          0 :                         memset( &*iter, 0, desc.size );
     509         [ #  # ]:          0 :                         err.clear();
     510                 :            :                     }
     511 [ +  - ][ -  + ]:       1314 :                     else if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ -  + ]
     512                 :          0 :                         return;
     513         [ +  - ]:       1314 :                     iter += desc.size;
     514                 :            :                 }
     515                 :            :             }
     516 [ +  - ][ +  - ]:          9 :             vtk_write_attrib_data( file, desc, arrptr( tagdata ), myMesh->num_vertices(), err );MSQ_ERRRTN( err );
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
                 [ +  - ]
     517                 :          9 :         }
     518                 :            :     }
     519                 :            : 
     520                 :            :     // If no element tags, then done
     521         [ +  + ]:         61 :     if( !have_elem_data )
     522                 :            :     {
     523         [ +  - ]:         52 :         file.close();
     524                 :         52 :         return;
     525                 :            :     }
     526                 :            : 
     527                 :            :     // Begin element data section
     528 [ +  - ][ +  - ]:          9 :     file << "\nCELL_DATA " << myMesh->num_elements() << "\n";
         [ +  - ][ +  - ]
     529                 :            :     // Write element tag data to vtk attributes, group by field.
     530                 :          9 :     f = fields.begin();
     531 [ +  - ][ +  + ]:         22 :     while( f != fields.end() )
     532                 :            :     {
     533 [ +  - ][ +  - ]:         13 :         if( !myTags->tag_has_element_data( f->second, err ) )
                 [ -  + ]
     534                 :            :         {
     535         [ #  # ]:          0 :             ++f;
     536                 :          0 :             continue;
     537                 :            :         }
     538                 :            : 
     539                 :         13 :         int pcount = 0;
     540 [ +  - ][ +  - ]:         26 :         for( e = f; e != fields.end() && e->first == f->first; ++e )
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
           [ +  +  #  # ]
     541 [ +  - ][ +  - ]:         13 :             if( myTags->tag_has_element_data( e->second, err ) ) ++pcount;
                 [ +  - ]
     542         [ -  + ]:         13 :         if( !pcount ) continue;
     543                 :            : 
     544 [ +  - ][ +  - ]:         13 :         if( myTags->properties( f->second, err ).vtkType == TagDescription::FIELD )
                 [ +  + ]
     545 [ +  - ][ +  - ]:          2 :             file << "FIELD " << f->first << " " << pcount << std::endl;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     546         [ -  + ]:         11 :         else if( pcount > 1 )
     547                 :            :         {
     548                 :            :             MSQ_SETERR( err )
     549                 :            :             ( MsqError::INTERNAL_ERROR, "Tag name \"%s\" conflicts with VTK field name in tag \"%s\"\n",
     550 [ #  # ][ #  # ]:          0 :               f->first.c_str(), myTags->properties( ( ++f )->second, err ).name.c_str() );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     551                 :          0 :             return;
     552                 :            :         }
     553                 :            : 
     554 [ +  - ][ +  - ]:         26 :         for( ; f != e; ++f )
                 [ +  + ]
     555                 :            :         {
     556 [ +  - ][ +  - ]:         13 :             if( !myTags->tag_has_element_data( f->second, err ) ) continue;
                 [ -  + ]
     557                 :            : 
     558 [ +  - ][ +  - ]:         13 :             const TagDescription& desc = myTags->properties( f->second, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
     559 [ +  - ][ +  - ]:         13 :             std::vector< char > tagdata( myMesh->num_elements() * desc.size );
     560                 :         13 :             std::vector< char >::iterator iter = tagdata.begin();
     561 [ +  - ][ +  + ]:       2938 :             for( i = 0; i < myMesh->max_element_index(); ++i )
     562                 :            :             {
     563 [ +  - ][ +  - ]:       2925 :                 if( myMesh->is_element_valid( i ) )
     564                 :            :                 {
     565 [ +  - ][ +  - ]:       2925 :                     myTags->get_element_data( f->second, 1, &i, &*iter, err );
                 [ +  - ]
     566 [ +  - ][ +  + ]:       2925 :                     if( err.error_code() == MsqError::TAG_NOT_FOUND )
     567                 :            :                     {
     568         [ +  - ]:         10 :                         memset( &*iter, 0, desc.size );
     569         [ +  - ]:         10 :                         err.clear();
     570                 :            :                     }
     571 [ +  - ][ -  + ]:       2915 :                     else if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ -  + ]
     572                 :          0 :                         return;
     573         [ +  - ]:       2925 :                     iter += desc.size;
     574                 :            :                 }
     575                 :            :             }
     576 [ +  - ][ +  - ]:         13 :             vtk_write_attrib_data( file, desc, arrptr( tagdata ), myMesh->num_elements(), err );MSQ_ERRRTN( err );
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
                 [ +  - ]
     577                 :         13 :         }
     578                 :            :     }
     579                 :            : 
     580                 :            :     // Close the file
     581 [ +  - ][ +  + ]:        122 :     file.close();
     582                 :            : }
     583                 :            : 
     584                 :          0 : void MeshImpl::read_exodus( const char* in_filename, MsqError& err )
     585                 :            : {
     586                 :            : #ifndef MSQ_USING_EXODUS
     587         [ #  # ]:          0 :     MSQ_SETERR( err )( MsqError::NOT_IMPLEMENTED );
     588                 :            :     MSQ_DBGOUT( 1 ) << "Cannot read ExodusII file: " << in_filename << "\n";
     589                 :          0 :     return;
     590                 :            : #else
     591                 :            : 
     592                 :            :     clear();
     593                 :            : 
     594                 :            :     int app_float_size  = sizeof( double );
     595                 :            :     int file_float_size = 0;
     596                 :            :     float exo_version   = 0;
     597                 :            :     int exo_err         = 0;
     598                 :            : 
     599                 :            :     // Open the file
     600                 :            :     int file_id = ex_open( in_filename, EX_READ, &app_float_size, &file_float_size, &exo_version );
     601                 :            : 
     602                 :            :     // Make sure we opened the file correctly
     603                 :            :     if( file_id < 0 )
     604                 :            :     {
     605                 :            :         MSQ_SETERR( err )( MsqError::FILE_ACCESS );
     606                 :            :         return;
     607                 :            :     }
     608                 :            : 
     609                 :            :     // make sure the file is saved as doubles
     610                 :            :     if( file_float_size != sizeof( double ) )
     611                 :            :     {
     612                 :            :         MSQ_SETERR( err )
     613                 :            :         ( "File saved with float-sized reals.  Can only read files "
     614                 :            :           "saved with doubles.",
     615                 :            :           MsqError::NOT_IMPLEMENTED );
     616                 :            :         return;
     617                 :            :     }
     618                 :            : 
     619                 :            :     char title[MAX_LINE_LENGTH];
     620                 :            :     int dim, vert_count, elem_count, block_count, ns_count, ss_count;
     621                 :            : 
     622                 :            :     // get info about the file
     623                 :            :     exo_err = ex_get_init( file_id, title, &dim, &vert_count, &elem_count, &block_count, &ns_count, &ss_count );
     624                 :            :     if( exo_err < 0 )
     625                 :            :     {
     626                 :            :         MSQ_SETERR( err )( "Unable to get entity counts from file.", MsqError::PARSE_ERROR );
     627                 :            :         return;
     628                 :            :     }
     629                 :            : 
     630                 :            :     myMesh->allocate_vertices( vert_count, err );MSQ_ERRRTN( err );
     631                 :            :     myMesh->allocate_elements( elem_count, err );MSQ_ERRRTN( err );
     632                 :            : 
     633                 :            :     // Now fill in the data
     634                 :            : 
     635                 :            :     // Get the vertex coordinates
     636                 :            :     std::vector< double > coords( vert_count * 3 );
     637                 :            :     double* x_iter = arrptr( coords );
     638                 :            :     double* y_iter = &coords[vert_count];
     639                 :            :     double* z_iter = &coords[2 * vert_count];
     640                 :            :     numCoords      = dim;
     641                 :            :     if( dim == 2 )
     642                 :            :     {
     643                 :            :         exo_err = ex_get_coord( file_id, x_iter, y_iter, 0 );
     644                 :            :         memset( z_iter, 0, sizeof( double ) * vert_count );
     645                 :            :     }
     646                 :            :     else
     647                 :            :     {
     648                 :            :         exo_err = ex_get_coord( file_id, x_iter, y_iter, z_iter );
     649                 :            :     }
     650                 :            :     // Make sure it worked
     651                 :            :     if( exo_err < 0 )
     652                 :            :     {
     653                 :            :         MSQ_SETERR( err )
     654                 :            :         ( "Unable to retrieve vertex coordinates from file.", MsqError::PARSE_ERROR );
     655                 :            :         return;
     656                 :            :     }
     657                 :            : 
     658                 :            :     // Store vertex coordinates in vertex array
     659                 :            :     int i;
     660                 :            :     for( i = 0; i < vert_count; ++i )
     661                 :            :         myMesh->reset_vertex( i, Vector3D( *( x_iter++ ), *( y_iter++ ), *( z_iter )++ ), false, err );
     662                 :            :     coords.clear();
     663                 :            : 
     664                 :            :     // Get block list
     665                 :            :     std::vector< int > block_ids( block_count );
     666                 :            :     exo_err = ex_get_elem_blk_ids( file_id, arrptr( block_ids ) );
     667                 :            :     if( exo_err < 0 )
     668                 :            :     {
     669                 :            :         MSQ_SETERR( err )( "Unable to read block IDs from file.", MsqError::PARSE_ERROR );
     670                 :            :         return;
     671                 :            :     }
     672                 :            : 
     673                 :            :     std::vector< int > conn;
     674                 :            :     size_t index = 0;
     675                 :            :     for( i = 0; i < block_count; i++ )
     676                 :            :     {
     677                 :            :         // Get info about this block's elements
     678                 :            :         char elem_type_str[MAX_STR_LENGTH];
     679                 :            :         int num_block_elems, verts_per_elem, num_atts;
     680                 :            :         exo_err =
     681                 :            :             ex_get_elem_block( file_id, block_ids[i], elem_type_str, &num_block_elems, &verts_per_elem, &num_atts );
     682                 :            :         if( exo_err < 0 )
     683                 :            :         {
     684                 :            :             MSQ_SETERR( err )( "Unable to read parameters for block.", MsqError::PARSE_ERROR );
     685                 :            :             return;
     686                 :            :         }
     687                 :            : 
     688                 :            :         // Figure out which type of element we're working with
     689                 :            :         EntityTopology elem_type;
     690                 :            :         for( int j = 0; elem_type_str[j]; j++ )
     691                 :            :             elem_type_str[j] = toupper( elem_type_str[j] );
     692                 :            :         if( !strncmp( elem_type_str, "TRI", 3 ) ) { elem_type = TRIANGLE; }
     693                 :            :         else if( !strncmp( elem_type_str, "QUA", 3 ) || !strncmp( elem_type_str, "SHE", 3 ) )
     694                 :            :         {
     695                 :            :             elem_type = QUADRILATERAL;
     696                 :            :         }
     697                 :            :         else if( !strncmp( elem_type_str, "HEX", 3 ) )
     698                 :            :         {
     699                 :            :             elem_type = HEXAHEDRON;
     700                 :            :         }
     701                 :            :         else if( !strncmp( elem_type_str, "TET", 3 ) )
     702                 :            :         {
     703                 :            :             elem_type = TETRAHEDRON;
     704                 :            :         }
     705                 :            :         else if( !strncmp( elem_type_str, "PYRAMID", 7 ) )
     706                 :            :         {
     707                 :            :             elem_type = PYRAMID;
     708                 :            :         }
     709                 :            :         else if( !strncmp( elem_type_str, "WEDGE", 5 ) )
     710                 :            :         {
     711                 :            :             elem_type = PRISM;
     712                 :            :         }
     713                 :            :         else
     714                 :            :         {
     715                 :            :             MSQ_SETERR( err )
     716                 :            :             ( "Unrecognized element type in block", MsqError::UNSUPPORTED_ELEMENT );
     717                 :            :             continue;
     718                 :            :         }
     719                 :            : 
     720                 :            :         if( conn.size() < (unsigned)( num_block_elems * verts_per_elem ) )
     721                 :            :             conn.resize( num_block_elems * verts_per_elem );
     722                 :            :         exo_err = ex_get_elem_conn( file_id, block_ids[i], arrptr( conn ) );
     723                 :            :         if( exo_err < 0 )
     724                 :            :         {
     725                 :            :             MSQ_SETERR( err )
     726                 :            :             ( "Unable to read element block connectivity.", MsqError::PARSE_ERROR );
     727                 :            :             return;
     728                 :            :         }
     729                 :            : 
     730                 :            :         std::vector< size_t > vertices( verts_per_elem );
     731                 :            :         std::vector< int >::iterator conn_iter = conn.begin();
     732                 :            :         for( const size_t end = index + num_block_elems; index < end; ++index )
     733                 :            :         {
     734                 :            :             for( std::vector< size_t >::iterator iter = vertices.begin(); iter != vertices.end(); ++iter, ++conn_iter )
     735                 :            :                 *iter = *conn_iter - 1;
     736                 :            : 
     737                 :            :             myMesh->reset_element( index, vertices, elem_type, err );MSQ_CHKERR( err );
     738                 :            :         }
     739                 :            :     }
     740                 :            : 
     741                 :            :     // Finally, mark boundary nodes
     742                 :            :     int num_fixed_nodes = 0;
     743                 :            :     int num_dist_in_set = 0;
     744                 :            :     if( ns_count > 0 )
     745                 :            :     {
     746                 :            :         exo_err = ex_get_node_set_param( file_id, 111, &num_fixed_nodes, &num_dist_in_set );
     747                 :            :         if( exo_err < 0 )
     748                 :            :         {
     749                 :            :             MSQ_PRINT( 1 )( "\nError opening nodeset 111, no boundary nodes marked." );
     750                 :            :             num_fixed_nodes = 0;
     751                 :            :         }
     752                 :            :     }
     753                 :            :     std::vector< int > fixed_nodes( num_fixed_nodes );
     754                 :            :     if( num_fixed_nodes )
     755                 :            :     {
     756                 :            :         exo_err = ex_get_node_set( file_id, 111, arrptr( fixed_nodes ) );
     757                 :            :         if( exo_err < 0 ) { MSQ_SETERR( err )( "Error retrieving fixed nodes.", MsqError::PARSE_ERROR ); }
     758                 :            :     }
     759                 :            : 
     760                 :            :     // See if this vertex is marked as a boundary vertex
     761                 :            :     for( i = 0; i < num_fixed_nodes; ++i )
     762                 :            :     {
     763                 :            :         myMesh->fix_vertex( fixed_nodes[i] - 1, true, err );MSQ_CHKERR( err );
     764                 :            :     }
     765                 :            : 
     766                 :            :     // Finish up
     767                 :            :     exo_err = ex_close( file_id );
     768                 :            :     if( exo_err < 0 ) MSQ_SETERR( err )( "Error closing Exodus file.", MsqError::IO_ERROR );
     769                 :            : #endif
     770                 :            : }
     771                 :            : //! Writes an exodus file of the mesh.
     772                 :          0 : void MeshImpl::write_exodus( const char* out_filename, MsqError& err )
     773                 :            : {
     774                 :            :     // just return an error if we don't have access to exodus
     775                 :            : #ifndef MSQ_USING_EXODUS
     776         [ #  # ]:          0 :     MSQ_SETERR( err )( "Exodus not enabled in this build of Mesquite", MsqError::NOT_IMPLEMENTED );
     777                 :            :     MSQ_DBGOUT( 1 ) << "Cannot read ExodusII file: " << out_filename << "\n";
     778                 :          0 :     return;
     779                 :            : #else
     780                 :            :     size_t i, j, k;
     781                 :            :     if( !myMesh || !myMesh->num_vertices() )
     782                 :            :     {
     783                 :            :         MSQ_SETERR( err )
     784                 :            :         ( "No vertices in MeshImpl.  Nothing written to file.", MsqError::PARSE_ERROR );
     785                 :            :         return;
     786                 :            :     }
     787                 :            :     // get some element info
     788                 :            :     // We need to know how many of each element type we have.  We
     789                 :            :     // are going to create an element block for each element type
     790                 :            :     // that exists the mesh.  Block 1 will be tri3; block 2 will be
     791                 :            :     // shell; block 3 will be tetra, and block 4 will be hex.
     792                 :            :     const unsigned MAX_NODES = 27;
     793                 :            :     const unsigned MIN_NODES = 2;
     794                 :            :     int counts[MIXED][MAX_NODES + 1];
     795                 :            :     memset( counts, 0, sizeof( counts ) );
     796                 :            : 
     797                 :            :     for( i = 0; i < myMesh->max_element_index(); ++i )
     798                 :            :     {
     799                 :            :         if( !myMesh->is_element_valid( i ) ) continue;
     800                 :            : 
     801                 :            :         EntityTopology type = myMesh->element_topology( i, err );MSQ_ERRRTN( err );
     802                 :            :         unsigned nodes = myMesh->element_connectivity( i, err ).size();MSQ_ERRRTN( err );
     803                 :            :         if( (unsigned)type >= MIXED || nodes < MIN_NODES || nodes > MAX_NODES )
     804                 :            :         {
     805                 :            :             MSQ_SETERR( err )( "Invalid element typology.", MsqError::INTERNAL_ERROR );
     806                 :            :             return;
     807                 :            :         }
     808                 :            :         ++counts[type][nodes];
     809                 :            :     }
     810                 :            : 
     811                 :            :     // Count number of required element blocks
     812                 :            :     int block_count = 0;
     813                 :            :     for( i = 0; i < MIXED; ++i )
     814                 :            :         for( j = MIN_NODES; j < MAX_NODES; ++j )
     815                 :            :             if( counts[i][j] ) ++block_count;
     816                 :            : 
     817                 :            :     // figure out if we have fixed nodes, if so, we need a nodeset
     818                 :            :     int num_fixed_nodes = 0;
     819                 :            :     for( i = 0; i < myMesh->max_vertex_index(); ++i )
     820                 :            :     {
     821                 :            :         bool fixed = myMesh->is_vertex_valid( i ) && myMesh->vertex_is_fixed( i, err );MSQ_ERRRTN( err );
     822                 :            :         num_fixed_nodes += fixed;
     823                 :            :     }
     824                 :            : 
     825                 :            :     // write doubles instead of floats
     826                 :            :     int app_float_size  = sizeof( double );
     827                 :            :     int file_float_size = sizeof( double );
     828                 :            :     int exo_err         = 0;
     829                 :            : 
     830                 :            :     // Create the file.  If it exists, clobber it.  This could be dangerous.
     831                 :            :     int file_id = ex_create( out_filename, EX_CLOBBER, &app_float_size, &file_float_size );
     832                 :            : 
     833                 :            :     // Make sure we opened the file correctly
     834                 :            :     if( file_id < 0 )
     835                 :            :     {
     836                 :            :         MSQ_SETERR( err )( MsqError::FILE_ACCESS );
     837                 :            :         return;
     838                 :            :     }
     839                 :            : 
     840                 :            :     char title[MAX_LINE_LENGTH] = "Mesquite Export";
     841                 :            : 
     842                 :            :     size_t vert_count = myMesh->num_vertices();
     843                 :            :     size_t elem_count = myMesh->num_elements();
     844                 :            : 
     845                 :            :     int ns_count = 0;
     846                 :            :     if( num_fixed_nodes > 0 ) ns_count = 1;
     847                 :            :     int ss_count = 0;
     848                 :            : 
     849                 :            :     // put the initial info about the file
     850                 :            :     exo_err = ex_put_init( file_id, title, numCoords, vert_count, elem_count, block_count, ns_count, ss_count );
     851                 :            :     if( exo_err < 0 )
     852                 :            :     {
     853                 :            :         MSQ_SETERR( err )( "Unable to initialize file data.", MsqError::IO_ERROR );
     854                 :            :         return;
     855                 :            :     }
     856                 :            : 
     857                 :            :     // Gather vertex coordinate data and write to file.
     858                 :            :     std::vector< double > coords( vert_count * 3 );
     859                 :            :     std::vector< double >::iterator x, y, z;
     860                 :            :     x = coords.begin();
     861                 :            :     y = x + vert_count;
     862                 :            :     z = y + vert_count;
     863                 :            :     for( i = 0; i < myMesh->max_vertex_index(); ++i )
     864                 :            :     {
     865                 :            :         if( !myMesh->is_vertex_valid( i ) ) continue;
     866                 :            : 
     867                 :            :         if( z == coords.end() )
     868                 :            :         {
     869                 :            :             MSQ_SETERR( err )( "Array overflow", MsqError::INTERNAL_ERROR );
     870                 :            :             return;
     871                 :            :         }
     872                 :            : 
     873                 :            :         Vector3D coords = myMesh->get_vertex_coords( i, err );MSQ_ERRRTN( err );
     874                 :            :         *x = coords.x();
     875                 :            :         ++x;
     876                 :            :         *y = coords.y();
     877                 :            :         ++y;
     878                 :            :         *z = coords.z();
     879                 :            :         ++z;
     880                 :            :     }
     881                 :            :     if( z != coords.end() )
     882                 :            :     {
     883                 :            :         MSQ_SETERR( err )( "Counter at incorrect number.", MsqError::INTERNAL_ERROR );
     884                 :            :         return;
     885                 :            :     }
     886                 :            :     // put the coords
     887                 :            :     exo_err = ex_put_coord( file_id, arrptr( coords ), &coords[vert_count], &coords[2 * vert_count] );
     888                 :            :     if( exo_err < 0 )
     889                 :            :     {
     890                 :            :         MSQ_SETERR( err )( "Unable to put vertex coordinates in file.", MsqError::IO_ERROR );
     891                 :            :         return;
     892                 :            :     }
     893                 :            : 
     894                 :            :     // put the names of the coordinates
     895                 :            :     char* coord_names[] = { "x", "y", "z" };
     896                 :            :     exo_err             = ex_put_coord_names( file_id, coord_names );
     897                 :            : 
     898                 :            :     // Create element-type arrays indexed by EntityTopology
     899                 :            :     const char* tri_name  = "TRI";
     900                 :            :     const char* quad_name = "SHELL";
     901                 :            :     const char* tet_name  = "TETRA";
     902                 :            :     const char* hex_name  = "HEX";
     903                 :            :     const char* wdg_name  = "WEDGE";
     904                 :            :     const char* pyr_name  = "PYRAMID";
     905                 :            :     const char* exo_names[MIXED];
     906                 :            :     memset( exo_names, 0, sizeof( exo_names ) );
     907                 :            :     exo_names[TRIANGLE]      = tri_name;
     908                 :            :     exo_names[QUADRILATERAL] = quad_name;
     909                 :            :     exo_names[TETRAHEDRON]   = tet_name;
     910                 :            :     exo_names[HEXAHEDRON]    = hex_name;
     911                 :            :     exo_names[PRISM]         = wdg_name;
     912                 :            :     exo_names[PYRAMID]       = pyr_name;
     913                 :            :     unsigned min_nodes[MIXED];
     914                 :            :     memset( min_nodes, 0, sizeof( min_nodes ) );
     915                 :            :     min_nodes[TRIANGLE]      = 3;
     916                 :            :     min_nodes[QUADRILATERAL] = 4;
     917                 :            :     min_nodes[TETRAHEDRON]   = 4;
     918                 :            :     min_nodes[HEXAHEDRON]    = 8;
     919                 :            :     min_nodes[PRISM]         = 6;
     920                 :            :     min_nodes[PYRAMID]       = 5;
     921                 :            : 
     922                 :            :     // For each element type (topology and num nodes)
     923                 :            :     int block_id = 0;
     924                 :            :     char name_buf[16];
     925                 :            :     int num_atts = 0;
     926                 :            :     std::vector< int > conn;
     927                 :            :     for( i = 0; i < MIXED; ++i )
     928                 :            :     {
     929                 :            :         for( j = MIN_NODES; j < MAX_NODES; ++j )
     930                 :            :         {
     931                 :            :             // Have any of this topo & count combination?
     932                 :            :             if( !counts[i][j] ) continue;
     933                 :            : 
     934                 :            :             // Is a supported ExodusII type?
     935                 :            :             if( !exo_names[i] )
     936                 :            :             {
     937                 :            :                 MSQ_SETERR( err )
     938                 :            :                 ( MsqError::INVALID_STATE, "Element topology %d not supported by ExodusII", (int)i );
     939                 :            :                 return;
     940                 :            :             }
     941                 :            : 
     942                 :            :             // Construct ExodusII element name from topo & num nodes
     943                 :            :             if( j == min_nodes[i] )
     944                 :            :                 strcpy( name_buf, exo_names[i] );
     945                 :            :             else
     946                 :            :                 sprintf( name_buf, "%s%d", exo_names[i], (int)j );
     947                 :            : 
     948                 :            :             // Create element block
     949                 :            :             ++block_id;
     950                 :            :             exo_err = ex_put_elem_block( file_id, block_id, name_buf, counts[i][j], j, num_atts );
     951                 :            :             if( exo_err < 0 )
     952                 :            :             {
     953                 :            :                 MSQ_SETERR( err )( "Error creating the tri block.", MsqError::IO_ERROR );
     954                 :            :                 return;
     955                 :            :             }
     956                 :            : 
     957                 :            :             // For each element
     958                 :            :             conn.resize( counts[i][j] * j );
     959                 :            :             std::vector< int >::iterator iter = conn.begin();
     960                 :            :             for( k = 0; k < myMesh->max_element_index(); ++k )
     961                 :            :             {
     962                 :            :                 // If not correct topo, skip it.
     963                 :            :                 if( !myMesh->is_element_valid( k ) || (unsigned)( myMesh->element_topology( k, err ) ) != i ) continue;MSQ_ERRRTN( err );
     964                 :            : 
     965                 :            :                 // If not correct number nodes, skip it
     966                 :            :                 const std::vector< size_t >& elem_conn = myMesh->element_connectivity( k, err );MSQ_ERRRTN( err );
     967                 :            :                 if( elem_conn.size() != j ) continue;
     968                 :            : 
     969                 :            :                 // Append element connectivity to list
     970                 :            :                 for( std::vector< size_t >::const_iterator citer = elem_conn.begin(); citer != elem_conn.end();
     971                 :            :                      ++citer, ++iter )
     972                 :            :                 {
     973                 :            :                     assert( iter != conn.end() );
     974                 :            :                     *iter = *citer + 1;
     975                 :            :                 }
     976                 :            :             }
     977                 :            : 
     978                 :            :             // Make sure everything adds up
     979                 :            :             if( iter != conn.end() )
     980                 :            :             {
     981                 :            :                 MSQ_SETERR( err )( MsqError::INTERNAL_ERROR );
     982                 :            :                 return;
     983                 :            :             }
     984                 :            : 
     985                 :            :             // Write element block connectivity
     986                 :            :             exo_err = ex_put_elem_conn( file_id, block_id, arrptr( conn ) );
     987                 :            :             if( exo_err < 0 )
     988                 :            :             {
     989                 :            :                 MSQ_SETERR( err )( "Error writing element connectivity.", MsqError::IO_ERROR );
     990                 :            :                 return;
     991                 :            :             }
     992                 :            :         }
     993                 :            :     }
     994                 :            : 
     995                 :            :     // Finally, mark boundary nodes
     996                 :            : 
     997                 :            :     if( num_fixed_nodes > 0 )
     998                 :            :     {
     999                 :            :         exo_err = ex_put_node_set_param( file_id, 111, num_fixed_nodes, 0 );
    1000                 :            :         if( exo_err < 0 )
    1001                 :            :         {
    1002                 :            :             MSQ_SETERR( err )( "Error while initializing node set.", MsqError::IO_ERROR );
    1003                 :            :             return;
    1004                 :            :         }
    1005                 :            : 
    1006                 :            :         int node_id = 0;
    1007                 :            :         std::vector< int > fixed_nodes( num_fixed_nodes );
    1008                 :            :         std::vector< int >::iterator iter = fixed_nodes.begin();
    1009                 :            :         for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1010                 :            :         {
    1011                 :            :             if( !myMesh->is_vertex_valid( i ) ) continue;
    1012                 :            :             ++node_id;
    1013                 :            : 
    1014                 :            :             if( myMesh->vertex_is_fixed( i, err ) )
    1015                 :            :             {
    1016                 :            :                 if( iter == fixed_nodes.end() )
    1017                 :            :                 {
    1018                 :            :                     MSQ_SETERR( err )( MsqError::INTERNAL_ERROR );
    1019                 :            :                     return;
    1020                 :            :                 }
    1021                 :            :                 *iter = node_id;
    1022                 :            :                 ++iter;
    1023                 :            :             }
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :         if( iter != fixed_nodes.end() )
    1027                 :            :         {
    1028                 :            :             MSQ_SETERR( err )( MsqError::INTERNAL_ERROR );
    1029                 :            :             return;
    1030                 :            :         }
    1031                 :            : 
    1032                 :            :         exo_err = ex_put_node_set( file_id, 111, arrptr( fixed_nodes ) );
    1033                 :            :         if( exo_err < 0 )
    1034                 :            :         {
    1035                 :            :             MSQ_SETERR( err )( "Error while writing node set.", MsqError::IO_ERROR );
    1036                 :            :             return;
    1037                 :            :         }
    1038                 :            :     }
    1039                 :            :     exo_err = ex_close( file_id );
    1040                 :            :     if( exo_err < 0 ) MSQ_SETERR( err )( "Error closing Exodus file.", MsqError::IO_ERROR );
    1041                 :            : 
    1042                 :            : #endif
    1043                 :            : }
    1044                 :            : 
    1045                 :            : // Returns whether this mesh lies in a 2D or 3D coordinate system.
    1046                 :            : 
    1047                 :          0 : int MeshImpl::get_geometric_dimension( MsqError& /*err*/ )
    1048                 :            : {
    1049                 :          0 :     return numCoords;
    1050                 :            : }
    1051                 :            : 
    1052                 :       1154 : void MeshImpl::get_all_elements( std::vector< ElementHandle >& elems, MsqError& err )
    1053                 :            : {
    1054                 :            :     assert( sizeof( ElementHandle ) == sizeof( size_t ) );
    1055         [ +  - ]:        577 :     std::vector< size_t > temp;
    1056 [ +  - ][ +  - ]:       1154 :     myMesh->all_elements( temp, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1057         [ +  - ]:        577 :     elems.resize( temp.size() );
    1058 [ +  - ][ +  - ]:        577 :     if( !elems.empty() ) memcpy( arrptr( elems ), arrptr( temp ), sizeof( size_t ) * temp.size() );
         [ +  - ][ +  - ]
    1059                 :            : }
    1060                 :            : 
    1061                 :       1004 : void MeshImpl::get_all_vertices( std::vector< VertexHandle >& verts, MsqError& err )
    1062                 :            : {
    1063                 :            :     assert( sizeof( VertexHandle ) == sizeof( size_t ) );
    1064         [ +  - ]:        502 :     std::vector< size_t > temp;
    1065 [ +  - ][ +  - ]:       1004 :     myMesh->all_vertices( temp, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1066         [ +  - ]:        502 :     verts.resize( temp.size() );
    1067 [ +  - ][ +  - ]:        502 :     if( !verts.empty() ) memcpy( arrptr( verts ), arrptr( temp ), sizeof( size_t ) * temp.size() );
         [ +  - ][ +  - ]
    1068                 :            : }
    1069                 :            : 
    1070                 :            : // Returns a pointer to an iterator that iterates over the
    1071                 :            : // set of all vertices in this mesh.  The calling code should
    1072                 :            : // delete the returned iterator when it is finished with it.
    1073                 :            : // If vertices are added or removed from the Mesh after obtaining
    1074                 :            : // an iterator, the behavior of that iterator is undefined.
    1075                 :          0 : VertexIterator* MeshImpl::vertex_iterator( MsqError& /*err*/ )
    1076                 :            : {
    1077         [ #  # ]:          0 :     return new MeshImplVertIter( myMesh );
    1078                 :            : }
    1079                 :            : 
    1080                 :            : // Returns a pointer to an iterator that iterates over the
    1081                 :            : // set of all top-level elements in this mesh.  The calling code should
    1082                 :            : // delete the returned iterator when it is finished with it.
    1083                 :            : // If elements are added or removed from the Mesh after obtaining
    1084                 :            : // an iterator, the behavior of that iterator is undefined.
    1085                 :          0 : ElementIterator* MeshImpl::element_iterator( MsqError& /*err*/ )
    1086                 :            : {
    1087         [ #  # ]:          0 :     return new MeshImplElemIter( myMesh );
    1088                 :            : }
    1089                 :            : 
    1090                 :            : //************ Vertex Properties ********************
    1091                 :            : // Returns true or false, indicating whether the vertex
    1092                 :            : // is allowed to be repositioned.  True indicates that the vertex
    1093                 :            : // is fixed and cannot be moved.  Note that this is a read-only
    1094                 :            : // property; this flag can't be modified by users of the
    1095                 :            : // Mesh interface.
    1096                 :        274 : void MeshImpl::vertices_get_fixed_flag( const VertexHandle vert_array[], std::vector< bool >& on_bnd, size_t num_vtx,
    1097                 :            :                                         MsqError& err )
    1098                 :            : {
    1099                 :        274 :     on_bnd.resize( num_vtx );
    1100         [ +  + ]:     206877 :     for( size_t i = 0; i < num_vtx; ++i )
    1101                 :            :     {
    1102 [ -  + ][ #  # ]:     206603 :         on_bnd[i] = myMesh->vertex_is_fixed( (size_t)vert_array[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1103                 :            :     }
    1104                 :            : }
    1105                 :            : 
    1106                 :         15 : void MeshImpl::vertices_set_fixed_flag( const VertexHandle vert_array[], const std::vector< bool >& on_bnd,
    1107                 :            :                                         size_t num_vtx, MsqError& err )
    1108                 :            : {
    1109         [ -  + ]:         15 :     assert( on_bnd.size() >= num_vtx );
    1110         [ +  + ]:        219 :     for( size_t i = 0; i < num_vtx; ++i )
    1111                 :            :     {
    1112 [ -  + ][ #  # ]:        204 :         myMesh->fix_vertex( (size_t)vert_array[i], on_bnd[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1113                 :            :     }
    1114                 :            : }
    1115                 :         10 : void MeshImpl::vertices_get_slaved_flag( const VertexHandle vert_array[], std::vector< bool >& flags, size_t num_vtx,
    1116                 :            :                                          MsqError& err )
    1117                 :            : {
    1118                 :         10 :     flags.resize( num_vtx );
    1119         [ +  + ]:       1135 :     for( size_t i = 0; i < num_vtx; ++i )
    1120                 :            :     {
    1121 [ -  + ][ #  # ]:       1125 :         flags[i] = myMesh->vertex_is_slaved( (size_t)vert_array[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1122                 :            :     }
    1123                 :            : }
    1124                 :            : 
    1125                 :            : // Get/set location of a vertex
    1126                 :    2891478 : void MeshImpl::vertices_get_coordinates( const Mesh::VertexHandle vert_array[], MsqVertex* coordinates, size_t num_vtx,
    1127                 :            :                                          MsqError& err )
    1128                 :            : {
    1129         [ +  + ]:   18881549 :     for( size_t i = 0; i < num_vtx; ++i )
    1130                 :            :     {
    1131 [ -  + ][ #  # ]:   15990071 :         coordinates[i] = myMesh->get_vertex_coords( (size_t)vert_array[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1132                 :            :     }
    1133                 :            : }
    1134                 :            : 
    1135                 :     863023 : void MeshImpl::vertex_set_coordinates( VertexHandle vertex, const Vector3D& coordinates, MsqError& err )
    1136                 :            : {
    1137 [ -  + ][ #  # ]:     863023 :     myMesh->set_vertex_coords( (size_t)vertex, coordinates, err );MSQ_CHKERR( err );
    1138                 :     863023 : }
    1139                 :            : 
    1140                 :            : // Each vertex has a byte-sized flag that can be used to store
    1141                 :            : // flags.  This byte's value is neither set nor used by the mesh
    1142                 :            : // implementation.  It is intended to be used by Mesquite algorithms.
    1143                 :            : // Until a vertex's byte has been explicitly set, its value is 0.
    1144                 :    7512536 : void MeshImpl::vertex_set_byte( VertexHandle vertex, unsigned char byte, MsqError& err )
    1145                 :            : {
    1146 [ -  + ][ #  # ]:    7512536 :     vertices_set_byte( &vertex, &byte, 1, err );MSQ_CHKERR( err );
    1147                 :    7512536 : }
    1148                 :            : 
    1149                 :    2013359 : void MeshImpl::vertices_get_byte( const VertexHandle* vert_array, unsigned char* byte_array, size_t array_size,
    1150                 :            :                                   MsqError& err )
    1151                 :            : {
    1152         [ +  + ]:   11898636 :     for( size_t i = 0; i < array_size; i++ )
    1153                 :            :     {
    1154 [ -  + ][ #  # ]:    9885277 :         byte_array[i] = myMesh->get_vertex_byte( (size_t)vert_array[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1155                 :            :     }
    1156                 :            : }
    1157                 :            : 
    1158                 :            : // Retrieve the byte value for the specified vertex or vertices.
    1159                 :            : // The byte value is 0 if it has not yet been set via one of the
    1160                 :            : // *_set_byte() functions.
    1161                 :          0 : void MeshImpl::vertex_get_byte( const VertexHandle vertex, unsigned char* byte, MsqError& err )
    1162                 :            : {
    1163 [ #  # ][ #  # ]:          0 :     vertices_get_byte( &vertex, byte, 1, err );MSQ_CHKERR( err );
    1164                 :          0 : }
    1165                 :            : 
    1166                 :    7905407 : void MeshImpl::vertices_set_byte( const VertexHandle* vertex, const unsigned char* byte_array, size_t array_size,
    1167                 :            :                                   MsqError& err )
    1168                 :            : {
    1169         [ +  + ]:   17226967 :     for( size_t i = 0; i < array_size; i++ )
    1170                 :            :     {
    1171 [ -  + ][ #  # ]:    9321560 :         myMesh->set_vertex_byte( (size_t)vertex[i], byte_array[i], err );MSQ_ERRRTN( err );
                 [ -  + ]
    1172                 :            :     }
    1173                 :            : }
    1174                 :            : 
    1175                 :            : template < typename T >
    1176                 :            : struct cast_handle : public std::unary_function< size_t, T >
    1177                 :            : {
    1178                 :   21117880 :     T operator()( size_t idx ) const
    1179                 :            :     {
    1180                 :   21117880 :         return reinterpret_cast< T >( idx );
    1181                 :            :     }
    1182                 :            : };
    1183                 :            : 
    1184                 :     867911 : void MeshImpl::vertices_get_attached_elements( const VertexHandle* vertices, size_t num_vertices,
    1185                 :            :                                                std::vector< ElementHandle >& elements, std::vector< size_t >& offsets,
    1186                 :            :                                                MsqError& err )
    1187                 :            : {
    1188                 :     867911 :     elements.clear();
    1189                 :     867911 :     offsets.clear();
    1190                 :     867911 :     size_t prev_offset = 0;
    1191         [ +  - ]:     867911 :     offsets.reserve( num_vertices + 1 );
    1192         [ +  - ]:     867911 :     offsets.push_back( prev_offset );
    1193                 :     867911 :     const VertexHandle* const vtx_end = vertices + num_vertices;
    1194         [ +  + ]:    1735822 :     for( ; vertices < vtx_end; ++vertices )
    1195                 :            :     {
    1196 [ +  - ][ +  - ]:    1735822 :         const std::vector< size_t >& adj = myMesh->vertex_adjacencies( (size_t)*vertices, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1197                 :            : 
    1198                 :     867911 :         prev_offset = prev_offset + adj.size();
    1199         [ +  - ]:     867911 :         offsets.push_back( prev_offset );
    1200                 :            : 
    1201 [ +  - ][ +  - ]:     867911 :         std::transform( adj.begin(), adj.end(), std::back_inserter( elements ), cast_handle< ElementHandle >() );
    1202                 :            :     }
    1203                 :            : }
    1204                 :            : 
    1205                 :    1581491 : void MeshImpl::elements_get_attached_vertices( const ElementHandle* elements, size_t num_elems,
    1206                 :            :                                                std::vector< VertexHandle >& vertices, std::vector< size_t >& offsets,
    1207                 :            :                                                MsqError& err )
    1208                 :            : {
    1209                 :    1581491 :     vertices.clear();
    1210                 :    1581491 :     offsets.clear();
    1211                 :    1581491 :     size_t prev_offset = 0;
    1212         [ +  - ]:    1581491 :     offsets.reserve( num_elems + 1 );
    1213         [ +  - ]:    1581491 :     offsets.push_back( prev_offset );
    1214                 :    1581491 :     const ElementHandle* const elem_end = elements + num_elems;
    1215         [ +  + ]:    5966685 :     for( ; elements < elem_end; ++elements )
    1216                 :            :     {
    1217 [ +  - ][ +  - ]:    5966685 :         const std::vector< size_t >& conn = myMesh->element_connectivity( (size_t)*elements, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1218                 :            : 
    1219                 :    4385194 :         prev_offset = prev_offset + conn.size();
    1220         [ +  - ]:    4385194 :         offsets.push_back( prev_offset );
    1221                 :            : 
    1222 [ +  - ][ +  - ]:    4385194 :         std::transform( conn.begin(), conn.end(), std::back_inserter( vertices ), cast_handle< VertexHandle >() );
    1223                 :            :     }
    1224                 :            : }
    1225                 :            : 
    1226                 :            : // Returns the topologies of the given entities.  The "entity_topologies"
    1227                 :            : // array must be at least "num_elements" in size.
    1228                 :    1563888 : void MeshImpl::elements_get_topologies( const ElementHandle* element_handle_array, EntityTopology* element_topologies,
    1229                 :            :                                         size_t num_elements, MsqError& err )
    1230                 :            : {
    1231         [ +  + ]:    5941890 :     for( size_t i = 0; i < num_elements; i++ )
    1232                 :            :     {
    1233 [ -  + ][ #  # ]:    4378002 :         element_topologies[i] = myMesh->element_topology( (size_t)element_handle_array[i], err );MSQ_CHKERR( err );
    1234                 :            :     }
    1235                 :    1563888 : }
    1236                 :            : 
    1237                 :            : //**************** Memory Management ****************
    1238                 :            : // Tells the mesh that the client is finished with a given
    1239                 :            : // entity handle.
    1240                 :          0 : void MeshImpl::release_entity_handles( const EntityHandle* /*handle_array*/, size_t /*num_handles*/, MsqError& /*err*/ )
    1241                 :            : {
    1242                 :            :     // Do nothing
    1243                 :          0 : }
    1244                 :            : 
    1245                 :            : // Instead of deleting a Mesh when you think you are done,
    1246                 :            : // call release().  In simple cases, the implementation could
    1247                 :            : // just call the destructor.  More sophisticated implementations
    1248                 :            : // may want to keep the Mesh object to live longer than Mesquite
    1249                 :            : // is using it.
    1250                 :          0 : void MeshImpl::release()
    1251                 :            : {
    1252                 :            :     // delete this;
    1253                 :          0 : }
    1254                 :            : 
    1255                 :            : const char* const vtk_type_names[] = { "bit",          "char", "unsigned_char", "short", "unsigned_short", "int",
    1256                 :            :                                        "unsigned_int", "long", "unsigned_long", "float", "double",         0 };
    1257                 :            : 
    1258                 :        149 : void MeshImpl::read_vtk( const char* filename, MsqError& err )
    1259                 :            : {
    1260                 :            :     int major, minor;
    1261                 :            :     char vendor_string[257];
    1262                 :            :     size_t i;
    1263                 :            : 
    1264         [ +  - ]:        149 :     FILE* file = fopen( filename, "r" );
    1265         [ -  + ]:        149 :     if( !file )
    1266                 :            :     {
    1267 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( MsqError::FILE_ACCESS );
    1268                 :        149 :         return;
    1269                 :            :     }
    1270                 :            : 
    1271                 :            :     // Read file header
    1272                 :            : 
    1273 [ +  - ][ -  + ]:        149 :     if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
    1274                 :            :     {
    1275 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( MsqError::IO_ERROR );
    1276         [ #  # ]:          0 :         fclose( file );
    1277                 :          0 :         return;
    1278                 :            :     }
    1279                 :            : 
    1280 [ +  - ][ -  + ]:        149 :     if( !strchr( vendor_string, '\n' ) || 2 != sscanf( vendor_string, "# vtk DataFile Version %d.%d", &major, &minor ) )
                 [ -  + ]
    1281                 :            :     {
    1282 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( MsqError::FILE_FORMAT );
    1283         [ #  # ]:          0 :         fclose( file );
    1284                 :          0 :         return;
    1285                 :            :     }
    1286                 :            : 
    1287 [ +  - ][ -  + ]:        149 :     if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
    1288                 :            :     {
    1289 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( MsqError::IO_ERROR );
    1290         [ #  # ]:          0 :         fclose( file );
    1291                 :          0 :         return;
    1292                 :            :     }
    1293                 :            : 
    1294                 :            :     // VTK spec says this should not exceed 256 chars.
    1295         [ -  + ]:        149 :     if( !strchr( vendor_string, '\n' ) )
    1296                 :            :     {
    1297                 :            :         MSQ_SETERR( err )
    1298 [ #  # ][ #  # ]:          0 :         ( "Vendor string (line 2) exceeds 256 characters.", MsqError::PARSE_ERROR );
    1299         [ #  # ]:          0 :         fclose( file );
    1300                 :          0 :         return;
    1301                 :            :     }
    1302                 :            : 
    1303                 :            :     // Check file type
    1304                 :            : 
    1305         [ +  - ]:        149 :     FileTokenizer tokens( file );
    1306                 :        149 :     const char* const file_type_names[] = { "ASCII", "BINARY", 0 };
    1307 [ +  - ][ +  - ]:        149 :     int filetype                        = tokens.match_token( file_type_names, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1308         [ -  + ]:        149 :     if( 2 == filetype )
    1309                 :            :     {
    1310                 :            :         MSQ_SETERR( err )
    1311 [ #  # ][ #  # ]:          0 :         ( "Cannot read BINARY VTK files -- use ASCII.", MsqError::NOT_IMPLEMENTED );
    1312                 :          0 :         return;
    1313                 :            :     }
    1314                 :            : 
    1315                 :            :     // Clear any existing data
    1316         [ +  - ]:        149 :     this->clear();
    1317                 :            : 
    1318                 :        149 :     const char* outer_block_names[] = { "DATASET", "FIELD", 0 };
    1319                 :            :     // Read the mesh
    1320                 :            :     // VTK docs are inconsistant with regard to whether or not
    1321                 :            :     // a field block should be specified as "FIELD" or "DATASET FIELD",
    1322                 :            :     // so allow both.
    1323 [ +  - ][ +  + ]:        298 :     while( !tokens.eof() )
    1324                 :            :     {
    1325         [ +  - ]:        149 :         int blocktype = tokens.match_token( outer_block_names, err );
    1326 [ +  - ][ -  + ]:        149 :         if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ -  + ]
    1327                 :            :         {
    1328 [ #  # ][ #  # ]:          0 :             if( tokens.eof() )
    1329                 :            :             {
    1330         [ #  # ]:          0 :                 err.clear();
    1331                 :          0 :                 break;
    1332                 :            :             }
    1333                 :            :             else
    1334                 :          0 :                 return;
    1335                 :            :         }
    1336                 :            : 
    1337         [ +  - ]:        149 :         if( blocktype == 1 )
    1338                 :            :         {
    1339 [ +  - ][ +  - ]:        149 :             vtk_read_dataset( tokens, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1340                 :            :         }
    1341                 :            :         else
    1342                 :            :         {
    1343 [ #  # ][ #  # ]:          0 :             vtk_read_field( tokens, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1344                 :            :         }
    1345                 :            :     }
    1346                 :            : 
    1347                 :            :     // Make sure file actually contained some mesh
    1348 [ +  - ][ -  + ]:        149 :     if( myMesh->num_elements() == 0 )
    1349                 :            :     {
    1350 [ #  # ][ #  # ]:          0 :         MSQ_SETERR( err )( "File contained no mesh.", MsqError::PARSE_ERROR );
    1351                 :          0 :         return;
    1352                 :            :     }
    1353                 :            : 
    1354                 :            :     // There is no option for a 2-D mesh in VTK files.  Always 3
    1355                 :        149 :     numCoords = 3;
    1356                 :            : 
    1357                 :            :     // Convert tag data for fixed nodes to internal bitmap
    1358 [ +  - ][ +  - ]:        298 :     std::vector< bool > flags;
    1359 [ +  - ][ +  - ]:        149 :     tag_to_bool( "fixed", flags, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1360         [ +  + ]:        149 :     if( !flags.empty() )
    1361                 :            :     {
    1362 [ +  - ][ +  + ]:      54645 :         for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1363 [ +  - ][ +  - ]:      54645 :             myMesh->fix_vertex( i, flags[i], err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
    1364                 :            :     }
    1365                 :            : 
    1366                 :        149 :     flags.clear();
    1367 [ +  - ][ +  - ]:        149 :     tag_to_bool( "slaved", flags, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1368         [ +  + ]:        149 :     if( !flags.empty() )
    1369                 :            :     {
    1370 [ +  - ][ +  + ]:        488 :         for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1371 [ +  - ][ +  - ]:        633 :             myMesh->slave_vertex( i, flags[i], err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
    1372                 :        149 :     }
    1373                 :            : }
    1374                 :            : 
    1375                 :        298 : void MeshImpl::tag_to_bool( const char* tag_name, std::vector< bool >& values, MsqError& err )
    1376                 :            : {
    1377                 :            :     // Convert tag data for fixed nodes to internal bitmap
    1378 [ +  - ][ +  - ]:        298 :     TagHandle handle = tag_get( tag_name, err );
    1379 [ +  + ][ +  - ]:        298 :     if( !handle || MSQ_CHKERR( err ) )
         [ -  + ][ #  # ]
         [ #  # ][ +  + ]
    1380                 :            :     {
    1381         [ +  - ]:        152 :         err.clear();
    1382                 :        152 :         values.clear();
    1383                 :        298 :         return;
    1384                 :            :     }
    1385                 :            : 
    1386                 :            :     size_t i;
    1387 [ +  - ][ +  - ]:        146 :     values.resize( myMesh->max_vertex_index(), false );
    1388 [ +  - ][ +  - ]:        146 :     const TagDescription& tag_desc = myTags->properties( (size_t)handle, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1389 [ +  - ][ +  - ]:        146 :     bool havedata = myTags->tag_has_vertex_data( (size_t)handle, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1390         [ -  + ]:        146 :     if( !havedata )
    1391                 :            :     {
    1392                 :            :         MSQ_SETERR( err )
    1393 [ #  # ][ #  # ]:          0 :         ( MsqError::FILE_FORMAT, "'%s' attribute on elements, not vertices", tag_name );
    1394                 :          0 :         return;
    1395                 :            :     }
    1396                 :            : 
    1397   [ -  +  +  +  :        146 :     switch( tag_desc.type )
                   -  - ]
    1398                 :            :     {
    1399                 :            :         case BYTE: {
    1400                 :            :             char data;
    1401 [ #  # ][ #  # ]:          0 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1402                 :            :             {
    1403 [ #  # ][ #  # ]:          0 :                 myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1404         [ #  # ]:          0 :                 values[i] = !!data;
    1405                 :            :             }
    1406                 :          0 :             break;
    1407                 :            :         }
    1408                 :            :         case BOOL: {
    1409 [ +  - ][ +  + ]:       5074 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1410                 :            :             {
    1411                 :            :                 bool data;
    1412 [ +  - ][ +  - ]:       4999 :                 myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1413         [ +  - ]:       4999 :                 values[i] = data;
    1414                 :            :             }
    1415                 :         75 :             break;
    1416                 :            :         }
    1417                 :            :         case INT: {
    1418                 :            :             int data;
    1419 [ +  - ][ +  + ]:      13100 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1420                 :            :             {
    1421 [ +  - ][ +  - ]:      13060 :                 myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1422         [ +  - ]:      13060 :                 values[i] = !!data;
    1423                 :            :             }
    1424                 :         40 :             break;
    1425                 :            :         }
    1426                 :            :         case DOUBLE: {
    1427                 :            :             double data;
    1428 [ +  - ][ +  + ]:      36959 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1429                 :            :             {
    1430 [ +  - ][ +  - ]:      36928 :                 myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1431         [ +  - ]:      36928 :                 values[i] = !!data;
    1432                 :            :             }
    1433                 :         31 :             break;
    1434                 :            :         }
    1435                 :            :         case HANDLE: {
    1436                 :            :             unsigned long data;
    1437 [ #  # ][ #  # ]:          0 :             for( i = 0; i < myMesh->max_vertex_index(); ++i )
    1438                 :            :             {
    1439 [ #  # ][ #  # ]:          0 :                 myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1440         [ #  # ]:          0 :                 values[i] = !!data;
    1441                 :            :             }
    1442                 :          0 :             break;
    1443                 :            :         }
    1444                 :            :         default:
    1445 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( err )( MsqError::PARSE_ERROR, "'%s' attribute has invalid type", tag_name );
    1446                 :          0 :             return;
    1447                 :            :     }
    1448                 :            : 
    1449         [ +  - ]:        146 :     tag_delete( handle, err );
    1450                 :            : }
    1451                 :            : 
    1452                 :        149 : void MeshImpl::vtk_read_dataset( FileTokenizer& tokens, MsqError& err )
    1453                 :            : {
    1454                 :            :     const char* const data_type_names[] = {
    1455                 :            :         "STRUCTURED_POINTS", "STRUCTURED_GRID", "UNSTRUCTURED_GRID", "POLYDATA", "RECTILINEAR_GRID", "FIELD", 0
    1456                 :        149 :     };
    1457 [ +  - ][ +  - ]:        298 :     int datatype = tokens.match_token( data_type_names, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1458                 :            : 
    1459                 :            :     // Ignore FIELD data at beginning of DATASET. As far as I (J.Kraftcheck)
    1460                 :            :     // understand the VTK documentation, there should never be a FIELD block
    1461                 :            :     // inside a dataset, except in attribute data.  However, some app somewhere
    1462                 :            :     // writes them this way, so try to handle them.
    1463                 :            :     for( ;; )
    1464                 :            :     {
    1465         [ +  - ]:        149 :         tokens.match_token( "FIELD", err );
    1466 [ +  - ][ +  - ]:        149 :         if( err )
    1467                 :            :         {
    1468         [ +  - ]:        149 :             tokens.unget_token();
    1469         [ +  - ]:        149 :             err.clear();
    1470                 :        149 :             break;
    1471                 :            :         }
    1472 [ #  # ][ #  # ]:          0 :         vtk_read_field( tokens, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1473                 :            :     }
    1474                 :            : 
    1475   [ -  -  +  -  :        149 :     switch( datatype )
                -  -  - ]
    1476                 :            :     {
    1477                 :            :         case 1:
    1478         [ #  # ]:          0 :             vtk_read_structured_points( tokens, err );
    1479                 :          0 :             break;
    1480                 :            :         case 2:
    1481         [ #  # ]:          0 :             vtk_read_structured_grid( tokens, err );
    1482                 :          0 :             break;
    1483                 :            :         case 3:
    1484         [ +  - ]:        149 :             vtk_read_unstructured_grid( tokens, err );
    1485                 :        149 :             break;
    1486                 :            :         case 4:
    1487         [ #  # ]:          0 :             vtk_read_polydata( tokens, err );
    1488                 :          0 :             break;
    1489                 :            :         case 5:
    1490         [ #  # ]:          0 :             vtk_read_rectilinear_grid( tokens, err );
    1491                 :          0 :             break;
    1492                 :            :         case 6:
    1493         [ #  # ]:          0 :             vtk_read_field( tokens, err );
    1494                 :          0 :             break;
    1495                 :            :     }
    1496                 :            : 
    1497                 :            :     // Read attribute data
    1498                 :        149 :     const char* const block_type_names[] = { "POINT_DATA", "CELL_DATA", "DATASET", 0 };
    1499                 :        149 :     int blocktype                        = 0;
    1500 [ +  - ][ +  + ]:        341 :     while( !tokens.eof() )
    1501                 :            :     {
    1502                 :            :         // get POINT_DATA or CELL_DATA
    1503         [ +  - ]:        192 :         int new_block_type = tokens.match_token( block_type_names, err );
    1504         [ -  + ]:        192 :         if( new_block_type == 3 )  // done reading attributes
    1505                 :            :         {
    1506         [ #  # ]:          0 :             tokens.unget_token();
    1507                 :          0 :             return;
    1508                 :            :         }
    1509                 :            : 
    1510 [ +  - ][ +  + ]:        192 :         if( err )
    1511                 :            :         {
    1512 [ +  - ][ +  + ]:         20 :             if( tokens.eof() )
    1513                 :            :             {
    1514         [ +  - ]:          7 :                 err.clear();
    1515                 :          7 :                 break;
    1516                 :            :             }
    1517                 :            :             // If next token was neither POINT_DATA nor CELL_DATA,
    1518                 :            :             // then there's another attribute under the current one.
    1519         [ +  - ]:         13 :             if( blocktype )
    1520                 :            :             {
    1521         [ +  - ]:         13 :                 tokens.unget_token();
    1522         [ +  - ]:         13 :                 err.clear();
    1523                 :            :             }
    1524                 :            :             else
    1525                 :            :             {
    1526 [ #  # ][ #  # ]:          0 :                 MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1527                 :            :             }
    1528                 :            :         }
    1529                 :            :         else
    1530                 :            :         {
    1531                 :        172 :             blocktype = new_block_type;
    1532                 :            :             long count;
    1533 [ +  - ][ +  - ]:        172 :             tokens.get_long_ints( 1, &count, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1534                 :            : 
    1535 [ +  + ][ +  - ]:        172 :             if( blocktype == 1 && (unsigned long)count != myMesh->num_vertices() )
         [ -  + ][ -  + ]
    1536                 :            :             {
    1537                 :            :                 MSQ_SETERR( err )
    1538                 :            :                 ( MsqError::PARSE_ERROR,
    1539                 :            :                   "Count inconsistent with number of vertices"
    1540                 :            :                   " at line %d.",
    1541 [ #  # ][ #  # ]:          0 :                   tokens.line_number() );
                 [ #  # ]
    1542                 :          0 :                 return;
    1543                 :            :             }
    1544 [ +  + ][ +  - ]:        172 :             else if( blocktype == 2 && (unsigned long)count != myMesh->num_elements() )
         [ -  + ][ -  + ]
    1545                 :            :             {
    1546                 :            :                 MSQ_SETERR( err )
    1547                 :            :                 ( MsqError::PARSE_ERROR,
    1548                 :            :                   "Count inconsistent with number of elements"
    1549                 :            :                   " at line %d.",
    1550 [ #  # ][ #  # ]:          0 :                   tokens.line_number() );
                 [ #  # ]
    1551                 :        172 :                 return;
    1552                 :            :             }
    1553                 :            :         }
    1554                 :            : 
    1555         [ +  + ]:        185 :         if( blocktype == 1 )
    1556         [ +  - ]:        164 :             vtk_read_point_data( tokens, err );
    1557                 :            :         else
    1558 [ +  - ][ +  - ]:        185 :             vtk_read_cell_data( tokens, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1559                 :          0 :     }
    1560                 :            : }
    1561                 :            : 
    1562                 :          0 : void MeshImpl::vtk_read_structured_points( FileTokenizer& tokens, MsqError& err )
    1563                 :            : {
    1564                 :            :     long i, j, k;
    1565                 :            :     long dims[3];
    1566                 :            :     double origin[3], space[3];
    1567                 :            : 
    1568 [ #  # ][ #  # ]:          0 :     tokens.match_token( "DIMENSIONS", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1569 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 3, dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1570 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1571                 :            : 
    1572 [ #  # ][ #  # ]:          0 :     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
                 [ #  # ]
    1573                 :            :     {
    1574                 :            :         MSQ_SETERR( err )
    1575 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid dimension at line %d", tokens.line_number() );
                 [ #  # ]
    1576                 :          0 :         return;
    1577                 :            :     }
    1578                 :            : 
    1579 [ #  # ][ #  # ]:          0 :     tokens.match_token( "ORIGIN", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1580 [ #  # ][ #  # ]:          0 :     tokens.get_doubles( 3, origin, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1581 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1582                 :            : 
    1583                 :          0 :     const char* const spacing_names[] = { "SPACING", "ASPECT_RATIO", 0 };
    1584 [ #  # ][ #  # ]:          0 :     tokens.match_token( spacing_names, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1585 [ #  # ][ #  # ]:          0 :     tokens.get_doubles( 3, space, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1586 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1587                 :            : 
    1588 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( dims[0] * dims[1] * dims[2], err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1589                 :          0 :     size_t vtx = 0;
    1590         [ #  # ]:          0 :     Vector3D off( origin[0], origin[1], origin[2] );
    1591         [ #  # ]:          0 :     for( k = 0; k < dims[2]; ++k )
    1592         [ #  # ]:          0 :         for( j = 0; j < dims[1]; ++j )
    1593         [ #  # ]:          0 :             for( i = 0; i < dims[0]; ++i )
    1594                 :            :             {
    1595 [ #  # ][ #  # ]:          0 :                 myMesh->reset_vertex( vtx++, off + Vector3D( i * space[0], j * space[1], k * space[2] ), false, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1596                 :            :             }
    1597                 :            : 
    1598 [ #  # ][ #  # ]:          0 :     vtk_create_structured_elems( dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1599                 :            : }
    1600                 :            : 
    1601                 :          0 : void MeshImpl::vtk_read_structured_grid( FileTokenizer& tokens, MsqError& err )
    1602                 :            : {
    1603                 :            :     long num_verts, dims[3];
    1604                 :            : 
    1605 [ #  # ][ #  # ]:          0 :     tokens.match_token( "DIMENSIONS", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1606 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 3, dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1607 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1608                 :            : 
    1609 [ #  # ][ #  # ]:          0 :     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
                 [ #  # ]
    1610                 :            :     {
    1611                 :            :         MSQ_SETERR( err )
    1612 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid dimension at line %d", tokens.line_number() );
                 [ #  # ]
    1613                 :          0 :         return;
    1614                 :            :     }
    1615                 :            : 
    1616 [ #  # ][ #  # ]:          0 :     tokens.match_token( "POINTS", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1617 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 1, &num_verts, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1618 [ #  # ][ #  # ]:          0 :     tokens.match_token( vtk_type_names, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1619 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1620                 :            : 
    1621         [ #  # ]:          0 :     if( num_verts != ( dims[0] * dims[1] * dims[2] ) )
    1622                 :            :     {
    1623                 :            :         MSQ_SETERR( err )
    1624                 :            :         ( MsqError::PARSE_ERROR,
    1625                 :            :           "Point count not consistent with dimensions "
    1626                 :            :           "at line %d",
    1627 [ #  # ][ #  # ]:          0 :           tokens.line_number() );
                 [ #  # ]
    1628                 :          0 :         return;
    1629                 :            :     }
    1630                 :            : 
    1631 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( num_verts, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1632         [ #  # ]:          0 :     for( size_t vtx = 0; vtx < (size_t)num_verts; ++vtx )
    1633                 :            :     {
    1634         [ #  # ]:          0 :         Vector3D pos;
    1635 [ #  # ][ #  # ]:          0 :         tokens.get_doubles( 3, const_cast< double* >( pos.to_array() ), err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1636 [ #  # ][ #  # ]:          0 :         myMesh->reset_vertex( vtx, pos, false, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1637                 :            :     }
    1638                 :            : 
    1639 [ #  # ][ #  # ]:          0 :     vtk_create_structured_elems( dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1640                 :            : }
    1641                 :            : 
    1642                 :          0 : void MeshImpl::vtk_read_rectilinear_grid( FileTokenizer& tokens, MsqError& err )
    1643                 :            : {
    1644                 :            :     int i, j, k;
    1645                 :            :     long dims[3];
    1646                 :          0 :     const char* labels[] = { "X_COORDINATES", "Y_COORDINATES", "Z_COORDINATES" };
    1647 [ #  # ][ #  # ]:          0 :     vector< double > coords[3];
           [ #  #  #  # ]
    1648                 :            : 
    1649 [ #  # ][ #  # ]:          0 :     tokens.match_token( "DIMENSIONS", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1650 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 3, dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1651 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1652                 :            : 
    1653 [ #  # ][ #  # ]:          0 :     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
                 [ #  # ]
    1654                 :            :     {
    1655                 :            :         MSQ_SETERR( err )
    1656 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid dimension at line %d", tokens.line_number() );
                 [ #  # ]
    1657                 :          0 :         return;
    1658                 :            :     }
    1659                 :            : 
    1660         [ #  # ]:          0 :     for( i = 0; i < 3; i++ )
    1661                 :            :     {
    1662                 :            :         long count;
    1663 [ #  # ][ #  # ]:          0 :         tokens.match_token( labels[i], err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1664 [ #  # ][ #  # ]:          0 :         tokens.get_long_ints( 1, &count, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1665 [ #  # ][ #  # ]:          0 :         tokens.match_token( vtk_type_names, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1666 [ #  # ][ #  # ]:          0 :         tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1667                 :            : 
    1668         [ #  # ]:          0 :         if( count != dims[i] )
    1669                 :            :         {
    1670                 :            :             MSQ_SETERR( err )
    1671                 :            :             ( MsqError::PARSE_ERROR,
    1672                 :            :               "Coordinate count inconsistent with dimensions"
    1673                 :            :               " at line %d",
    1674 [ #  # ][ #  # ]:          0 :               tokens.line_number() );
                 [ #  # ]
    1675                 :          0 :             return;
    1676                 :            :         }
    1677                 :            : 
    1678         [ #  # ]:          0 :         coords[i].resize( count );
    1679 [ #  # ][ #  # ]:          0 :         tokens.get_doubles( count, &coords[i][0], err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1680                 :            :     }
    1681                 :            : 
    1682 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( dims[0] * dims[1] * dims[2], err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1683                 :          0 :     size_t vtx = 0;
    1684         [ #  # ]:          0 :     for( k = 0; k < dims[2]; ++k )
    1685         [ #  # ]:          0 :         for( j = 0; j < dims[1]; ++j )
    1686         [ #  # ]:          0 :             for( i = 0; i < dims[0]; ++i )
    1687                 :            :             {
    1688 [ #  # ][ #  # ]:          0 :                 myMesh->reset_vertex( vtx++, Vector3D( coords[0][i], coords[1][j], coords[2][k] ), false, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1689                 :            :             }
    1690                 :            : 
    1691 [ #  # ][ #  # ]:          0 :     vtk_create_structured_elems( dims, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    1692                 :            : }
    1693                 :            : 
    1694                 :          0 : void MeshImpl::vtk_read_polydata( FileTokenizer& tokens, MsqError& err )
    1695                 :            : {
    1696                 :            :     long num_verts;
    1697         [ #  # ]:          0 :     vector< int > connectivity;
    1698                 :          0 :     const char* const poly_data_names[] = { "VERTICES", "LINES", "POLYGONS", "TRIANGLE_STRIPS", 0 };
    1699                 :            : 
    1700 [ #  # ][ #  # ]:          0 :     tokens.match_token( "POINTS", err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1701 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 1, &num_verts, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1702 [ #  # ][ #  # ]:          0 :     tokens.match_token( vtk_type_names, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1703 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1704                 :            : 
    1705         [ #  # ]:          0 :     if( num_verts < 1 )
    1706                 :            :     {
    1707                 :            :         MSQ_SETERR( err )
    1708 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid point count at line %d", tokens.line_number() );
                 [ #  # ]
    1709                 :          0 :         return;
    1710                 :            :     }
    1711                 :            : 
    1712 [ #  # ][ #  # ]:          0 :     myMesh->allocate_vertices( num_verts, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1713         [ #  # ]:          0 :     for( size_t vtx = 0; vtx < (size_t)num_verts; ++vtx )
    1714                 :            :     {
    1715         [ #  # ]:          0 :         Vector3D pos;
    1716 [ #  # ][ #  # ]:          0 :         tokens.get_doubles( 3, const_cast< double* >( pos.to_array() ), err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1717 [ #  # ][ #  # ]:          0 :         myMesh->reset_vertex( vtx, pos, false, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1718                 :            :     }
    1719                 :            : 
    1720 [ #  # ][ #  # ]:          0 :     int poly_type = tokens.match_token( poly_data_names, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1721   [ #  #  #  # ]:          0 :     switch( poly_type )
    1722                 :            :     {
    1723                 :            :         case 3:
    1724 [ #  # ][ #  # ]:          0 :             vtk_read_polygons( tokens, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1725                 :          0 :             break;
    1726                 :            :         case 4:
    1727                 :            :             MSQ_SETERR( err )
    1728 [ #  # ][ #  # ]:          0 :             ( MsqError::NOT_IMPLEMENTED, "Unsupported type: triangle strips at line %d", tokens.line_number() );
                 [ #  # ]
    1729                 :          0 :             return;
    1730                 :            :         case 1:
    1731                 :            :         case 2:
    1732                 :            :             MSQ_SETERR( err )
    1733 [ #  # ][ #  # ]:          0 :             ( MsqError::NOT_IMPLEMENTED, "Entities of dimension < 2 at line %d", tokens.line_number() );
                 [ #  # ]
    1734         [ #  # ]:          0 :             return;
    1735                 :          0 :     }
    1736                 :            : }
    1737                 :            : 
    1738                 :          0 : void MeshImpl::vtk_read_polygons( FileTokenizer& tokens, MsqError& err )
    1739                 :            : {
    1740                 :            :     long size[2];
    1741                 :            : 
    1742 [ #  # ][ #  # ]:          0 :     tokens.get_long_ints( 2, size, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1743 [ #  # ][ #  # ]:          0 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1744 [ #  # ][ #  # ]:          0 :     myMesh->allocate_elements( size[0], err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1745         [ #  # ]:          0 :     std::vector< long > conn;
    1746                 :            : 
    1747 [ #  # ][ #  # ]:          0 :     for( int i = 0; i < size[0]; ++i )
    1748                 :            :     {
    1749                 :            :         long count;
    1750 [ #  # ][ #  # ]:          0 :         tokens.get_long_ints( 1, &count, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1751         [ #  # ]:          0 :         conn.resize( count );
    1752 [ #  # ][ #  # ]:          0 :         tokens.get_long_ints( count, arrptr( conn ), err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1753 [ #  # ][ #  # ]:          0 :         myMesh->reset_element( i, conn, POLYGON, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1754                 :          0 :     }
    1755                 :            : }
    1756                 :            : 
    1757                 :        149 : void MeshImpl::vtk_read_unstructured_grid( FileTokenizer& tokens, MsqError& err )
    1758                 :            : {
    1759                 :            :     long i, num_verts, num_elems[2];
    1760                 :            : 
    1761 [ +  - ][ +  - ]:        298 :     tokens.match_token( "POINTS", err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1762 [ +  - ][ +  - ]:        149 :     tokens.get_long_ints( 1, &num_verts, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1763 [ +  - ][ +  - ]:        149 :     tokens.match_token( vtk_type_names, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1764 [ +  - ][ +  - ]:        149 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1765                 :            : 
    1766         [ -  + ]:        149 :     if( num_verts < 1 )
    1767                 :            :     {
    1768                 :            :         MSQ_SETERR( err )
    1769 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid point count at line %d", tokens.line_number() );
                 [ #  # ]
    1770                 :          0 :         return;
    1771                 :            :     }
    1772                 :            : 
    1773 [ +  - ][ +  - ]:        149 :     myMesh->allocate_vertices( num_verts, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1774         [ +  + ]:      65900 :     for( size_t vtx = 0; vtx < (size_t)num_verts; ++vtx )
    1775                 :            :     {
    1776         [ +  - ]:      65751 :         Vector3D pos;
    1777 [ +  - ][ +  - ]:      65751 :         tokens.get_doubles( 3, const_cast< double* >( pos.to_array() ), err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
    1778 [ +  - ][ +  - ]:      65751 :         myMesh->reset_vertex( vtx, pos, false, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1779                 :            :     }
    1780                 :            : 
    1781 [ +  - ][ +  - ]:        149 :     tokens.match_token( "CELLS", err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1782 [ +  - ][ +  - ]:        149 :     tokens.get_long_ints( 2, num_elems, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1783 [ +  - ][ +  - ]:        149 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1784                 :            : 
    1785 [ +  - ][ +  - ]:        149 :     myMesh->allocate_elements( num_elems[0], err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1786         [ +  - ]:        149 :     std::vector< long > conn;
    1787         [ +  + ]:     116455 :     for( i = 0; i < num_elems[0]; ++i )
    1788                 :            :     {
    1789                 :            :         long count;
    1790 [ +  - ][ +  - ]:     116306 :         tokens.get_long_ints( 1, &count, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1791         [ +  - ]:     116306 :         conn.resize( count );
    1792 [ +  - ][ +  - ]:     116306 :         tokens.get_long_ints( count, arrptr( conn ), err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
                 [ -  + ]
    1793 [ +  - ][ +  - ]:     116306 :         myMesh->reset_element( i, conn, MIXED, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1794                 :            :     }
    1795                 :            : 
    1796 [ +  - ][ +  - ]:        149 :     tokens.match_token( "CELL_TYPES", err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1797 [ +  - ][ +  - ]:        149 :     tokens.get_long_ints( 1, &num_elems[1], err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1798 [ +  - ][ +  - ]:        149 :     tokens.get_newline( err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1799                 :            : 
    1800         [ -  + ]:        149 :     if( num_elems[0] != num_elems[1] )
    1801                 :            :     {
    1802                 :            :         MSQ_SETERR( err )
    1803                 :            :         ( MsqError::PARSE_ERROR,
    1804                 :            :           "Number of element types does not match number of elements"
    1805                 :            :           "at line %d",
    1806 [ #  # ][ #  # ]:          0 :           tokens.line_number() );
                 [ #  # ]
    1807                 :          0 :         return;
    1808                 :            :     }
    1809                 :            : 
    1810 [ +  - ][ +  - ]:        298 :     std::vector< size_t > tconn;
    1811 [ +  + ][ +  - ]:     116455 :     for( i = 0; i < num_elems[0]; ++i )
    1812                 :            :     {
    1813                 :            :         long type;
    1814                 :            :         size_t size;
    1815 [ +  - ][ +  - ]:     116306 :         tokens.get_long_ints( 1, &type, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1816                 :            : 
    1817                 :            :         // Check if type is a valid value
    1818         [ +  - ]:     116306 :         const VtkTypeInfo* info = VtkTypeInfo::find_type( type, err );
    1819 [ +  - ][ +  - ]:     116306 :         if( err || !info || ( !info->numNodes && type != POLYGON ) )
         [ +  - ][ +  + ]
         [ -  + ][ -  + ]
    1820                 :            :         {
    1821                 :            :             MSQ_SETERR( err )
    1822 [ #  # ][ #  # ]:          0 :             ( MsqError::PARSE_ERROR, "Invalid cell type %ld at line %d.", type, tokens.line_number() );
                 [ #  # ]
    1823                 :          0 :             return;
    1824                 :            :         }
    1825                 :            :         // Check if Mesquite supports the type
    1826         [ -  + ]:     116306 :         if( info->msqType == MIXED )
    1827                 :            :         {
    1828                 :            :             MSQ_SETERR( err )
    1829                 :            :             ( MsqError::UNSUPPORTED_ELEMENT, "Unsupported cell type %ld (%s) at line %d.", type, info->name,
    1830 [ #  # ][ #  # ]:          0 :               tokens.line_number() );
                 [ #  # ]
    1831                 :          0 :             return;
    1832                 :            :         }
    1833                 :            : 
    1834                 :            :         // If node-ordering is not the same as exodus...
    1835         [ +  + ]:     116306 :         if( info->vtkConnOrder )
    1836                 :            :         {
    1837 [ +  - ][ +  - ]:         12 :             size = myMesh->element_connectivity( i, err ).size();MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1838         [ -  + ]:         12 :             if( info->numNodes != size )
    1839                 :            :             {
    1840                 :            :                 MSQ_SETERR( err )
    1841                 :            :                 ( MsqError::UNSUPPORTED_ELEMENT, "Cell type %ld (%s) for element with %d nodes at Line %d", type,
    1842 [ #  # ][ #  # ]:          0 :                   info->name, (int)size, tokens.line_number() );
                 [ #  # ]
    1843                 :          0 :                 return;
    1844                 :            :             }
    1845                 :            : 
    1846         [ +  - ]:         12 :             tconn.resize( size );
    1847 [ +  - ][ +  - ]:         12 :             const std::vector< size_t >& pconn = myMesh->element_connectivity( i, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1848         [ +  + ]:         84 :             for( size_t j = 0; j < size; ++j )
    1849                 :            :             {
    1850 [ +  - ][ +  - ]:         72 :                 tconn[j] = pconn[info->vtkConnOrder[j]];
    1851                 :            :             }
    1852                 :            : 
    1853 [ +  - ][ +  - ]:         12 :             myMesh->reset_element( i, tconn, info->msqType, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1854                 :            :         }
    1855                 :            :         // Othewise (if node ordering is the same), just set the type.
    1856                 :            :         else
    1857                 :            :         {
    1858 [ +  - ][ +  - ]:     116294 :             myMesh->element_topology( i, info->msqType, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1859                 :            :         }
    1860                 :        149 :     }  // for(i)
    1861                 :            : }
    1862                 :            : 
    1863                 :          0 : void MeshImpl::vtk_create_structured_elems( const long* dims, MsqError& err )
    1864                 :            : {
    1865                 :            :     // NOTE: this should be work fine for edges also if
    1866                 :            :     //      Mesquite ever supports them.  Just add the
    1867                 :            :     //      type for dimension 1 to the switch statement.
    1868                 :            : 
    1869                 :            :     // int non_zero[3] = {0,0,0};  // True if dim > 0 for x, y, z respectively
    1870                 :          0 :     long elem_dim  = 0;           // Element dimension (2->quad, 3->hex)
    1871                 :          0 :     long num_elems = 1;           // Total number of elements
    1872                 :            :     long vert_per_elem;           // Element connectivity length
    1873                 :          0 :     long edims[3] = { 1, 1, 1 };  // Number of elements in each grid direction
    1874                 :            : 
    1875                 :            :     // Populate above data
    1876         [ #  # ]:          0 :     for( int d = 0; d < 3; d++ )
    1877         [ #  # ]:          0 :         if( dims[d] > 1 )
    1878                 :            :         {
    1879                 :            :             // non_zero[elem_dim] = d;
    1880                 :          0 :             edims[d] = dims[d] - 1;
    1881                 :          0 :             num_elems *= edims[d];
    1882                 :          0 :             elem_dim++;
    1883                 :            :         }
    1884                 :          0 :     vert_per_elem = 1 << elem_dim;
    1885                 :            : 
    1886                 :            :     // Get element type from element dimension
    1887                 :            :     EntityTopology type;
    1888      [ #  #  # ]:          0 :     switch( elem_dim )
    1889                 :            :     {
    1890                 :            :             // case 1: type = EDGE;          break;
    1891                 :            :         case 2:
    1892                 :          0 :             type = QUADRILATERAL;
    1893                 :          0 :             break;
    1894                 :            :         case 3:
    1895                 :          0 :             type = HEXAHEDRON;
    1896                 :          0 :             break;
    1897                 :            :         default:
    1898                 :            :             MSQ_SETERR( err )
    1899                 :            :             ( "Cannot create structured mesh with elements "
    1900                 :            :               "of dimension < 2 or > 3.",
    1901 [ #  # ][ #  # ]:          0 :               MsqError::NOT_IMPLEMENTED );
    1902                 :          0 :             return;
    1903                 :            :     }
    1904                 :            : 
    1905                 :            :     // Allocate storage for elements
    1906 [ #  # ][ #  # ]:          0 :     myMesh->allocate_elements( num_elems, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1907                 :            : 
    1908                 :            :     // Offsets of element vertices in grid relative to corner closest to origin
    1909                 :          0 :     long k                = dims[0] * dims[1];
    1910                 :          0 :     const long corners[8] = { 0, 1, 1 + dims[0], dims[0], k, k + 1, k + 1 + dims[0], k + dims[0] };
    1911                 :            : 
    1912                 :            :     // Populate element list
    1913         [ #  # ]:          0 :     std::vector< size_t > conn( vert_per_elem );
    1914                 :          0 :     size_t elem_idx = 0;
    1915 [ #  # ][ #  # ]:          0 :     for( long z = 0; z < edims[2]; ++z )
    1916         [ #  # ]:          0 :         for( long y = 0; y < edims[1]; ++y )
    1917         [ #  # ]:          0 :             for( long x = 0; x < edims[0]; ++x )
    1918                 :            :             {
    1919                 :          0 :                 const long index = x + y * dims[0] + z * ( dims[0] * dims[1] );
    1920         [ #  # ]:          0 :                 for( long j = 0; j < vert_per_elem; ++j )
    1921         [ #  # ]:          0 :                     conn[j] = index + corners[j];
    1922 [ #  # ][ #  # ]:          0 :                 myMesh->reset_element( elem_idx++, conn, type, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1923                 :          0 :             }
    1924                 :            : }
    1925                 :            : 
    1926                 :          0 : void* MeshImpl::vtk_read_field_data( FileTokenizer& tokens, size_t count, size_t num_fields,
    1927                 :            :                                      const std::string& field_name, TagDescription& tag, MsqError& err )
    1928                 :            : {
    1929 [ #  # ][ #  # ]:          0 :     tag.member = tokens.get_string( err );
    1930 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1931                 :            :     // If field is a struct containing multiple members, make
    1932                 :            :     // tag name the concatentation of the field name and member
    1933                 :            :     // name.
    1934         [ #  # ]:          0 :     if( num_fields > 1 )
    1935                 :            :     {
    1936         [ #  # ]:          0 :         tag.name = field_name;
    1937         [ #  # ]:          0 :         tag.name += " ";
    1938         [ #  # ]:          0 :         tag.name += tag.member;
    1939                 :          0 :         tag.member.clear();
    1940                 :            :     }
    1941                 :            :     // If field contains only one member, then make the tag
    1942                 :            :     // name be the field name, and store the member name to
    1943                 :            :     // preserve it for subsequent writes.
    1944                 :            :     else
    1945                 :            :     {
    1946         [ #  # ]:          0 :         tag.name = field_name;
    1947                 :            :     }
    1948                 :            : 
    1949                 :            :     // Get tuple size and count from the file.
    1950                 :            :     long sizes[2];
    1951         [ #  # ]:          0 :     tokens.get_long_ints( 2, sizes, err );
    1952 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1953         [ #  # ]:          0 :     if( sizes[0] < 1 )
    1954                 :            :     {
    1955                 :            :         MSQ_SETERR( err )
    1956                 :            :         ( MsqError::PARSE_ERROR, "Invalid tuple size (%ld) for field data %s at line %d\n", sizes[0], tag.name.c_str(),
    1957 [ #  # ][ #  # ]:          0 :           tokens.line_number() );
                 [ #  # ]
    1958                 :          0 :         return 0;
    1959                 :            :     }
    1960 [ #  # ][ #  # ]:          0 :     if( sizes[1] < 0 || ( count && (size_t)sizes[1] != count ) )
                 [ #  # ]
    1961                 :            :     {
    1962                 :            :         MSQ_SETERR( err )
    1963                 :            :         ( MsqError::PARSE_ERROR,
    1964                 :            :           "Invalid field data length at line %d.  "
    1965                 :            :           "Cannot map %lu tuples to  %ld entities.\n",
    1966 [ #  # ][ #  # ]:          0 :           tokens.line_number(), (unsigned long)count, sizes[1] );
                 [ #  # ]
    1967                 :          0 :         return 0;
    1968                 :            :     }
    1969                 :            : 
    1970         [ #  # ]:          0 :     int type = tokens.match_token( vtk_type_names, err );
    1971 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1972 [ #  # ][ #  # ]:          0 :     void* result = vtk_read_typed_data( tokens, type, sizes[0], sizes[1], tag, err );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    1973                 :          0 :     return result;
    1974                 :            : }
    1975                 :            : 
    1976                 :          0 : void MeshImpl::vtk_read_field( FileTokenizer& tokens, MsqError& err )
    1977                 :            : {
    1978                 :            :     // This is not supported yet.
    1979                 :            :     // Parse the data but throw it away because
    1980                 :            :     // Mesquite has no internal representation for it.
    1981                 :            : 
    1982 [ #  # ][ #  # ]:          0 :     std::string name = tokens.get_string( err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1983                 :            :     int count;
    1984 [ #  # ][ #  # ]:          0 :     tokens.get_integers( 1, &count, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1985                 :            : 
    1986 [ #  # ][ #  # ]:          0 :     for( int i = 0; i < count; i++ )
    1987                 :            :     {
    1988         [ #  # ]:          0 :         TagDescription tag;
    1989 [ #  # ][ #  # ]:          0 :         void* ptr = vtk_read_field_data( tokens, 0, 1, "", tag, err );
    1990 [ #  # ][ #  # ]:          0 :         if( ptr ) free( ptr );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1991                 :          0 :     }
    1992                 :            : }
    1993                 :            : 
    1994                 :        185 : void* MeshImpl::vtk_read_attrib_data( FileTokenizer& tokens, long count, TagDescription& tag, MsqError& err )
    1995                 :            : {
    1996                 :            :     const char* const type_names[] = { "SCALARS", "COLOR_SCALARS", "VECTORS", "NORMALS", "TEXTURE_COORDINATES",
    1997                 :            :                                        "TENSORS", "FIELD",
    1998                 :            :                                        // Some buggy VTK files have empty CELL_DATA/POINT_DATA
    1999                 :            :                                        // blocks Try to allow them by checking for possible other
    2000                 :            :                                        // tokens indicating the end of the block
    2001                 :        185 :                                        "POINT_DATA", "CELL_DATA", "DATASET", 0 };
    2002                 :            : 
    2003         [ +  - ]:        185 :     int type = tokens.match_token( type_names, err );
    2004 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2005         [ -  + ]:        185 :     if( type > 7 )  // empty CELL_DATA/POINT_DATA block.
    2006                 :            :     {
    2007                 :          0 :         tag.vtkType = TagDescription::NONE;
    2008         [ #  # ]:          0 :         tokens.unget_token();
    2009                 :          0 :         return 0;
    2010                 :            :     }
    2011                 :            : 
    2012         [ +  - ]:        185 :     const char* name = tokens.get_string( err );
    2013 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2014         [ +  - ]:        185 :     tag.name = name;
    2015                 :            : 
    2016                 :        185 :     void* data = 0;
    2017   [ +  -  -  -  :        185 :     switch( type )
             -  -  -  - ]
    2018                 :            :     {
    2019                 :            :         case 1:
    2020         [ +  - ]:        185 :             data        = vtk_read_scalar_attrib( tokens, count, tag, err );
    2021                 :        185 :             tag.vtkType = TagDescription::SCALAR;
    2022                 :        185 :             break;
    2023                 :            :         case 2:
    2024         [ #  # ]:          0 :             data        = vtk_read_color_attrib( tokens, count, tag, err );
    2025                 :          0 :             tag.vtkType = TagDescription::COLOR;
    2026                 :          0 :             break;
    2027                 :            :         case 3:
    2028         [ #  # ]:          0 :             data        = vtk_read_vector_attrib( tokens, count, tag, err );
    2029                 :          0 :             tag.vtkType = TagDescription::VECTOR;
    2030                 :          0 :             break;
    2031                 :            :         case 4:
    2032         [ #  # ]:          0 :             data        = vtk_read_vector_attrib( tokens, count, tag, err );
    2033                 :          0 :             tag.vtkType = TagDescription::NORMAL;
    2034                 :          0 :             break;
    2035                 :            :         case 5:
    2036         [ #  # ]:          0 :             data        = vtk_read_texture_attrib( tokens, count, tag, err );
    2037                 :          0 :             tag.vtkType = TagDescription::TEXTURE;
    2038                 :          0 :             break;
    2039                 :            :         case 6:
    2040         [ #  # ]:          0 :             data        = vtk_read_tensor_attrib( tokens, count, tag, err );
    2041                 :          0 :             tag.vtkType = TagDescription::TENSOR;
    2042                 :          0 :             break;
    2043                 :            :         case 7:
    2044                 :          0 :             data        = 0;
    2045                 :          0 :             tag.vtkType = TagDescription::FIELD;
    2046                 :          0 :             break;
    2047                 :            :     }
    2048                 :            : 
    2049                 :        185 :     return data;
    2050                 :            : }
    2051                 :            : 
    2052                 :        164 : void MeshImpl::vtk_read_point_data( FileTokenizer& tokens, MsqError& err )
    2053                 :            : {
    2054         [ +  - ]:        164 :     TagDescription tag;
    2055 [ +  - ][ +  - ]:        164 :     void* data = vtk_read_attrib_data( tokens, myMesh->num_vertices(), tag, err );
    2056         [ +  - ]:        164 :     if( data )  // normal attribute
    2057                 :            :     {
    2058         [ +  - ]:        164 :         vtk_store_point_data( data, tag, err );
    2059 [ +  - ][ -  + ]:        164 :         free( data );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
    2060                 :        164 :         return;
    2061                 :            :         ;
    2062                 :            :     }
    2063         [ #  # ]:          0 :     else if( tag.vtkType == TagDescription::FIELD )
    2064                 :            :     {
    2065         [ #  # ]:          0 :         std::string field = tag.name;
    2066                 :            :         int field_count;
    2067 [ #  # ][ #  # ]:          0 :         tokens.get_integers( 1, &field_count, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2068 [ #  # ][ #  # ]:          0 :         for( int i = 0; i < field_count; ++i )
    2069                 :            :         {
    2070 [ #  # ][ #  # ]:          0 :             data = vtk_read_field_data( tokens, myMesh->num_vertices(), field_count, field, tag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2071         [ #  # ]:          0 :             vtk_store_point_data( data, tag, err );
    2072 [ #  # ][ #  # ]:          0 :             free( data );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2073         [ -  + ]:        164 :         }
    2074                 :        164 :     }
    2075                 :            : }
    2076                 :            : 
    2077                 :        164 : void MeshImpl::vtk_store_point_data( const void* data, TagDescription& tag, MsqError& err )
    2078                 :            : {
    2079 [ +  - ][ +  - ]:        328 :     size_t tag_handle = myTags->handle( tag.name, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2080         [ +  + ]:        164 :     if( !tag_handle )
    2081                 :            :     {
    2082 [ +  - ][ +  - ]:        155 :         tag_handle = myTags->create( tag, 0, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2083                 :            :     }
    2084                 :            :     else
    2085                 :            :     {
    2086 [ +  - ][ +  - ]:          9 :         const TagDescription& desc = myTags->properties( tag_handle, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2087 [ +  - ][ -  + ]:          9 :         if( desc != tag )
    2088                 :            :         {
    2089                 :            :             MSQ_SETERR( err )
    2090                 :            :             ( MsqError::PARSE_ERROR,
    2091                 :            :               "Inconsistent types between element "
    2092                 :            :               "and vertex attributes named \"%s\"\n",
    2093 [ #  # ][ #  # ]:          0 :               tag.name.c_str() );
    2094                 :          0 :             return;
    2095                 :            :         }
    2096                 :            :     }
    2097                 :            : 
    2098         [ +  - ]:        164 :     std::vector< size_t > vertex_handles;
    2099 [ +  - ][ +  - ]:        164 :     myMesh->all_vertices( vertex_handles, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2100         [ +  - ]:        164 :     if( !vertex_handles.empty() )
    2101 [ +  - ][ +  - ]:        164 :         myTags->set_vertex_data( tag_handle, vertex_handles.size(), arrptr( vertex_handles ), data, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
    2102                 :            : }
    2103                 :            : 
    2104                 :         21 : void MeshImpl::vtk_read_cell_data( FileTokenizer& tokens, MsqError& err )
    2105                 :            : {
    2106         [ +  - ]:         21 :     TagDescription tag;
    2107 [ +  - ][ +  - ]:         21 :     void* data = vtk_read_attrib_data( tokens, myMesh->num_elements(), tag, err );
    2108         [ +  - ]:         21 :     if( data )  // normal attribute
    2109                 :            :     {
    2110         [ +  - ]:         21 :         vtk_store_cell_data( data, tag, err );
    2111 [ +  - ][ -  + ]:         21 :         free( data );MSQ_CHKERR( err );
         [ #  # ][ #  # ]
    2112                 :         21 :         return;
    2113                 :            :         ;
    2114                 :            :     }
    2115         [ #  # ]:          0 :     else if( tag.vtkType == TagDescription::FIELD )
    2116                 :            :     {
    2117         [ #  # ]:          0 :         std::string field = tag.name;
    2118                 :            :         int field_count;
    2119 [ #  # ][ #  # ]:          0 :         tokens.get_integers( 1, &field_count, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2120 [ #  # ][ #  # ]:          0 :         for( int i = 0; i < field_count; ++i )
    2121                 :            :         {
    2122 [ #  # ][ #  # ]:          0 :             data = vtk_read_field_data( tokens, myMesh->num_elements(), field_count, field, tag, err );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2123         [ #  # ]:          0 :             vtk_store_cell_data( data, tag, err );
    2124 [ #  # ][ #  # ]:          0 :             free( data );MSQ_ERRRTN( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2125         [ -  + ]:         21 :         }
    2126                 :         21 :     }
    2127                 :            : }
    2128                 :            : 
    2129                 :         21 : void MeshImpl::vtk_store_cell_data( const void* data, TagDescription& tag, MsqError& err )
    2130                 :            : {
    2131 [ +  - ][ +  - ]:         42 :     size_t tag_handle = myTags->handle( tag.name, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2132         [ +  + ]:         21 :     if( !tag_handle )
    2133                 :            :     {
    2134 [ +  - ][ +  - ]:         16 :         tag_handle = myTags->create( tag, 0, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2135                 :            :     }
    2136                 :            :     else
    2137                 :            :     {
    2138 [ +  - ][ +  - ]:          5 :         const TagDescription& desc = myTags->properties( tag_handle, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2139 [ +  - ][ -  + ]:          5 :         if( desc != tag )
    2140                 :            :         {
    2141                 :            :             MSQ_SETERR( err )
    2142                 :            :             ( MsqError::PARSE_ERROR,
    2143                 :            :               "Inconsistent types between element "
    2144                 :            :               "and vertex attributes named \"%s\"\n",
    2145 [ #  # ][ #  # ]:          0 :               tag.name.c_str() );
    2146                 :          0 :             return;
    2147                 :            :         }
    2148                 :            :     }
    2149                 :            : 
    2150         [ +  - ]:         21 :     std::vector< size_t > element_handles;
    2151 [ +  - ][ +  - ]:         21 :     myMesh->all_elements( element_handles, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2152         [ +  - ]:         21 :     if( !element_handles.empty() )
    2153 [ +  - ][ +  - ]:         21 :         myTags->set_element_data( tag_handle, element_handles.size(), arrptr( element_handles ), data, err );MSQ_ERRRTN( err );
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
    2154                 :            : }
    2155                 :            : 
    2156                 :        185 : void* MeshImpl::vtk_read_typed_data( FileTokenizer& tokens, int type, size_t per_elem, size_t num_elem,
    2157                 :            :                                      TagDescription& tag, MsqError& err )
    2158                 :            : {
    2159                 :            :     void* data_ptr;
    2160                 :        185 :     size_t count = per_elem * num_elem;
    2161   [ +  +  -  +  :        185 :     switch( type )
                      - ]
    2162                 :            :     {
    2163                 :            :         case 1:
    2164                 :         75 :             tag.size = per_elem * sizeof( bool );
    2165                 :         75 :             tag.type = BOOL;
    2166                 :         75 :             data_ptr = malloc( num_elem * tag.size );
    2167                 :         75 :             tokens.get_booleans( count, (bool*)data_ptr, err );
    2168                 :         75 :             break;
    2169                 :            :         case 2:
    2170                 :            :         case 3:
    2171                 :            :         case 4:
    2172                 :            :         case 5:
    2173                 :            :         case 6:
    2174                 :            :         case 7:
    2175                 :         79 :             tag.size = per_elem * sizeof( int );
    2176                 :         79 :             tag.type = INT;
    2177                 :         79 :             data_ptr = malloc( num_elem * tag.size );
    2178                 :         79 :             tokens.get_integers( count, (int*)data_ptr, err );
    2179                 :         79 :             break;
    2180                 :            :         case 8:
    2181                 :            :         case 9:
    2182                 :            :             // this is a bit of a hack since MeshImpl doesn't have a LONG type (HANDLE is used by
    2183                 :            :             // ParallelMesh for long)
    2184                 :          0 :             tag.size = per_elem * sizeof( size_t );
    2185                 :            :             assert( sizeof( long ) == sizeof( size_t ) );
    2186                 :            :             assert( sizeof( long ) == sizeof( void* ) );
    2187                 :          0 :             tag.type = HANDLE;
    2188                 :          0 :             data_ptr = malloc( num_elem * tag.size );
    2189                 :          0 :             tokens.get_long_ints( count, (long*)data_ptr, err );
    2190                 :          0 :             break;
    2191                 :            :         case 10:
    2192                 :            :         case 11:
    2193                 :         31 :             tag.size = per_elem * sizeof( double );
    2194                 :         31 :             tag.type = DOUBLE;
    2195                 :         31 :             data_ptr = malloc( num_elem * tag.size );
    2196                 :         31 :             tokens.get_doubles( count, (double*)data_ptr, err );
    2197                 :         31 :             break;
    2198                 :            :         default:
    2199         [ #  # ]:          0 :             MSQ_SETERR( err )( "Invalid data type", MsqError::INVALID_ARG );
    2200                 :          0 :             return 0;
    2201                 :            :     }
    2202                 :            : 
    2203 [ -  + ][ #  # ]:        185 :     if( MSQ_CHKERR( err ) )
                 [ -  + ]
    2204                 :            :     {
    2205                 :          0 :         free( data_ptr );
    2206                 :          0 :         return 0;
    2207                 :            :     }
    2208                 :            : 
    2209                 :        185 :     return data_ptr;
    2210                 :            : }
    2211                 :            : 
    2212                 :        185 : void* MeshImpl::vtk_read_scalar_attrib( FileTokenizer& tokens, long count, TagDescription& desc, MsqError& err )
    2213                 :            : {
    2214         [ -  + ]:        185 :     if( !count ) return 0;
    2215                 :            : 
    2216         [ +  - ]:        185 :     int type = tokens.match_token( vtk_type_names, err );
    2217 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2218                 :            : 
    2219                 :            :     long size;
    2220         [ +  - ]:        185 :     const char* tok = tokens.get_string( err );
    2221 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2222                 :        185 :     const char* end = 0;
    2223                 :        185 :     size            = strtol( tok, (char**)&end, 0 );
    2224         [ +  + ]:        185 :     if( *end )
    2225                 :            :     {
    2226                 :        154 :         size = 1;
    2227         [ +  - ]:        154 :         tokens.unget_token();
    2228                 :            :     }
    2229                 :            : 
    2230                 :            :     // VTK spec says cannot be greater than 4--do we care?
    2231 [ +  - ][ -  + ]:        185 :     if( size < 1 || size > 4 )
    2232                 :            :     {
    2233                 :            :         MSQ_SETERR( err )
    2234                 :            :         ( MsqError::PARSE_ERROR,
    2235                 :            :           "Scalar count out of range [1,4]"
    2236                 :            :           " at line %d",
    2237 [ #  # ][ #  # ]:          0 :           tokens.line_number() );
                 [ #  # ]
    2238                 :          0 :         return 0;
    2239                 :            :     }
    2240                 :            : 
    2241         [ +  - ]:        185 :     tokens.match_token( "LOOKUP_TABLE", err );
    2242 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2243         [ +  - ]:        185 :     tok = tokens.get_string( err );
    2244 [ +  - ][ -  + ]:        185 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2245                 :            : 
    2246                 :            :     // If no lookup table, just read and return the data
    2247         [ +  - ]:        185 :     if( !strcmp( tok, "default" ) )
    2248                 :            :     {
    2249         [ +  - ]:        185 :         void* ptr = vtk_read_typed_data( tokens, type, size, count, desc, err );
    2250 [ +  - ][ -  + ]:        185 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ -  + ]
    2251                 :        185 :         return ptr;
    2252                 :            :     }
    2253                 :            : 
    2254                 :            :     // If we got this far, then the data has a lookup
    2255                 :            :     // table.  First read the lookup table and convert
    2256                 :            :     // to integers.
    2257         [ #  # ]:          0 :     string name = tok;
    2258         [ #  # ]:          0 :     vector< long > table( size * count );
    2259 [ #  # ][ #  # ]:          0 :     if( type > 0 && type < 10 )  // Is an integer type
    2260                 :            :     {
    2261 [ #  # ][ #  # ]:          0 :         tokens.get_long_ints( table.size(), arrptr( table ), err );
    2262 [ #  # ][ #  # ]:          0 :         MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2263                 :            :     }
    2264                 :            :     else  // Is a real-number type
    2265                 :            :     {
    2266 [ #  # ][ #  # ]:          0 :         for( std::vector< long >::iterator iter = table.begin(); iter != table.end(); ++iter )
                 [ #  # ]
    2267                 :            :         {
    2268                 :            :             double data;
    2269         [ #  # ]:          0 :             tokens.get_doubles( 1, &data, err );
    2270 [ #  # ][ #  # ]:          0 :             MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2271                 :            : 
    2272         [ #  # ]:          0 :             *iter = (long)data;
    2273 [ #  # ][ #  # ]:          0 :             if( (double)*iter != data )
    2274                 :            :             {
    2275                 :            :                 MSQ_SETERR( err )
    2276 [ #  # ][ #  # ]:          0 :                 ( MsqError::PARSE_ERROR, "Invalid lookup index (%.0f) at line %d", data, tokens.line_number() );
                 [ #  # ]
    2277                 :          0 :                 return 0;
    2278                 :            :             }
    2279                 :            :         }
    2280                 :            :     }
    2281                 :            : 
    2282                 :            :     // Now read the data - must be float RGBA color triples
    2283                 :            : 
    2284                 :            :     long table_count;
    2285         [ #  # ]:          0 :     tokens.match_token( "LOOKUP_TABLE", err );
    2286 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2287         [ #  # ]:          0 :     tokens.match_token( name.c_str(), err );
    2288 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2289         [ #  # ]:          0 :     tokens.get_long_ints( 1, &table_count, err );
    2290 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2291                 :            : 
    2292         [ #  # ]:          0 :     vector< float > table_data( table_count * 4 );
    2293 [ #  # ][ #  # ]:          0 :     tokens.get_floats( table_data.size(), arrptr( table_data ), err );
    2294 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2295                 :            : 
    2296                 :            :     // Create list from indexed data
    2297                 :            : 
    2298                 :          0 :     float* data      = (float*)malloc( sizeof( float ) * count * size * 4 );
    2299                 :          0 :     float* data_iter = data;
    2300 [ #  # ][ #  # ]:          0 :     for( std::vector< long >::iterator idx = table.begin(); idx != table.end(); ++idx )
                 [ #  # ]
    2301                 :            :     {
    2302 [ #  # ][ #  # ]:          0 :         if( *idx < 0 || *idx >= table_count )
         [ #  # ][ #  # ]
                 [ #  # ]
    2303                 :            :         {
    2304                 :            :             MSQ_SETERR( err )
    2305 [ #  # ][ #  # ]:          0 :             ( MsqError::PARSE_ERROR, "LOOKUP_TABLE index %ld out of range.", *idx );
                 [ #  # ]
    2306                 :          0 :             free( data );
    2307                 :          0 :             return 0;
    2308                 :            :         }
    2309                 :            : 
    2310         [ #  # ]:          0 :         for( int i = 0; i < 4; i++ )
    2311                 :            :         {
    2312 [ #  # ][ #  # ]:          0 :             *data_iter = table_data[4 * *idx + i];
    2313                 :          0 :             ++data_iter;
    2314                 :            :         }
    2315                 :            :     }
    2316                 :            : 
    2317                 :          0 :     desc.size = size * 4 * sizeof( float );
    2318                 :          0 :     desc.type = DOUBLE;
    2319                 :        185 :     return data;
    2320                 :            : }
    2321                 :            : 
    2322                 :          0 : void* MeshImpl::vtk_read_color_attrib( FileTokenizer& tokens, long count, TagDescription& tag, MsqError& err )
    2323                 :            : {
    2324                 :            :     long size;
    2325         [ #  # ]:          0 :     tokens.get_long_ints( 1, &size, err );
    2326 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2327                 :            : 
    2328         [ #  # ]:          0 :     if( size < 1 )
    2329                 :            :     {
    2330                 :            :         MSQ_SETERR( err )
    2331 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid size (%ld) at line %d", size, tokens.line_number() );
                 [ #  # ]
    2332                 :          0 :         return 0;
    2333                 :            :     }
    2334                 :            : 
    2335                 :          0 :     float* data = (float*)malloc( sizeof( float ) * count * size );
    2336         [ #  # ]:          0 :     tokens.get_floats( count * size, data, err );
    2337 [ #  # ][ #  # ]:          0 :     if( MSQ_CHKERR( err ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    2338                 :            :     {
    2339                 :          0 :         free( data );
    2340                 :          0 :         return 0;
    2341                 :            :     }
    2342                 :            : 
    2343                 :          0 :     tag.size = size * sizeof( float );
    2344                 :          0 :     tag.type = DOUBLE;
    2345                 :          0 :     return data;
    2346                 :            : }
    2347                 :            : 
    2348                 :          0 : void* MeshImpl::vtk_read_vector_attrib( FileTokenizer& tokens, long count, TagDescription& tag, MsqError& err )
    2349                 :            : {
    2350                 :          0 :     int type = tokens.match_token( vtk_type_names, err );
    2351 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
                 [ #  # ]
    2352                 :            : 
    2353                 :          0 :     void* result = vtk_read_typed_data( tokens, type, 3, count, tag, err );
    2354 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
                 [ #  # ]
    2355                 :          0 :     return result;
    2356                 :            : }
    2357                 :            : 
    2358                 :          0 : void* MeshImpl::vtk_read_texture_attrib( FileTokenizer& tokens, long count, TagDescription& tag, MsqError& err )
    2359                 :            : {
    2360                 :            :     int type, dim;
    2361         [ #  # ]:          0 :     tokens.get_integers( 1, &dim, err );
    2362 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2363         [ #  # ]:          0 :     type = tokens.match_token( vtk_type_names, err );
    2364 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2365                 :            : 
    2366 [ #  # ][ #  # ]:          0 :     if( dim < 1 || dim > 3 )
    2367                 :            :     {
    2368                 :            :         MSQ_SETERR( err )
    2369 [ #  # ][ #  # ]:          0 :         ( MsqError::PARSE_ERROR, "Invalid dimension (%d) at line %d.", dim, tokens.line_number() );
                 [ #  # ]
    2370                 :          0 :         return 0;
    2371                 :            :     }
    2372                 :            : 
    2373         [ #  # ]:          0 :     void* result = vtk_read_typed_data( tokens, type, dim, count, tag, err );
    2374 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
         [ #  # ][ #  # ]
                 [ #  # ]
    2375                 :          0 :     return result;
    2376                 :            : }
    2377                 :            : 
    2378                 :          0 : void* MeshImpl::vtk_read_tensor_attrib( FileTokenizer& tokens, long count, TagDescription& tag, MsqError& err )
    2379                 :            : {
    2380                 :          0 :     int type = tokens.match_token( vtk_type_names, err );
    2381 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
                 [ #  # ]
    2382                 :            : 
    2383                 :          0 :     void* result = vtk_read_typed_data( tokens, type, 9, count, tag, err );
    2384 [ #  # ][ #  # ]:          0 :     MSQ_ERRZERO( err );
                 [ #  # ]
    2385                 :          0 :     return result;
    2386                 :            : }
    2387                 :            : 
    2388                 :         22 : void MeshImpl::vtk_write_attrib_data( std::ostream& file, const TagDescription& desc, const void* data, size_t count,
    2389                 :            :                                       MsqError& err ) const
    2390                 :            : {
    2391                 :            :     // [email protected]: we now allow this type to be able to write e.g. GLOBAL_ID for parallel
    2392                 :            :     // meshes
    2393                 :            :     /*
    2394                 :            :     if (desc.type == HANDLE)
    2395                 :            :     {
    2396                 :            :       MSQ_SETERR(err)("Cannot write HANDLE tag data to VTK file.",
    2397                 :            :                       MsqError::FILE_FORMAT);
    2398                 :            :       return;
    2399                 :            :       }*/
    2400                 :            : 
    2401                 :         22 :     TagDescription::VtkType vtk_type = desc.vtkType;
    2402         [ +  - ]:         22 :     unsigned vlen                    = desc.size / MeshImplTags::size_from_tag_type( desc.type );
    2403                 :            :     // guess one from data length if not set
    2404         [ -  + ]:         22 :     if( vtk_type == TagDescription::NONE )
    2405                 :            :     {
    2406      [ #  #  # ]:          0 :         switch( vlen )
    2407                 :            :         {
    2408                 :            :             default:
    2409                 :          0 :                 vtk_type = TagDescription::SCALAR;
    2410                 :          0 :                 break;
    2411                 :            :             case 3:
    2412                 :          0 :                 vtk_type = TagDescription::VECTOR;
    2413                 :          0 :                 break;
    2414                 :            :             case 9:
    2415                 :          0 :                 vtk_type = TagDescription::TENSOR;
    2416                 :          0 :                 break;
    2417                 :            :                 return;
    2418                 :            :         }
    2419                 :            :     }
    2420                 :            : 
    2421                 :            :     // [email protected]: from class Mesh, the typenames below should correspond in order...
    2422                 :            :     // enum TagType { BYTE, BOOL, INT, DOUBLE, HANDLE };
    2423                 :            : 
    2424                 :         22 :     const char* const typenames[] = { "unsigned_char", "bit", "int", "double", "unsigned_long" };
    2425 [ +  - ][ +  - ]:         44 :     std::string field, member;
                 [ +  - ]
    2426                 :            : 
    2427                 :            :     int num_per_line;
    2428   [ +  -  -  -  :         22 :     switch( vtk_type )
             -  -  +  - ]
    2429                 :            :     {
    2430                 :            :         case TagDescription::SCALAR:
    2431                 :         20 :             num_per_line = vlen;
    2432 [ +  - ][ +  - ]:         20 :             file << "SCALARS " << desc.name << " " << typenames[desc.type] << " " << vlen << "\n";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2433         [ +  - ]:         20 :             file << "LOOKUP_TABLE default\n";
    2434                 :         20 :             break;
    2435                 :            :         case TagDescription::COLOR:
    2436                 :          0 :             num_per_line = vlen;
    2437 [ #  # ][ #  # ]:          0 :             file << "COLOR_SCALARS " << desc.name << " " << vlen << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    2438                 :          0 :             break;
    2439                 :            :         case TagDescription::VECTOR:
    2440                 :          0 :             num_per_line = 3;
    2441         [ #  # ]:          0 :             if( vlen != 3 )
    2442                 :            :             {
    2443                 :            :                 MSQ_SETERR( err )
    2444                 :            :                 ( MsqError::INTERNAL_ERROR, "Tag \"%s\" is labeled as a VTK vector attribute but has %u values.",
    2445 [ #  # ][ #  # ]:          0 :                   desc.name.c_str(), vlen );
    2446                 :          0 :                 return;
    2447                 :            :             }
    2448 [ #  # ][ #  # ]:          0 :             file << "VECTORS " << desc.name << " " << typenames[desc.type] << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    2449                 :          0 :             break;
    2450                 :            :         case TagDescription::NORMAL:
    2451                 :          0 :             num_per_line = 3;
    2452         [ #  # ]:          0 :             if( vlen != 3 )
    2453                 :            :             {
    2454                 :            :                 MSQ_SETERR( err )
    2455                 :            :                 ( MsqError::INTERNAL_ERROR, "Tag \"%s\" is labeled as a VTK normal attribute but has %u values.",
    2456 [ #  # ][ #  # ]:          0 :                   desc.name.c_str(), vlen );
    2457                 :          0 :                 return;
    2458                 :            :             }
    2459 [ #  # ][ #  # ]:          0 :             file << "NORMALS " << desc.name << " " << typenames[desc.type] << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    2460                 :          0 :             break;
    2461                 :            :         case TagDescription::TEXTURE:
    2462                 :          0 :             num_per_line = vlen;
    2463 [ #  # ][ #  # ]:          0 :             file << "TEXTURE_COORDINATES " << desc.name << " " << typenames[desc.type] << " " << vlen << "\n";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2464                 :          0 :             break;
    2465                 :            :         case TagDescription::TENSOR:
    2466                 :          0 :             num_per_line = 3;
    2467         [ #  # ]:          0 :             if( vlen != 9 )
    2468                 :            :             {
    2469                 :            :                 MSQ_SETERR( err )
    2470                 :            :                 ( MsqError::INTERNAL_ERROR, "Tag \"%s\" is labeled as a VTK tensor attribute but has %u values.",
    2471 [ #  # ][ #  # ]:          0 :                   desc.name.c_str(), vlen );
    2472                 :          0 :                 return;
    2473                 :            :             }
    2474 [ #  # ][ #  # ]:          0 :             file << "TENSORS " << desc.name << " " << typenames[desc.type] << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    2475                 :          0 :             break;
    2476                 :            :         case TagDescription::FIELD:
    2477                 :          2 :             num_per_line = vlen;
    2478 [ +  - ][ +  - ]:          2 :             get_field_names( desc, field, member, err );MSQ_ERRRTN( err );
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    2479 [ +  - ][ +  - ]:          2 :             file << member << " " << vlen << " " << count << " " << typenames[desc.type] << "\n";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2480                 :          2 :             break;
    2481                 :            :         default:
    2482 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( err )( "Unknown VTK attribute type for tag.", MsqError::INTERNAL_ERROR );
    2483                 :          0 :             return;
    2484                 :            :     }
    2485                 :            : 
    2486                 :         22 :     size_t i, total = count * vlen;
    2487         [ +  - ]:         22 :     char* space = new char[num_per_line];
    2488                 :         22 :     memset( space, ' ', num_per_line );
    2489                 :         22 :     space[num_per_line - 1]    = '\n';
    2490                 :         22 :     const unsigned char* odata = (const unsigned char*)data;
    2491                 :         22 :     const bool* bdata          = (const bool*)data;
    2492                 :         22 :     const int* idata           = (const int*)data;
    2493                 :         22 :     const long* ldata          = (const long*)data;
    2494                 :         22 :     const double* ddata        = (const double*)data;
    2495   [ -  -  +  +  :         22 :     switch( desc.type )
                   -  - ]
    2496                 :            :     {
    2497                 :            :         case BYTE:
    2498         [ #  # ]:          0 :             for( i = 0; i < total; ++i )
    2499 [ #  # ][ #  # ]:          0 :                 file << (unsigned int)odata[i] << space[i % num_per_line];
    2500                 :          0 :             break;
    2501                 :            :         case BOOL:
    2502         [ #  # ]:          0 :             for( i = 0; i < total; ++i )
    2503 [ #  # ][ #  # ]:          0 :                 file << ( bdata[i] ? '1' : '0' ) << space[i % num_per_line];
                 [ #  # ]
    2504                 :          0 :             break;
    2505                 :            :         case INT:
    2506         [ +  + ]:       3357 :             for( i = 0; i < total; ++i )
    2507 [ +  - ][ +  - ]:       3339 :                 file << idata[i] << space[i % num_per_line];
    2508                 :         18 :             break;
    2509                 :            :         case DOUBLE:
    2510         [ +  + ]:       2254 :             for( i = 0; i < total; ++i )
    2511 [ +  - ][ +  - ]:       2250 :                 file << ddata[i] << space[i % num_per_line];
    2512                 :          4 :             break;
    2513                 :            :         case HANDLE:
    2514         [ #  # ]:          0 :             for( i = 0; i < total; ++i )
    2515 [ #  # ][ #  # ]:          0 :                 file << ldata[i] << space[i % num_per_line];
    2516                 :          0 :             break;
    2517                 :            :         default:
    2518 [ #  # ][ #  # ]:          0 :             MSQ_SETERR( err )( "Unknown tag type.", MsqError::INTERNAL_ERROR );
    2519                 :            :     }
    2520 [ +  - ][ +  - ]:         44 :     delete[] space;
    2521                 :            : }
    2522                 :            : 
    2523                 :            : /**************************************************************************
    2524                 :            :  *                               TAGS
    2525                 :            :  **************************************************************************/
    2526                 :            : 
    2527                 :         22 : TagHandle MeshImpl::tag_create( const std::string& name, TagType type, unsigned length, const void* defval,
    2528                 :            :                                 MsqError& err )
    2529                 :            : {
    2530                 :            :     TagDescription::VtkType vtype;
    2531         [ +  - ]:         22 :     std::string field;
    2532   [ +  +  -  + ]:         22 :     switch( length )
    2533                 :            :     {
    2534                 :            :         case 1:
    2535                 :         14 :             vtype = TagDescription::SCALAR;
    2536                 :         14 :             break;
    2537                 :            :         case 3:
    2538                 :          6 :             vtype = TagDescription::VECTOR;
    2539                 :          6 :             break;
    2540                 :            :         case 9:
    2541                 :          0 :             vtype = TagDescription::TENSOR;
    2542                 :          0 :             break;
    2543                 :            :         default:
    2544                 :          2 :             vtype = TagDescription::FIELD;
    2545         [ +  - ]:          2 :             field = MESQUITE_FIELD_TAG;
    2546                 :          2 :             break;
    2547                 :            :     }
    2548                 :            : 
    2549                 :            :     // If tag name contains a space, assume the tag name
    2550                 :            :     // is a concatenation of the VTK field and member names.
    2551 [ +  + ][ +  - ]:         22 :     if( vtype != TagDescription::FIELD && name.find( " " ) != std::string::npos ) vtype = TagDescription::FIELD;
         [ -  + ][ -  + ]
    2552                 :            : 
    2553         [ +  - ]:         22 :     size_t size = MeshImplTags::size_from_tag_type( type );
    2554 [ +  - ][ +  - ]:         22 :     TagDescription desc( name, type, vtype, length * size, field );
                 [ +  - ]
    2555         [ +  - ]:         22 :     size_t index = myTags->create( desc, defval, err );
    2556 [ +  - ][ +  + ]:         22 :     MSQ_ERRZERO( err );
         [ +  - ][ +  - ]
                 [ +  + ]
    2557                 :         22 :     return (TagHandle)index;
    2558                 :            : }
    2559                 :            : 
    2560                 :        152 : void MeshImpl::tag_delete( TagHandle handle, MsqError& err )
    2561                 :            : {
    2562 [ -  + ][ #  # ]:        152 :     myTags->destroy( (size_t)handle, err );MSQ_CHKERR( err );
    2563                 :        152 : }
    2564                 :            : 
    2565                 :        337 : TagHandle MeshImpl::tag_get( const std::string& name, MsqError& err )
    2566                 :            : {
    2567                 :        337 :     size_t index = myTags->handle( name, err );
    2568 [ -  + ][ #  # ]:        337 :     MSQ_ERRZERO( err );
                 [ -  + ]
    2569 [ +  + ][ +  - ]:        337 :     if( !index ) MSQ_SETERR( err )( MsqError::TAG_NOT_FOUND, "could not find tag \"%s\"", name.c_str() );
    2570                 :        337 :     return (TagHandle)index;
    2571                 :            : }
    2572                 :            : 
    2573                 :         28 : void MeshImpl::tag_properties( TagHandle handle, std::string& name, TagType& type, unsigned& length, MsqError& err )
    2574                 :            : {
    2575 [ -  + ][ #  # ]:         28 :     const TagDescription& desc = myTags->properties( (size_t)handle, err );MSQ_ERRRTN( err );
                 [ -  + ]
    2576                 :            : 
    2577                 :         28 :     name   = desc.name;
    2578                 :         28 :     type   = desc.type;
    2579                 :         28 :     length = (unsigned)( desc.size / MeshImplTags::size_from_tag_type( desc.type ) );
    2580                 :            : }
    2581                 :            : 
    2582                 :        450 : void MeshImpl::tag_set_element_data( TagHandle handle, size_t num_elems, const ElementHandle* elem_array,
    2583                 :            :                                      const void* values, MsqError& err )
    2584                 :            : {
    2585 [ -  + ][ #  # ]:        450 :     myTags->set_element_data( (size_t)handle, num_elems, (const size_t*)elem_array, values, err );MSQ_CHKERR( err );
    2586                 :        450 : }
    2587                 :            : 
    2588                 :     149856 : void MeshImpl::tag_get_element_data( TagHandle handle, size_t num_elems, const ElementHandle* elem_array, void* values,
    2589                 :            :                                      MsqError& err )
    2590                 :            : {
    2591 [ -  + ][ #  # ]:     149856 :     myTags->get_element_data( (size_t)handle, num_elems, (const size_t*)elem_array, values, err );MSQ_CHKERR( err );
    2592                 :     149856 : }
    2593                 :            : 
    2594                 :         18 : void MeshImpl::tag_set_vertex_data( TagHandle handle, size_t num_elems, const VertexHandle* elem_array,
    2595                 :            :                                     const void* values, MsqError& err )
    2596                 :            : {
    2597 [ -  + ][ #  # ]:         18 :     myTags->set_vertex_data( (size_t)handle, num_elems, (const size_t*)elem_array, values, err );MSQ_CHKERR( err );
    2598                 :         18 : }
    2599                 :            : 
    2600                 :    4811112 : void MeshImpl::tag_get_vertex_data( TagHandle handle, size_t num_elems, const VertexHandle* elem_array, void* values,
    2601                 :            :                                     MsqError& err )
    2602                 :            : {
    2603 [ -  + ][ #  # ]:    4811112 :     myTags->get_vertex_data( (size_t)handle, num_elems, (const size_t*)elem_array, values, err );MSQ_CHKERR( err );
    2604                 :    4811112 : }
    2605                 :            : 
    2606 [ +  - ][ +  - ]:        128 : }  // namespace MBMesquite

Generated by: LCOV version 1.11