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
|