Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Mesh/MeshImpl.cpp
Go to the documentation of this file.
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  diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
24  pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov,
25  kraftche@cae.wisc.edu
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 kraftche@cae.wisc.edu
34 //
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 
55 #ifdef MSQ_USE_OLD_STD_HEADERS
56 # include <string.h>
57 # include <vector.h>
58 # include <stdlib.h>
59 #else
60 # include <string>
61 # include <vector>
62 # include <cstdlib>
63  using std::string;
64  using std::vector;
65 #endif
66 
67 #ifdef MSQ_USE_OLD_IO_HEADERS
68 # include <fstream.h>
69 # include <iomanip.h>
70 #else
71 # include <fstream>
72 # include <iomanip>
73  using std::ifstream;
74  using std::ofstream;
75  using std::endl;
76 #endif
77 
78 #ifdef MSQ_USING_EXODUS
79 #include "exodusII.h"
80 #endif
81 
82 #include "MsqDebug.hpp"
83 namespace Mesquite
84 {
85 
86 
88  : numCoords(0),
89  myMesh( new MeshImplData ),
90  myTags( new MeshImplTags )
91 {}
92 
94 {
95  delete myMesh;
96  delete myTags;
97 }
98 
100 {
101  myMesh->clear();
102  myTags->clear();
103 }
104 
105 
106 void MeshImpl::write_vtk(const char* out_filename, MsqError &err)
107 {
108  ofstream file(out_filename);
109  if (!file)
110  {
112  return;
113  }
114 
115  // Write a header
116  file << "# vtk DataFile Version 2.0\n";
117  file << "Mesquite Mesh\n";
118  file << "ASCII\n";
119  file << "DATASET UNSTRUCTURED_GRID\n";
120 
121  // Write vertex coordinates
122  file << "POINTS " << myMesh->num_vertices() << " float\n";
123 
124  std::vector<size_t> vertex_indices( myMesh->max_vertex_index() );
125  size_t i, count = 0;
126  for (i = 0; i < myMesh->max_vertex_index(); ++i)
127  {
128  if (myMesh->is_vertex_valid(i))
129  {
130  Vector3D coords = myMesh->get_vertex_coords( i, err ); MSQ_ERRRTN(err);
131  file << coords[0] << ' ' << coords[1] << ' ' << coords[2] << '\n';
132  vertex_indices[i] = count++;
133  }
134  else
135  {
136  vertex_indices[i] = myMesh->max_vertex_index();
137  }
138  }
139 
140  // Write out the connectivity table
141  size_t connectivity_size = myMesh->num_elements() + myMesh->num_vertex_uses();
142  file << "CELLS " << myMesh->num_elements() << ' ' << connectivity_size << '\n';
143  ElementIterator* e_iter = element_iterator(err); MSQ_ERRRTN(err);
144  msq_std::vector<VertexHandle> conn;
145  while (!e_iter->is_at_end())
146  {
147  ElementHandle elem = **e_iter;
148  count = element_get_attached_vertex_count( elem, err ); MSQ_ERRRTN(err);
149  if (count > conn.size())
150  conn.resize(count);
151 
152  element_get_connectivity( elem, &conn[0], conn.size(), err ); MSQ_ERRRTN(err);
153  EntityTopology topo = element_get_topology( **e_iter, err ); MSQ_ERRRTN(err);
154 
155  // If necessary, convert from Exodus to VTK node-ordering.
156  if (topo == PRISM) // VTK Wedge
157  {
158  msq_std::swap( conn[1], conn[2] );
159  msq_std::swap( conn[4], conn[5] );
160  }
161  else if (topo == HEXAHEDRON && count == 20) // VTK Quadratic Hex
162  {
163  msq_std::swap( conn[12], conn[16] );
164  msq_std::swap( conn[13], conn[17] );
165  msq_std::swap( conn[14], conn[18] );
166  msq_std::swap( conn[15], conn[19] );
167  }
168 
169  file << count;
170  for (i = 0; i < count; ++i)
171  file << ' ' << vertex_indices[(size_t)conn[i]];
172  file << '\n';
173 
174  ++*e_iter;
175  }
176 
177  // Write out the element types
178  file << "CELL_TYPES " << myMesh->num_elements() << '\n';
179  e_iter->restart();
180  while (!e_iter->is_at_end())
181  {
182  EntityTopology topo = element_get_topology( **e_iter, err ); MSQ_ERRRTN(err);
183  count = element_get_attached_vertex_count( **e_iter, err ); MSQ_ERRRTN(err);
184  int type;
185  switch (topo) {
186  case POLYGON: type = 7; break;
187  case TRIANGLE: type = count == 6 ? 22 : 5; break;
188  case QUADRILATERAL: type = count == 8 ? 23 : 9; break;
189  case TETRAHEDRON: type = count == 10 ? 24 : 10; break;
190  case HEXAHEDRON: type = count == 20 ? 25 : 12; break;
191  case PRISM: type = 13; break;
192  case PYRAMID: type = 14; break;
193  default:
195  "Cannot write element type %d to a VTK file\n",
196  (int)topo );
197  delete e_iter;
198  return;
199  }
200 
201  file << type << '\n';
202  e_iter->operator++();
203  }
204  delete e_iter;
205 
206  // Write out which points are fixed.
207  file << "POINT_DATA " << myMesh->num_vertices()
208  << "\nSCALARS fixed bit\nLOOKUP_TABLE default\n";
209  for (i = 0; i < myMesh->max_vertex_index(); ++i)
210  if (myMesh->is_vertex_valid( i ))
211  file <<( myMesh->vertex_is_fixed( i, err ) ? "1" : "0") << "\n";
212 
213  // Write vertex tag data to vtk attributes
215  for (tagiter = myTags->tag_begin(); tagiter != myTags->tag_end(); ++tagiter)
216  {
217  bool havevert = myTags->tag_has_vertex_data( *tagiter, err ); MSQ_ERRRTN(err);
218  if (!havevert)
219  continue;
220 
221  const TagDescription& desc = myTags->properties( *tagiter, err );
222  MSQ_ERRRTN(err);
223 
224  std::vector<char> tagdata( myMesh->num_vertices() * desc.size );
225  std::vector<char>::iterator iter = tagdata.begin();
226  for (i = 0; i < myMesh->max_vertex_index(); ++i)
227  {
228  if (myMesh->is_vertex_valid(i))
229  {
230  myTags->get_vertex_data( *tagiter, 1, &i, &*iter, err );
231  MSQ_ERRRTN(err);
232  iter += desc.size;
233  }
234  }
235 
236  vtk_write_attrib_data( file,
237  desc,
238  &tagdata[0],
239  myMesh->num_vertices(),
240  err );
241  MSQ_ERRRTN(err);
242  }
243 
244  // If there are any element attributes, write them
245  for (tagiter = myTags->tag_begin(); tagiter != myTags->tag_end(); ++tagiter)
246  {
247  bool haveelem = myTags->tag_has_element_data( *tagiter, err ); MSQ_ERRRTN(err);
248  if (haveelem)
249  {
250  file << "\nCELL_DATA " << myMesh->num_elements() << "\n";
251  break;
252  }
253  }
254  for (tagiter = myTags->tag_begin(); tagiter != myTags->tag_end(); ++tagiter)
255  {
256  bool haveelem = myTags->tag_has_element_data( *tagiter, err ); MSQ_ERRRTN(err);
257  if (!haveelem)
258  continue;
259 
260 
261  const TagDescription& desc = myTags->properties( *tagiter, err );
262  MSQ_ERRRTN(err);
263 
264  std::vector<char> tagdata( myMesh->num_elements() * desc.size );
265  std::vector<char>::iterator iter = tagdata.begin();
266  for (i = 0; i < myMesh->max_element_index(); ++i)
267  {
268  if (myMesh->is_element_valid(i))
269  {
270  myTags->get_element_data( *tagiter, 1, &i, &*iter, err );
271  MSQ_ERRRTN(err);
272  iter += desc.size;
273  }
274  }
275 
276  vtk_write_attrib_data( file,
277  desc,
278  &tagdata[0],
279  myMesh->num_elements(),
280  err );
281  MSQ_ERRRTN(err);
282  }
283 
284 
285  // Close the file
286  file.close();
287 }
288 
289 void MeshImpl::read_exodus(const char* in_filename , MsqError &err)
290 {
291 #ifndef MSQ_USING_EXODUS
293  MSQ_DBGOUT(1) << "Cannot read ExodusII file: " << in_filename << "\n";
294  return;
295 #else
296 
297  clear();
298 
299  int app_float_size = sizeof(double);
300  int file_float_size = 0;
301  float exo_version = 0;
302  int exo_err = 0;
303 
304  // Open the file
305  int file_id = ex_open(in_filename, EX_READ, &app_float_size,
306  &file_float_size, &exo_version);
307 
308  // Make sure we opened the file correctly
309  if (file_id < 0)
310  {
312  return;
313  }
314 
315  // make sure the file is saved as doubles
316  if (file_float_size != sizeof(double))
317  {
318  MSQ_SETERR(err)("File saved with float-sized reals. Can only read files "
319  "saved with doubles.", MsqError::NOT_IMPLEMENTED );
320  return;
321  }
322 
323  char title[MAX_LINE_LENGTH];
324  int dim, vert_count, elem_count, block_count, ns_count, ss_count;
325 
326  // get info about the file
327  exo_err = ex_get_init(file_id, title, &dim, &vert_count,
328  &elem_count, &block_count, &ns_count, &ss_count);
329  if (exo_err < 0)
330  {
331  MSQ_SETERR(err)("Unable to get entity counts from file.",
333  return;
334  }
335 
336  myMesh->allocate_vertices( vert_count, err ); MSQ_ERRRTN(err);
337  myMesh->allocate_elements( elem_count, err ); MSQ_ERRRTN(err);
338 
339  // Now fill in the data
340 
341  // Get the vertex coordinates
342  msq_std::vector<double> coords(vert_count * 3);
343  double* x_iter = &coords[0];
344  double* y_iter = &coords[vert_count];
345  double* z_iter = &coords[2*vert_count];
346  numCoords = dim;
347  if (dim == 2)
348  {
349  exo_err = ex_get_coord( file_id, x_iter, y_iter, 0 );
350  memset( z_iter, 0, sizeof(double)*vert_count );
351  }
352  else
353  {
354  exo_err = ex_get_coord( file_id, x_iter, y_iter, z_iter );
355  }
356  // Make sure it worked
357  if (exo_err < 0)
358  {
359  MSQ_SETERR(err)("Unable to retrieve vertex coordinates from file.",
361  return;
362  }
363 
364  // Store vertex coordinates in vertex array
365  int i;
366  for (i = 0; i < vert_count; ++i)
367  myMesh->reset_vertex( i, Vector3D(*(x_iter++), *(y_iter++), *(z_iter)++), false, err );
368  coords.clear();
369 
370 
371  // Get block list
372  msq_std::vector<int> block_ids(block_count);
373  exo_err = ex_get_elem_blk_ids(file_id, &block_ids[0]);
374  if (exo_err < 0)
375  {
376  MSQ_SETERR(err)("Unable to read block IDs from file.", MsqError::PARSE_ERROR);
377  return;
378  }
379 
380 
381  msq_std::vector<int> conn;
382  size_t index = 0;
383  for (i = 0; i < block_count; i++)
384  {
385  // Get info about this block's elements
386  char elem_type_str[MAX_STR_LENGTH];
387  int num_block_elems, verts_per_elem, num_atts;
388  exo_err = ex_get_elem_block(file_id, block_ids[i], elem_type_str,
389  &num_block_elems, &verts_per_elem,
390  &num_atts);
391  if (exo_err < 0)
392  {
393  MSQ_SETERR(err)("Unable to read parameters for block.",MsqError::PARSE_ERROR);
394  return;
395  }
396 
397  // Figure out which type of element we're working with
398  EntityTopology elem_type;
399  for (int j = 0; j < 3; j++)
400  elem_type_str[j] = toupper(elem_type_str[j]);
401  if (!strncmp(elem_type_str, "TRI", 3))
402  {
403  elem_type = Mesquite::TRIANGLE;
404  }
405  else if (!strncmp(elem_type_str, "QUA", 3) ||
406  !strncmp(elem_type_str, "SHE", 3))
407  {
408  elem_type = Mesquite::QUADRILATERAL;
409  }
410  else if (!strncmp(elem_type_str, "HEX", 3))
411  {
412  elem_type = Mesquite::HEXAHEDRON;
413  }
414  else if (!strncmp(elem_type_str, "TET", 3))
415  {
416  elem_type = Mesquite::TETRAHEDRON;
417  }
418  else
419  {
420  MSQ_SETERR(err)("Unrecognized element type in block",
422  continue;
423  }
424 
425  if (conn.size() < (unsigned)(num_block_elems*verts_per_elem))
426  conn.resize( num_block_elems*verts_per_elem );
427  exo_err = ex_get_elem_conn( file_id, block_ids[i], &conn[0] );
428  if (exo_err < 0)
429  {
430  MSQ_SETERR(err)("Unable to read element block connectivity.",
432  return;
433  }
434 
435  msq_std::vector<size_t> vertices(verts_per_elem);
436  msq_std::vector<int>::iterator conn_iter = conn.begin();
437  for (const size_t end = index + num_block_elems; index < end; ++index)
438  {
439  for (msq_std::vector<size_t>::iterator iter = vertices.begin();
440  iter != vertices.end(); ++iter, ++conn_iter)
441  *iter = *conn_iter - 1;
442 
443  myMesh->reset_element( index, vertices, elem_type, err ); MSQ_CHKERR(err);
444  }
445  }
446 
447  // Finally, mark boundary nodes
448  int num_fixed_nodes=0;
449  int num_dist_in_set=0;
450  if(ns_count>0){
451  exo_err=ex_get_node_set_param(file_id,111,&num_fixed_nodes,
452  &num_dist_in_set);
453  if(exo_err<0){
454  MSQ_PRINT(1)("\nError opening nodeset 111, no boundary nodes marked.");
455  num_fixed_nodes=0;
456  }
457  }
458  msq_std::vector<int> fixed_nodes(num_fixed_nodes);
459  exo_err = ex_get_node_set(file_id, 111, &fixed_nodes[0]);
460  if(exo_err<0){
461  MSQ_SETERR(err)("Error retrieving fixed nodes.", MsqError::PARSE_ERROR);
462  }
463 
464  // See if this vertex is marked as a boundary vertex
465  for (i=0; i < num_fixed_nodes; ++i)
466  {
467  myMesh->fix_vertex( fixed_nodes[i]-1, true, err ); MSQ_CHKERR(err);
468  }
469 
470  // Finish up
471  exo_err=ex_close(file_id);
472  if(exo_err<0)
473  MSQ_SETERR(err)("Error closing Exodus file.", MsqError::IO_ERROR);
474 #endif
475 }
477 void Mesquite::MeshImpl::write_exodus(const char* out_filename,
478  Mesquite::MsqError &err)
479 {
480  //just return an error if we don't have access to exodus
481 #ifndef MSQ_USING_EXODUS
482  MSQ_SETERR(err)("Exodus not enabled in this build of Mesquite",
484  MSQ_DBGOUT(1) << "Cannot read ExodusII file: " << out_filename << "\n";
485  return;
486 #else
487  size_t i, j, k;
488  if (!myMesh || !myMesh->num_vertices())
489  {
490  MSQ_SETERR(err)("No vertices in MeshImpl. Nothing written to file.",
492  return;
493  }
494  //get some element info
495  //We need to know how many of each element type we have. We
496  //are going to create an element block for each element type
497  //that exists the mesh. Block 1 will be tri3; block 2 will be
498  //shell; block 3 will be tetra, and block 4 will be hex.
499  const unsigned MAX_NODES = 27;
500  const unsigned MIN_NODES = 2;
501  int counts[MIXED][MAX_NODES+1];
502  memset( counts, 0, sizeof(counts) );
503 
504  for (i = 0; i < myMesh->max_element_index(); ++i)
505  {
506  if (!myMesh->is_element_valid(i))
507  continue;
508 
509  EntityTopology type = myMesh->element_topology(i, err); MSQ_ERRRTN(err);
510  unsigned nodes = myMesh->element_connectivity(i, err).size(); MSQ_ERRRTN(err);
511  if ((unsigned)type >= MIXED || nodes < MIN_NODES || nodes > MAX_NODES)
512  {
513  MSQ_SETERR(err)("Invalid element typology.", MsqError::INTERNAL_ERROR);
514  return;
515  }
516  ++counts[type][nodes];
517  }
518 
519  // Count number of required element blocks
520  int block_count = 0;
521  for (i = 0; i < MIXED; ++i)
522  for (j = MIN_NODES; j < MAX_NODES; ++j)
523  if (counts[i][j])
524  ++block_count;
525 
526  //figure out if we have fixed nodes, if so, we need a nodeset
527  int num_fixed_nodes=0;
528  for (i = 0; i < myMesh->max_vertex_index(); ++i)
529  {
530  bool fixed = myMesh->is_vertex_valid(i) &&
531  myMesh->vertex_is_fixed(i, err); MSQ_ERRRTN(err);
532  num_fixed_nodes += fixed;
533  }
534 
535 
536  //write doubles instead of floats
537  int app_float_size = sizeof(double);
538  int file_float_size = sizeof(double);
539  int exo_err = 0;
540 
541  // Create the file. If it exists, clobber it. This could be dangerous.
542  int file_id = ex_create(out_filename, EX_CLOBBER, &app_float_size,
543  &file_float_size);
544 
545  // Make sure we opened the file correctly
546  if (file_id < 0)
547  {
549  return;
550  }
551 
552  char title[MAX_LINE_LENGTH]="Mesquite Export";
553 
554  size_t vert_count=0;
555  size_t elem_count=0;
556  size_t temp_var=0;
557  get_all_sizes(vert_count, elem_count, temp_var, err);
558 
559  int ns_count=0;
560  if(num_fixed_nodes>0)
561  ns_count=1;
562  int ss_count=0;
563 
564  // put the initial info about the file
565  exo_err = ex_put_init(file_id, title, numCoords, vert_count,
566  elem_count, block_count, ns_count, ss_count);
567  if (exo_err < 0)
568  {
569  MSQ_SETERR(err)("Unable to initialize file data.", MsqError::IO_ERROR);
570  return;
571  }
572 
573 
574  // Gather vertex coordinate data and write to file.
575  msq_std::vector<double> coords(vert_count * 3);
576  msq_std::vector<double>::iterator x, y, z;
577  x = coords.begin();
578  y = x + vert_count;
579  z = y + vert_count;
580  for (i = 0; i < myMesh->max_vertex_index(); ++i)
581  {
582  if (!myMesh->is_vertex_valid(i))
583  continue;
584 
585  if (z == coords.end())
586  {
587  MSQ_SETERR(err)("Array overflow", MsqError::INTERNAL_ERROR);
588  return;
589  }
590 
591  Vector3D coords = myMesh->get_vertex_coords(i, err); MSQ_ERRRTN(err);
592  *x = coords.x(); ++x;
593  *y = coords.y(); ++y;
594  *z = coords.z(); ++z;
595  }
596  if(z != coords.end())
597  {
598  MSQ_SETERR(err)("Counter at incorrect number.", MsqError::INTERNAL_ERROR);
599  return;
600  }
601  //put the coords
602  exo_err = ex_put_coord(file_id, &coords[0], &coords[vert_count], &coords[2*vert_count]);
603  if (exo_err < 0)
604  {
605  MSQ_SETERR(err)("Unable to put vertex coordinates in file.",MsqError::IO_ERROR);
606  return;
607  }
608 
609  //put the names of the coordinates
610  char* coord_names[] = { "x", "y", "z" };
611  exo_err = ex_put_coord_names(file_id, coord_names);
612 
613  // Create element-type arrays indexed by Mesquite::EntityTopology
614  const char* tri_name = "TRI";
615  const char* quad_name = "SHELL";
616  const char* tet_name = "TETRA";
617  const char* hex_name = "HEX";
618  const char* wdg_name = "PRISM";
619  const char* pyr_name = "PYR";
620  const char* exo_names[MIXED];
621  memset( exo_names, 0, sizeof(exo_names) );
622  exo_names[TRIANGLE] = tri_name;
623  exo_names[QUADRILATERAL] = quad_name;
624  exo_names[TETRAHEDRON] = tet_name;
625  exo_names[HEXAHEDRON] = hex_name;
626  exo_names[PRISM] = wdg_name;
627  exo_names[PYRAMID] = pyr_name;
628  unsigned min_nodes[MIXED];
629  memset( min_nodes, 0, sizeof(min_nodes) );
630  min_nodes[TRIANGLE] = 3;
631  min_nodes[QUADRILATERAL] = 4;
632  min_nodes[TETRAHEDRON] = 4;
633  min_nodes[HEXAHEDRON] = 8;
634  min_nodes[PRISM] = 6;
635  min_nodes[PYRAMID] = 5;
636 
637  // For each element type (topology and num nodes)
638  int block_id = 0;
639  char name_buf[16];
640  int num_atts = 0;
641  msq_std::vector<int> conn;
642  for (i = 0; i < MIXED; ++i)
643  {
644  for (j = MIN_NODES; j < MAX_NODES; ++j)
645  {
646  // Have any of this topo & count combination?
647  if (!counts[i][j])
648  continue;
649 
650  // Is a supported ExodusII type?
651  if (!exo_names[i])
652  {
654  "Element topology %d not supported by ExodusII", (int)i );
655  return;
656  }
657 
658  // Construct ExodusII element name from topo & num nodes
659  if (j == min_nodes[i])
660  strcpy( name_buf, exo_names[i] );
661  else
662  sprintf( name_buf, "%s%d", exo_names[i], (int)j );
663 
664  // Create element block
665  ++block_id;
666  exo_err = ex_put_elem_block( file_id, block_id, name_buf,
667  counts[i][j], j, num_atts );
668  if(exo_err<0)
669  {
670  MSQ_SETERR(err)("Error creating the tri block.", MsqError::IO_ERROR);
671  return;
672  }
673 
674  // For each element
675  conn.resize( counts[i][j] * j );
676  std::vector<int>::iterator iter = conn.begin();
677  for (k = 0; k < myMesh->max_element_index(); ++k)
678  {
679  // If not correct topo, skip it.
680  if (!myMesh->is_element_valid(k) ||
681  (unsigned)(myMesh->element_topology(k, err)) != i)
682  continue;
683  MSQ_ERRRTN(err);
684 
685  // If not correct number nodes, skip it
686  const msq_std::vector<size_t>& elem_conn = myMesh->element_connectivity(k, err);
687  MSQ_ERRRTN(err);
688  if (elem_conn.size() != j)
689  continue;
690 
691  // Append element connectivity to list
692  for (msq_std::vector<size_t>::const_iterator citer = elem_conn.begin();
693  citer != elem_conn.end(); ++citer, ++iter)
694  {
695  assert(iter != conn.end());
696  *iter = *citer + 1;
697  }
698  }
699 
700  // Make sure everything adds up
701  if (iter != conn.end())
702  {
704  return;
705  }
706 
707  // Write element block connectivity
708  exo_err = ex_put_elem_conn( file_id, block_id, &conn[0] );
709  if (exo_err<0)
710  {
711  MSQ_SETERR(err)("Error writing element connectivity.", MsqError::IO_ERROR );
712  return;
713  }
714  }
715  }
716 
717  // Finally, mark boundary nodes
718 
719  if(num_fixed_nodes>0){
720  exo_err=ex_put_node_set_param(file_id, 111, num_fixed_nodes, 0);
721  if(exo_err<0) {
722  MSQ_SETERR(err)("Error while initializing node set.", MsqError::IO_ERROR);
723  return;
724  }
725 
726  int node_id = 0;
727  msq_std::vector<int> fixed_nodes( num_fixed_nodes );
728  msq_std::vector<int>::iterator iter = fixed_nodes.begin();
729  for (i = 0; i < myMesh->max_vertex_index(); ++i)
730  {
731  if (!myMesh->is_vertex_valid(i))
732  continue;
733  ++node_id;
734 
735  if (myMesh->vertex_is_fixed( i, err ))
736  {
737  if (iter == fixed_nodes.end())
738  {
740  return;
741  }
742  *iter = node_id;
743  ++iter;
744  }
745  }
746 
747  if (iter != fixed_nodes.end())
748  {
750  return;
751  }
752 
753  exo_err=ex_put_node_set(file_id, 111, &fixed_nodes[0]);
754  if(exo_err<0) {
755  MSQ_SETERR(err)("Error while writing node set.", MsqError::IO_ERROR);
756  return;
757  }
758  }
759  exo_err=ex_close(file_id);
760  if(exo_err<0)
761  MSQ_SETERR(err)("Error closing Exodus file.", MsqError::IO_ERROR);
762 
763 #endif
764 }
765 // Returns whether this mesh lies in a 2D or 3D coordinate system.
767 {
768  return numCoords;
769 }
770 
771 
772 void MeshImpl::get_all_sizes( size_t& vertex_count,
773  size_t& element_count,
774  size_t& vertex_use_count,
775  MsqError& )
776 {
777  vertex_count = myMesh->num_vertices();
778  element_count = myMesh->num_elements();
779  vertex_use_count = myMesh->num_vertex_uses();
780 }
781 
782 void MeshImpl::get_all_mesh( VertexHandle* vert_array, size_t vert_len,
783  ElementHandle* elem_array, size_t elem_len,
784  size_t* elem_conn_offsets, size_t offset_len,
785  size_t* elem_conn_indices, size_t index_len,
786  MsqError& err )
787 {
788  if (vert_len < myMesh->num_vertices() ||
789  elem_len < myMesh->num_elements() ||
790  offset_len < myMesh->num_elements()+1 ||
791  index_len < myMesh->num_vertex_uses()) {
792  MSQ_SETERR(err)("Insufficient space in array", MsqError::INVALID_ARG );
793  return;
794  }
795 
796  myMesh->copy_mesh( (size_t*)vert_array,
797  (size_t*)elem_array,
798  elem_conn_offsets,
799  elem_conn_indices );
800 }
801 
803  size_t count, MsqError& err )
804 {
805  size_t result = 0;
806  for (size_t i = 0; i < count; ++i)
807  {
808  result += myMesh->element_connectivity( (size_t)(elem_array[i]), err ).size();
809  MSQ_ERRZERO(err);
810  }
811  return result;
812 }
813 
814 
815 // Returns a pointer to an iterator that iterates over the
816 // set of all vertices in this mesh. The calling code should
817 // delete the returned iterator when it is finished with it.
818 // If vertices are added or removed from the Mesh after obtaining
819 // an iterator, the behavior of that iterator is undefined.
821 {
822  return new MeshImplVertIter( myMesh );
823 }
824 
825 // Returns a pointer to an iterator that iterates over the
826 // set of all top-level elements in this mesh. The calling code should
827 // delete the returned iterator when it is finished with it.
828 // If elements are added or removed from the Mesh after obtaining
829 // an iterator, the behavior of that iterator is undefined.
831 {
832  return new MeshImplElemIter( myMesh );
833 }
834 
835 //************ Vertex Properties ********************
836 // Returns true or false, indicating whether the vertex
837 // is allowed to be repositioned. True indicates that the vertex
838 // is fixed and cannot be moved. Note that this is a read-only
839 // property; this flag can't be modified by users of the
840 // Mesquite::Mesh interface.
842 {
843  return false;
844 }
845 
846 // Sets on_bnd[] to true or false, indicating whether the vertex
847 // is on the boundary. Boundary nodes may be treated as
848 // a special case by some algorithms or culling methods.
849 // Note that this is a read-only
850 // property; this flag can't be modified by users of the
851 // Mesquite::Mesh interface.
853  VertexHandle vert_array[], bool on_bnd[],
854  size_t num_vtx, MsqError& err)
855 {
856  for (size_t i=0; i<num_vtx; ++i)
857  {
858  on_bnd[i] = myMesh->vertex_is_fixed( (size_t)vert_array[i], err );
859  MSQ_ERRRTN(err);
860  }
861 }
862 
863 // Get/set location of a vertex
865  const Mesh::VertexHandle vert_array[],
866  MsqVertex* coordinates,
867  size_t num_vtx,
868  MsqError& err)
869 {
870  for (size_t i=0; i<num_vtx; ++i) {
871  coordinates[i] = myMesh->get_vertex_coords( (size_t)vert_array[i], err );
872  MSQ_ERRRTN(err);
873  }
874 }
875 
876 
877 
879  VertexHandle vertex,
880  const Vector3D &coordinates,
881  MsqError& err)
882 {
883  myMesh->set_vertex_coords( (size_t)vertex, coordinates, err ); MSQ_CHKERR(err);
884 }
885 
886 // Each vertex has a byte-sized flag that can be used to store
887 // flags. This byte's value is neither set nor used by the mesh
888 // implementation. It is intended to be used by Mesquite algorithms.
889 // Until a vertex's byte has been explicitly set, its value is 0.
891  unsigned char byte,
892  MsqError& err)
893 {
894  vertices_set_byte( &vertex, &byte, 1, err ); MSQ_CHKERR(err);
895 }
896 
898  unsigned char *byte_array,
899  size_t array_size,
900  MsqError& err)
901 {
902  for (size_t i = 0; i < array_size; i++)
903  {
904  byte_array[i] = myMesh->get_vertex_byte( (size_t)vert_array[i], err );
905  MSQ_ERRRTN(err);
906  }
907 }
908 
909 // Retrieve the byte value for the specified vertex or vertices.
910 // The byte value is 0 if it has not yet been set via one of the
911 // *_set_byte() functions.
913  unsigned char *byte,
914  MsqError &err )
915 {
916  vertices_get_byte( &vertex, byte, 1, err ); MSQ_CHKERR(err);
917 }
918 
920  unsigned char *byte_array,
921  size_t array_size,
922  MsqError& err)
923 {
924  for (size_t i = 0; i < array_size; i++)
925  {
926  myMesh->set_vertex_byte( (size_t)vertex[i], byte_array[i], err );
927  MSQ_ERRRTN(err);
928  }
929 }
930 
931 
932 // Gets the number of elements attached to this vertex.
933 // Useful to determine how large the "elem_array" parameter
934 // of the vertex_get_attached_elements() function must be.
936  MsqError &err)
937 {
938  size_t result = myMesh->vertex_adjacencies( (size_t)vertex, err ).size();
939  MSQ_CHKERR(err);
940  return result;
941 }
942 
943 // Gets the elements attached to this vertex.
945  ElementHandle* elem_array,
946  size_t sizeof_elem_array,
947  MsqError& err )
948 {
949  const msq_std::vector<size_t>& elems
950  = myMesh->vertex_adjacencies( (size_t)vertex, err ); MSQ_ERRRTN(err);
951 
952  if (sizeof_elem_array < elems.size())
953  {
954  MSQ_SETERR(err)("Insufficient space in array", MsqError::INVALID_ARG );
955  return;
956  }
957 
958  memcpy( elem_array, &elems[0], elems.size() * sizeof(size_t) );
959 }
960 
961 
962 // Gets the number of vertices in this element.
963 // This data can also be found by querying the
964 // element's topology and getting the number
965 // of vertices per element for that topology type.
967  MsqError& err )
968 {
969  size_t result = myMesh->element_connectivity( (size_t)elem, err ).size();
970  MSQ_CHKERR(err);
971  return result;
972 }
973 
974 // Returns the vertices that are part of the topological definition of each
975 // element in the "elem_handles" array. When this function is called, the
976 // following must be true:
977 // a) "elem_handles" points at an array of "num_elems" element handles.
978 // b) "vert_handles" points at an array of size "sizeof_vert_handles"
979 // c) "csr_data" points at an array of size "sizeof_csr_data"
980 // d) "csr_offsets" points at an array of size "num_elems+1"
981 //
982 // When this function returns, adjacency information will be stored
983 // in csr format:
984 // a) "vert_handles" stores handles to all vertices found in one
985 // or more of the elements. Each vertex appears only
986 // once in "vert_handles", even if it is in multiple elements.
987 // b) "sizeof_vert_handles" is set to the number of vertex
988 // handles placed into "vert_handles".
989 // c) "sizeof_csr_data" is set to the total number of vertex uses (for
990 // example, sizeof_csr_data = 6 in the case of 2 TRIANGLES, even if
991 // the two triangles share some vertices).
992 // c) "csr_offsets" is filled such that csr_offset[i] indicates the location
993 // of entity i's first adjacency in "csr_data". The number of vertices
994 // in element i is equal to csr_offsets[i+1] - csr_offsets[i]. For this
995 // reason, csr_offsets[num_elems] is set to the new value of
996 // "sizeof_csr_data".
997 // d) "csr_data" stores integer offsets which give the location of
998 // each adjacency in the "vert_handles" array.
999 //
1000 // As an example of how to use this data, you can get the handle of the first
1001 // vertex in element #3 like this:
1002 // VertexHandle vh = vert_handles[ csr_data[ csr_offsets[3] ] ]
1003 //
1004 // and the second vertex of element #3 like this:
1005 // VertexHandle vh = vert_handles[ csr_data[ csr_offsets[3]+1 ] ]
1006 //
1008  size_t num_elems,
1009  VertexHandle* vert_handles,
1010  size_t& sizeof_vert_handles,
1011  size_t* csr_data,
1012  size_t& sizeof_csr_data,
1013  size_t* csr_offsets,
1014  MsqError& err )
1015 {
1016  if (num_elems == 0)
1017  return;
1018 
1019  if (num_elems == 1)
1020  {
1021  size_t elem = (size_t)elem_handles[0];
1022  const msq_std::vector<size_t>& conn
1023  = myMesh->element_connectivity( elem, err );
1024  MSQ_ERRRTN(err);
1025 
1026  if (conn.size() > sizeof_vert_handles ||
1027  conn.size() > sizeof_csr_data )
1028  {
1029  sizeof_vert_handles = sizeof_csr_data = conn.size();
1030  MSQ_SETERR(err)("Insufficient space in array.", MsqError::INVALID_ARG );
1031  return;
1032  }
1033 
1034  memcpy( vert_handles, &conn[0], sizeof(size_t)*conn.size() );
1035  csr_offsets[0] = 0;
1036  csr_offsets[1] = conn.size();
1037  for (size_t j = 0; j < conn.size(); ++j)
1038  csr_data[j] = j;
1039 
1040  return;
1041  }
1042 
1043 
1044  size_t vtx_count = 0;
1045  size_t use_count = 0;
1046 
1047  msq_std::map<size_t, size_t> index_map;
1048  for (size_t i = 0; i < num_elems; ++i)
1049  {
1050  size_t elem = (size_t)elem_handles[i];
1051  const msq_std::vector<size_t>& conn
1052  = myMesh->element_connectivity( elem, err );
1053  MSQ_ERRRTN(err);
1054  csr_offsets[i] = use_count;
1055 
1056  for (size_t j = 0; j < conn.size(); ++j)
1057  {
1058  size_t idx;
1059  size_t vert = conn[j];
1060  msq_std::map<size_t, size_t>::const_iterator iter = index_map.find( vert );
1061  if (iter == index_map.end())
1062  {
1063  idx = vtx_count++;
1064  if (idx < sizeof_vert_handles)
1065  vert_handles[idx] = (VertexHandle)vert;
1066  index_map[vert] = idx;
1067  }
1068  else
1069  {
1070  idx = iter->second;
1071  }
1072 
1073  if (use_count < sizeof_csr_data)
1074  csr_data[use_count] = idx;
1075  ++use_count;
1076  }
1077  }
1078  csr_offsets[num_elems] = use_count;
1079 
1080  if (vtx_count > sizeof_vert_handles ||
1081  use_count > sizeof_csr_data )
1082  {
1083  MSQ_SETERR(err)("Insufficient space in array.", MsqError::INVALID_ARG );
1084  }
1085 
1086  sizeof_vert_handles = vtx_count;
1087  sizeof_csr_data = use_count;
1088 }
1089 
1091  VertexHandle* vert_array,
1092  size_t array_size,
1093  MsqError& err )
1094 {
1095  const msq_std::vector<size_t>& conn
1096  = myMesh->element_connectivity( (size_t)elem, err ); MSQ_ERRRTN(err);
1097  if (conn.size() > array_size)
1098  {
1099  MSQ_SETERR(err)("Insufficient array size", MsqError::INVALID_ARG);
1100  return;
1101  }
1102  memcpy( vert_array, &conn[0], conn.size() * sizeof(VertexHandle) );
1103 }
1104 
1105 
1106 // Returns the topology of the given entity.
1108 {
1109  EntityTopology result;
1110  elements_get_topologies( &entity_handle, &result, 1, err ); MSQ_CHKERR(err);
1111  return result;
1112 }
1113 
1114 // Returns the topologies of the given entities. The "entity_topologies"
1115 // array must be at least "num_elements" in size.
1116 void MeshImpl::elements_get_topologies( ElementHandle element_handle_array[],
1117  EntityTopology element_topologies[],
1118  size_t num_elements,
1119  MsqError& err)
1120 {
1121  for (size_t i = 0; i < num_elements; i++)
1122  {
1123  element_topologies[i] = myMesh->
1124  element_topology( (size_t)element_handle_array[i], err );
1125  MSQ_CHKERR(err);
1126  }
1127 }
1128 
1129 
1130 
1131 
1132 
1133 //**************** Memory Management ****************
1134 // Tells the mesh that the client is finished with a given
1135 // entity handle.
1137  Mesquite::Mesh::EntityHandle* /*handle_array*/,
1138  size_t /*num_handles*/,
1139  MsqError &/*err*/)
1140 {
1141  // Do nothing
1142 }
1143 
1144 // Instead of deleting a Mesh when you think you are done,
1145 // call release(). In simple cases, the implementation could
1146 // just call the destructor. More sophisticated implementations
1147 // may want to keep the Mesh object to live longer than Mesquite
1148 // is using it.
1150 {
1151  //delete this;
1152 }
1153 
1154 
1155 
1156 const char* const vtk_type_names[] = { "bit",
1157  "char",
1158  "unsigned_char",
1159  "short",
1160  "unsigned_short",
1161  "int",
1162  "unsigned_int",
1163  "long",
1164  "unsigned_long",
1165  "float",
1166  "double",
1167  0 };
1168 
1169 void MeshImpl::read_vtk( const char* filename, MsqError &err )
1170 {
1171  int major, minor;
1172  char vendor_string[257];
1173  size_t i;
1174 
1175  FILE* file = fopen( filename, "r" );
1176  if (!file)
1177  {
1179  return;
1180  }
1181 
1182  // Read file header
1183 
1184  if (!fgets( vendor_string, sizeof(vendor_string), file ))
1185  {
1187  fclose( file );
1188  return;
1189  }
1190 
1191  if (!strchr( vendor_string, '\n' ) ||
1192  2 != sscanf( vendor_string, "# vtk DataFile Version %d.%d", &major, &minor ))
1193  {
1195  fclose( file );
1196  return;
1197  }
1198 
1199  if (!fgets( vendor_string, sizeof(vendor_string), file ))
1200  {
1202  fclose( file );
1203  return;
1204  }
1205 
1206  // VTK spec says this should not exceed 256 chars.
1207  if (!strchr( vendor_string, '\n' ))
1208  {
1209  MSQ_SETERR(err)( "Vendor string (line 2) exceeds 256 characters.",
1211  fclose( file );
1212  return;
1213  }
1214 
1215 
1216  // Check file type
1217 
1218  FileTokenizer tokens( file );
1219  const char* const file_type_names[] = { "ASCII", "BINARY", 0 };
1220  int filetype = tokens.match_token( file_type_names, err ); MSQ_ERRRTN(err);
1221  if (2 == filetype) {
1222  MSQ_SETERR(err)( "Cannot read BINARY VTK files -- use ASCII.",
1224  return;
1225  }
1226 
1227  // Clear any existing data
1228  this->clear();
1229 
1230  // Read the mesh
1231  tokens.match_token( "DATASET", err ); MSQ_ERRRTN(err);
1232  vtk_read_dataset( tokens, err ); MSQ_ERRRTN(err);
1233 
1234  // Make sure file actually contained some mesh
1235  if (myMesh->num_elements() == 0)
1236  {
1237  MSQ_SETERR(err)("File contained no mesh.", MsqError::PARSE_ERROR);
1238  return;
1239  }
1240 
1241  // Read attribute data until end of file.
1242  const char* const block_type_names[] = { "POINT_DATA", "CELL_DATA", 0 };
1243  int blocktype = 0;
1244  while (!tokens.eof())
1245  {
1246  // get POINT_DATA or CELL_DATA
1247  int new_block_type = tokens.match_token( block_type_names, err );
1248  if (tokens.eof())
1249  {
1250  err.clear();
1251  break;
1252  }
1253  if (err)
1254  {
1255  // If next token was neither POINT_DATA nor CELL_DATA,
1256  // then there's another attribute under the current one.
1257  if (blocktype)
1258  {
1259  tokens.unget_token();
1260  err.clear();
1261  }
1262  else
1263  {
1264  MSQ_ERRRTN(err);
1265  }
1266  }
1267  else
1268  {
1269  blocktype = new_block_type;
1270  long count;
1271  tokens.get_long_ints( 1, &count, err); MSQ_ERRRTN(err);
1272 
1273  if (blocktype == 1 && (unsigned long)count != myMesh->num_vertices())
1274  {
1276  "Count inconsistent with number of vertices"
1277  " at line %d.", tokens.line_number());
1278  return;
1279  }
1280  else if (blocktype == 2 && (unsigned long)count != myMesh->num_elements())
1281  {
1283  "Count inconsistent with number of elements"
1284  " at line %d.", tokens.line_number());
1285  return;
1286  }
1287  }
1288 
1289 
1290  if (blocktype == 1)
1291  vtk_read_point_data( tokens, err );
1292  else
1293  vtk_read_cell_data ( tokens, err );
1294  MSQ_ERRRTN(err);
1295  }
1296 
1297  // There is no option for a 2-D mesh in VTK files. Always 3
1298  numCoords = 3;
1299 
1300  // Convert tag data for fixed nodes to internal bitmap
1301  TagHandle handle = tag_get( "fixed", err );
1302  if (!handle || MSQ_CHKERR(err)) return;
1303 
1304  const TagDescription& tag_desc = myTags->properties( (size_t)handle, err ); MSQ_ERRRTN(err);
1305  bool havedata = myTags->tag_has_vertex_data( (size_t)handle, err ); MSQ_ERRRTN(err);
1306  if (!havedata)
1307  {
1308  MSQ_SETERR(err)("'fixed' attribute on elements, not vertices", MsqError::FILE_FORMAT);
1309  return;
1310  }
1311 
1312  switch( tag_desc.type )
1313  {
1314  case BYTE:
1315  {
1316  char data;
1317  for (i = 0; i < myMesh->max_vertex_index(); ++i)
1318  {
1319  myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err ); MSQ_ERRRTN(err);
1320  myMesh->fix_vertex( i, !!data, err ); MSQ_ERRRTN(err);
1321  }
1322  break;
1323  }
1324  case BOOL:
1325  {
1326  bool data;
1327  for (i = 0; i < myMesh->max_vertex_index(); ++i)
1328  {
1329  myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err ); MSQ_ERRRTN(err);
1330  myMesh->fix_vertex( i, data, err ); MSQ_ERRRTN(err);
1331  }
1332  break;
1333  }
1334  case INT:
1335  {
1336  int data;
1337  for (i = 0; i < myMesh->max_vertex_index(); ++i)
1338  {
1339  myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err ); MSQ_ERRRTN(err);
1340  myMesh->fix_vertex( i, !!data, err ); MSQ_ERRRTN(err);
1341  }
1342  break;
1343  }
1344  case DOUBLE:
1345  {
1346  double data;
1347  for (i = 0; i < myMesh->max_vertex_index(); ++i)
1348  {
1349  myTags->get_vertex_data( (size_t)handle, 1, &i, &data, err ); MSQ_ERRRTN(err);
1350  myMesh->fix_vertex( i, !!data, err ); MSQ_ERRRTN(err);
1351  }
1352  break;
1353  }
1354  default:
1355  MSQ_SETERR(err)("'fixed' attribute has invalid type", MsqError::PARSE_ERROR);
1356  return;
1357  }
1358 
1359  tag_delete( handle, err );
1360 }
1361 
1363 {
1364  const char* const data_type_names[] = { "STRUCTURED_POINTS",
1365  "STRUCTURED_GRID",
1366  "UNSTRUCTURED_GRID",
1367  "POLYDATA",
1368  "RECTILINEAR_GRID",
1369  "FIELD",
1370  0 };
1371  int datatype = tokens.match_token( data_type_names, err ); MSQ_ERRRTN(err);
1372  switch( datatype )
1373  {
1374  case 1: vtk_read_structured_points( tokens, err ); break;
1375  case 2: vtk_read_structured_grid ( tokens, err ); break;
1376  case 3: vtk_read_unstructured_grid( tokens, err ); break;
1377  case 4: vtk_read_polydata ( tokens, err ); break;
1378  case 5: vtk_read_rectilinear_grid ( tokens, err ); break;
1379  case 6: vtk_read_field ( tokens, err ); break;
1380  }
1381 }
1382 
1383 
1385 {
1386  long i, j, k;
1387  long dims[3];
1388  double origin[3], space[3];
1389 
1390  tokens.match_token( "DIMENSIONS", err ); MSQ_ERRRTN(err);
1391  tokens.get_long_ints( 3, dims, err ); MSQ_ERRRTN(err);
1392  tokens.get_newline( err ); MSQ_ERRRTN(err);
1393 
1394  if (dims[0] < 1 || dims[1] < 1 || dims[2] < 1)
1395  {
1397  "Invalid dimension at line %d",
1398  tokens.line_number());
1399  return;
1400  }
1401 
1402  tokens.match_token( "ORIGIN", err ); MSQ_ERRRTN(err);
1403  tokens.get_doubles( 3, origin, err ); MSQ_ERRRTN(err);
1404  tokens.get_newline( err ); MSQ_ERRRTN(err);
1405 
1406  const char* const spacing_names[] = { "SPACING", "ASPECT_RATIO", 0 };
1407  tokens.match_token( spacing_names, err );MSQ_ERRRTN(err);
1408  tokens.get_doubles( 3, space, err ); MSQ_ERRRTN(err);
1409  tokens.get_newline( err ); MSQ_ERRRTN(err);
1410 
1411  myMesh->allocate_vertices( dims[0]*dims[1]*dims[2], err ); MSQ_ERRRTN(err);
1412  size_t vtx = 0;
1413  Vector3D off( origin[0], origin[1], origin[2] );
1414  for (k = 0; k < dims[2]; ++k)
1415  for (j = 0; j < dims[1]; ++j)
1416  for (i = 0; i < dims[0]; ++i)
1417  {
1418  myMesh->reset_vertex( vtx++, off + Vector3D( i*space[0], j*space[1], k*space[2] ), false, err );
1419  MSQ_ERRRTN(err);
1420  }
1421 
1422  vtk_create_structured_elems( dims, err ); MSQ_ERRRTN(err);
1423 }
1424 
1426 {
1427  long num_verts, dims[3];
1428 
1429  tokens.match_token( "DIMENSIONS", err ); MSQ_ERRRTN(err);
1430  tokens.get_long_ints( 3, dims, err ); MSQ_ERRRTN(err);
1431  tokens.get_newline( err ); MSQ_ERRRTN(err);
1432 
1433  if (dims[0] < 1 || dims[1] < 1 || dims[2] < 1)
1434  {
1436  "Invalid dimension at line %d",
1437  tokens.line_number());
1438  return;
1439  }
1440 
1441  tokens.match_token( "POINTS", err ); MSQ_ERRRTN(err);
1442  tokens.get_long_ints( 1, &num_verts, err ); MSQ_ERRRTN(err);
1443  tokens.match_token( vtk_type_names, err ); MSQ_ERRRTN(err);
1444  tokens.get_newline( err ); MSQ_ERRRTN(err);
1445 
1446  if (num_verts != (dims[0] * dims[1] * dims[2]))
1447  {
1449  "Point count not consistent with dimensions "
1450  "at line %d", tokens.line_number() );
1451  return;
1452  }
1453 
1454  myMesh->allocate_vertices( num_verts, err ); MSQ_ERRRTN(err);
1455  for (size_t vtx = 0; vtx < (size_t)num_verts; ++vtx)
1456  {
1457  Vector3D pos;
1458  tokens.get_doubles( 3, const_cast<double*>(pos.to_array()), err ); MSQ_ERRRTN(err);
1459  myMesh->reset_vertex( vtx, pos, false, err ); MSQ_ERRRTN(err);
1460  }
1461 
1462  vtk_create_structured_elems( dims, err ); MSQ_ERRRTN(err);
1463 }
1464 
1466 {
1467  int i, j, k;
1468  long dims[3];
1469  const char* labels[] = { "X_COORDINATES", "Y_COORDINATES", "Z_COORDINATES" };
1470  vector<double> coords[3];
1471 
1472  tokens.match_token( "DIMENSIONS", err ); MSQ_ERRRTN(err);
1473  tokens.get_long_ints( 3, dims, err ); MSQ_ERRRTN(err);
1474  tokens.get_newline( err ); MSQ_ERRRTN(err);
1475 
1476  if (dims[0] < 1 || dims[1] < 1 || dims[2] < 1)
1477  {
1479  "Invalid dimension at line %d",
1480  tokens.line_number());
1481  return;
1482  }
1483 
1484  for (i = 0; i < 3; i++)
1485  {
1486  long count;
1487  tokens.match_token( labels[i], err ); MSQ_ERRRTN(err);
1488  tokens.get_long_ints( 1, &count, err ); MSQ_ERRRTN(err);
1489  tokens.match_token( vtk_type_names, err ); MSQ_ERRRTN(err);
1490  tokens.get_newline( err ); MSQ_ERRRTN(err);
1491 
1492  if (count != dims[i])
1493  {
1495  "Coordinate count inconsistent with dimensions"
1496  " at line %d", tokens.line_number());
1497  return;
1498  }
1499 
1500  coords[i].resize(count);
1501  tokens.get_doubles( count, &coords[i][0], err ); MSQ_ERRRTN(err);
1502  }
1503 
1504  myMesh->allocate_vertices( dims[0]*dims[1]*dims[2], err ); MSQ_ERRRTN(err);
1505  size_t vtx = 0;
1506  for (k = 0; k < dims[2]; ++k)
1507  for (j = 0; j < dims[1]; ++j)
1508  for (i = 0; i < dims[0]; ++i)
1509  {
1510  myMesh->reset_vertex( vtx++, Vector3D( coords[0][i], coords[1][j], coords[2][k] ), false, err );
1511  MSQ_ERRRTN(err);
1512  }
1513 
1514 
1515  vtk_create_structured_elems( dims, err ); MSQ_ERRRTN(err);
1516 }
1517 
1519 {
1520  long num_verts;
1521  vector<int> connectivity;
1522  const char* const poly_data_names[] = { "VERTICES",
1523  "LINES",
1524  "POLYGONS",
1525  "TRIANGLE_STRIPS",
1526  0 };
1527 
1528  tokens.match_token( "POINTS", err ); MSQ_ERRRTN(err);
1529  tokens.get_long_ints( 1, &num_verts, err ); MSQ_ERRRTN(err);
1530  tokens.match_token( vtk_type_names, err ); MSQ_ERRRTN(err);
1531  tokens.get_newline( err ); MSQ_ERRRTN(err);
1532 
1533  if (num_verts < 1)
1534  {
1536  "Invalid point count at line %d", tokens.line_number());
1537  return;
1538  }
1539 
1540  myMesh->allocate_vertices( num_verts, err ); MSQ_ERRRTN(err);
1541  for (size_t vtx = 0; vtx < (size_t)num_verts; ++vtx)
1542  {
1543  Vector3D pos;
1544  tokens.get_doubles( 3, const_cast<double*>(pos.to_array()), err ); MSQ_ERRRTN(err);
1545  myMesh->reset_vertex( vtx, pos, false, err ); MSQ_ERRRTN(err);
1546  }
1547 
1548  int poly_type = tokens.match_token( poly_data_names, err );MSQ_ERRRTN(err);
1549  switch (poly_type)
1550  {
1551  case 3:
1552  vtk_read_polygons( tokens, err ); MSQ_ERRRTN(err);
1553  break;
1554  case 4:
1556  "Unsupported type: triangle strips at line %d",
1557  tokens.line_number() );
1558  return;
1559  case 1:
1560  case 2:
1562  "Entities of dimension < 2 at line %d",
1563  tokens.line_number() );
1564  return;
1565  }
1566 }
1567 
1569 {
1570  long size[2];
1571 
1572  tokens.get_long_ints( 2, size, err ); MSQ_ERRRTN(err);
1573  tokens.get_newline( err ); MSQ_ERRRTN(err);
1574  myMesh->allocate_elements( size[0], err ); MSQ_ERRRTN(err);
1575  msq_std::vector<size_t> conn;
1576  assert(sizeof(long) == sizeof(size_t));
1577 
1578  for (int i = 0; i < size[0]; ++i)
1579  {
1580  long count;
1581  tokens.get_long_ints( 1, &count, err ); MSQ_ERRRTN(err);
1582  conn.resize( count );
1583  tokens.get_long_ints( count, (long*)&conn[0], err ); MSQ_ERRRTN(err);
1584  myMesh->reset_element( i, conn, POLYGON, err ); MSQ_ERRRTN(err);
1585  }
1586 }
1587 
1588 
1589 
1591 {
1592  long i, num_verts, num_elems[2];
1593 
1594  tokens.match_token( "POINTS", err ); MSQ_ERRRTN(err);
1595  tokens.get_long_ints( 1, &num_verts, err ); MSQ_ERRRTN(err);
1596  tokens.match_token( vtk_type_names, err ); MSQ_ERRRTN(err);
1597  tokens.get_newline( err ); MSQ_ERRRTN(err);
1598 
1599  if (num_verts < 1)
1600  {
1602  "Invalid point count at line %d", tokens.line_number());
1603  return;
1604  }
1605 
1606  myMesh->allocate_vertices( num_verts, err ); MSQ_ERRRTN(err);
1607  for (size_t vtx = 0; vtx < (size_t)num_verts; ++vtx)
1608  {
1609  Vector3D pos;
1610  tokens.get_doubles( 3, const_cast<double*>(pos.to_array()), err ); MSQ_ERRRTN(err);
1611  myMesh->reset_vertex( vtx, pos, false, err ); MSQ_ERRRTN(err);
1612  }
1613 
1614  tokens.match_token( "CELLS", err ); MSQ_ERRRTN(err);
1615  tokens.get_long_ints( 2, num_elems, err ); MSQ_ERRRTN(err);
1616  tokens.get_newline( err ); MSQ_ERRRTN(err);
1617 
1618  myMesh->allocate_elements( num_elems[0], err ); MSQ_ERRRTN(err);
1619  msq_std::vector<size_t> conn;
1620  assert(sizeof(long) == sizeof(size_t));
1621  for (i = 0; i < num_elems[0]; ++i)
1622  {
1623  long count;
1624  tokens.get_long_ints( 1, &count, err); MSQ_ERRRTN(err);
1625  conn.resize( count );
1626  tokens.get_long_ints( count, (long*)&conn[0], err ); MSQ_ERRRTN(err);
1627  myMesh->reset_element( i, conn, MIXED, err ); MSQ_ERRRTN(err);
1628  }
1629 
1630  tokens.match_token( "CELL_TYPES", err ); MSQ_ERRRTN(err);
1631  tokens.get_long_ints( 1, &num_elems[1], err ); MSQ_ERRRTN(err);
1632  tokens.get_newline( err ); MSQ_ERRRTN(err);
1633 
1634  if (num_elems[0] != num_elems[1])
1635  {
1637  "Number of element types does not match number of elements"
1638  "at line %d", tokens.line_number() );
1639  return;
1640  }
1641 
1642  /* Map VTK types to Mesquite Types */
1643  const int pixel_swap[] = { 2, 3, -1 };
1644  const int voxel_swap[] = { 2, 3, 6, 7, -1 };
1645  const int wedge_swap[] = { 1, 2, 4, 5, -1 };
1646  const int qhex_swap[] = { 12, 16, 13, 17, 14, 18, 15, 19, -1 };
1647  const struct { const char* name; // name for type from vtk documentation
1648  EntityTopology topo; // Mesquite element topology type
1649  unsigned size; // Expected connectivity length
1650  const int* swap; // Index pairs to swap for vtk->exodus ordering
1651  } vtk_cell_types[] = {
1652  { 0, MIXED, 0, 0 },
1653  { "vertex", MIXED, 1, 0 },
1654  { "polyvertex", MIXED, 0, 0 },
1655  { "line", MIXED, 2, 0 },
1656  { "polyline", MIXED, 0, 0 },
1657  { "triangle", TRIANGLE, 3, 0 },
1658  { "triangle strip", MIXED, 0, 0 },
1659  { "polygon", POLYGON, 0, 0 },
1660  { "pixel", QUADRILATERAL, 4, pixel_swap },
1661  { "quadrilateral", QUADRILATERAL, 4, 0 },
1662  { "tetrahedron", TETRAHEDRON, 4, 0 },
1663  { "voxel", HEXAHEDRON, 8, voxel_swap },
1664  { "hexahedron", HEXAHEDRON, 8, 0 },
1665  { "wedge", PRISM, 6, wedge_swap },
1666  { "pyramid", PYRAMID, 5, 0 },
1667  { 0, MIXED, 0, 0 },
1668  { 0, MIXED, 0, 0 },
1669  { 0, MIXED, 0, 0 },
1670  { 0, MIXED, 0, 0 },
1671  { 0, MIXED, 0, 0 },
1672  { 0, MIXED, 0, 0 },
1673  { 0, MIXED, 0, 0 },
1674  { "quadratic tri", TRIANGLE, 6, 0 },
1675  { "quadratic quad", QUADRILATERAL, 8, 0 },
1676  { "quadratic tet", TETRAHEDRON, 10, 0 },
1677  { "quadratic hex", HEXAHEDRON, 20, qhex_swap }
1678  };
1679 
1680  msq_std::vector<size_t> tconn;
1681  for (i = 0; i < num_elems[0]; ++i)
1682  {
1683  long type;
1684  size_t size;
1685  tokens.get_long_ints( 1, &type, err ); MSQ_ERRRTN(err);
1686 
1687  // Check if type is a valid value
1688  if ((unsigned long)type > 25 || !vtk_cell_types[type].name)
1689  {
1691  "Invalid cell type %ld at line %d.",
1692  type, tokens.line_number() );
1693  return;
1694  }
1695  // Check if Mesquite supports the type
1696  if (vtk_cell_types[type].topo == MIXED)
1697  {
1699  "Unsupported cell type %ld (%s) at line %d.",
1700  type, vtk_cell_types[type].name, tokens.line_number() );
1701  return;
1702  }
1703 
1704  // If node-ordering is not the same as exodus...
1705  if (vtk_cell_types[type].swap)
1706  {
1707  size = myMesh->element_connectivity( i, err ).size(); MSQ_ERRRTN(err);
1708  if (vtk_cell_types[type].size != size)
1709  {
1711  "Cell type %ld (%s) for element with %d nodes at Line %d",
1712  type, vtk_cell_types[type].name, (int)size, tokens.line_number() );
1713  return;
1714  }
1715 
1716  tconn = myMesh->element_connectivity(i, err ); MSQ_ERRRTN(err);
1717  for (const int* iter = vtk_cell_types[type].swap; *iter > 0; iter += 2)
1718  msq_std::swap( tconn[iter[0]], tconn[iter[1]] );
1719 
1720  myMesh->reset_element( i, tconn, vtk_cell_types[type].topo, err );MSQ_ERRRTN(err);
1721  }
1722  // Othewise (if node ordering is the same), just set the type.
1723  else
1724  {
1725  myMesh->element_topology( i, vtk_cell_types[type].topo, err );MSQ_ERRRTN(err);
1726  }
1727  } // for(i)
1728 }
1729 
1731  MsqError& err )
1732 {
1733  //NOTE: this should be work fine for edges also if
1734  // Mesquite ever supports them. Just add the
1735  // type for dimension 1 to the switch statement.
1736 
1737  int non_zero[3] = {0,0,0}; // True if dim > 0 for x, y, z respectively
1738  long elem_dim = 0; // Element dimension (2->quad, 3->hex)
1739  long num_elems = 1; // Total number of elements
1740  long vert_per_elem; // Element connectivity length
1741  long edims[3] = { 1, 1, 1 };// Number of elements in each grid direction
1742 
1743  // Populate above data
1744  for (int d = 0; d < 3; d++)
1745  if (dims[d] > 1)
1746  {
1747  non_zero[elem_dim++] = d;
1748  edims[d] = dims[d] - 1;
1749  num_elems *= edims[d];
1750  }
1751  vert_per_elem = 1 << elem_dim;
1752 
1753  // Get element type from element dimension
1754  EntityTopology type;
1755  switch( elem_dim )
1756  {
1757  //case 1: type = EDGE; break;
1758  case 2: type = QUADRILATERAL; break;
1759  case 3: type = HEXAHEDRON; break;
1760  default:
1761  MSQ_SETERR(err)( "Cannot create structured mesh with elements "
1762  "of dimension < 2 or > 3.",
1764  return;
1765  }
1766 
1767  // Allocate storage for elements
1768  myMesh->allocate_elements( num_elems, err ); MSQ_ERRRTN(err);
1769 
1770  // Offsets of element vertices in grid relative to corner closest to origin
1771  long k = dims[0]*dims[1];
1772  const long corners[8] = { 0, 1, 1+dims[0], dims[0], k, k+1, k+1+dims[0], k+dims[0] };
1773 
1774  // Populate element list
1775  msq_std::vector<size_t> conn( vert_per_elem );
1776  size_t elem_idx = 0;
1777  for (long z = 0; z < edims[2]; ++z)
1778  for (long y = 0; y < edims[1]; ++y)
1779  for (long x = 0; x < edims[0]; ++x)
1780  {
1781  const long index = x + y*dims[0] + z*(dims[0]*dims[1]);
1782  for (long j = 0; j < vert_per_elem; ++j)
1783  conn[j] = index + corners[j];
1784  myMesh->reset_element( elem_idx++, conn, type, err ); MSQ_ERRRTN(err);
1785  }
1786 }
1787 
1789 {
1790  // This is not supported yet.
1791  // Parse the data but throw it away because
1792  // Mesquite has no internal representation for it.
1793 
1794  // Could save this in tags, but the only useful thing that
1795  // could be done with the data is to write it back out
1796  // with the modified mesh. As there's no way to save the
1797  // type of a tag in Mesquite, it cannot be written back
1798  // out correctly either.
1799  // FIXME: Don't know what to do with this data.
1800  // For now, read it and throw it out.
1801 
1802  long num_arrays;
1803  tokens.get_long_ints( 1, &num_arrays, err ); MSQ_ERRRTN(err);
1804 
1805  for (long i = 0; i < num_arrays; ++i)
1806  {
1807  /*const char* name =*/ tokens.get_string( err ); MSQ_ERRRTN(err);
1808 
1809  long dims[2];
1810  tokens.get_long_ints( 2, dims, err ); MSQ_ERRRTN(err);
1811  tokens.match_token( vtk_type_names, err ); MSQ_ERRRTN(err);
1812 
1813  long num_vals = dims[0] * dims[1];
1814 
1815  for (long j = 0; j < num_vals; j++)
1816  {
1817  double junk;
1818  tokens.get_doubles( 1, &junk, err ); MSQ_ERRRTN(err);
1819  }
1820  }
1821 }
1822 
1824  long count,
1825  TagDescription& tag,
1826  MsqError& err )
1827 {
1828  const char* const type_names[] = { "SCALARS",
1829  "COLOR_SCALARS",
1830  "VECTORS",
1831  "NORMALS",
1832  "TEXTURE_COORDINATES",
1833  "TENSORS",
1834  "FIELD",
1835  0 };
1836 
1837  int type = tokens.match_token( type_names, err );
1838  const char* name = tokens.get_string( err ); MSQ_ERRZERO(err);
1839  tag.name = name;
1840 
1841  void* data = 0;
1842  switch( type )
1843  {
1844  case 1: data = vtk_read_scalar_attrib ( tokens, count, tag, err );
1846  break;
1847  case 2: data = vtk_read_color_attrib ( tokens, count, tag, err );
1849  break;
1850  case 3: data = vtk_read_vector_attrib ( tokens, count, tag, err );
1852  break;
1853  case 4: data = vtk_read_vector_attrib ( tokens, count, tag, err );
1855  break;
1856  case 5: data = vtk_read_texture_attrib( tokens, count, tag, err );
1858  break;
1859  case 6: data = vtk_read_tensor_attrib ( tokens, count, tag, err );
1861  break;
1862  case 7: // Can't handle field data yet.
1864  "Cannot read field data (line %d).",
1865  tokens.line_number());
1866  }
1867 
1868  return data;
1869 }
1870 
1872  MsqError& err )
1873 {
1874  TagDescription tag;
1875  void* data = vtk_read_attrib_data( tokens, myMesh->num_vertices(), tag, err );
1876  MSQ_ERRRTN(err);
1877 
1878  size_t tag_handle = myTags->handle( tag.name, err );
1879  if (MSQ_CHKERR(err)) {
1880  free( data );
1881  return;
1882  }
1883  if (!tag_handle)
1884  {
1885  tag_handle = myTags->create( tag, err );
1886  if (MSQ_CHKERR(err)) {
1887  free( data );
1888  return;
1889  }
1890  }
1891  else
1892  {
1893  const TagDescription& desc = myTags->properties( tag_handle, err );
1894  if (MSQ_CHKERR(err)) {
1895  free( data );
1896  return;
1897  }
1898  if (desc != tag)
1899  {
1901  "Inconsistent types between element "
1902  "and vertex attributes of same name "
1903  "at line %d", tokens.line_number() );
1904  free( data );
1905  return;
1906  }
1907  }
1908 
1909  msq_std::vector<size_t> vertex_handles;
1910  myMesh->all_vertices( vertex_handles, err );
1911  if (MSQ_CHKERR(err)) {
1912  free( data );
1913  return;
1914  }
1915  myTags->set_vertex_data( tag_handle,
1916  vertex_handles.size(),
1917  &vertex_handles[0],
1918  data,
1919  err ); MSQ_CHKERR(err);
1920  free( data );
1921 
1922 }
1923 
1924 
1926  MsqError& err )
1927 {
1928  TagDescription tag;
1929  void* data = vtk_read_attrib_data( tokens, myMesh->num_elements(), tag, err );
1930  MSQ_ERRRTN(err);
1931 
1932  size_t tag_handle = myTags->handle( tag.name, err );
1933  if (MSQ_CHKERR(err)) {
1934  free( data );
1935  return;
1936  }
1937  if (!tag_handle)
1938  {
1939  tag_handle = myTags->create( tag, err );
1940  if (MSQ_CHKERR(err)) {
1941  free( data );
1942  return;
1943  }
1944  }
1945  else
1946  {
1947  const TagDescription& desc = myTags->properties( tag_handle, err );
1948  if (MSQ_CHKERR(err)) {
1949  free( data );
1950  return;
1951  }
1952  if (desc != tag)
1953  {
1955  "Inconsistent types between element "
1956  "and vertex attributes of same name "
1957  "at line %d", tokens.line_number() );
1958  free( data );
1959  return;
1960  }
1961  }
1962 
1963  msq_std::vector<size_t> element_handles;
1964  myMesh->all_elements( element_handles, err );
1965  if (MSQ_CHKERR(err)) {
1966  free( data );
1967  return;
1968  }
1969  myTags->set_element_data( tag_handle,
1970  element_handles.size(),
1971  &element_handles[0],
1972  data,
1973  err ); MSQ_CHKERR(err);
1974  free( data );
1975 
1976 }
1977 
1979  int type,
1980  size_t per_elem,
1981  size_t num_elem,
1982  TagDescription& tag,
1983  MsqError &err )
1984 {
1985  void* data_ptr;
1986  size_t count = per_elem * num_elem;
1987  switch ( type )
1988  {
1989  case 1:
1990  tag.size = per_elem*sizeof(bool);
1991  tag.type = BOOL;
1992  data_ptr = malloc( num_elem*tag.size );
1993  tokens.get_booleans( count, (bool*)data_ptr, err );
1994  break;
1995  case 2:
1996  case 3:
1997  case 4:
1998  case 5:
1999  case 6:
2000  case 7:
2001  case 8:
2002  case 9:
2003  tag.size = per_elem*sizeof(int);
2004  tag.type = INT;
2005  data_ptr = malloc( num_elem*tag.size );
2006  tokens.get_integers( count, (int*)data_ptr, err );
2007  break;
2008  case 10:
2009  case 11:
2010  tag.size = per_elem*sizeof(double);
2011  tag.type = DOUBLE;
2012  data_ptr = malloc( num_elem*tag.size );
2013  tokens.get_doubles( count, (double*)data_ptr, err );
2014  break;
2015  default:
2016  MSQ_SETERR(err)( "Invalid data type", MsqError::INVALID_ARG );
2017  return 0;
2018  }
2019 
2020  if (MSQ_CHKERR(err))
2021  {
2022  free( data_ptr );
2023  return 0;
2024  }
2025 
2026  return data_ptr;
2027 }
2028 
2029 
2030 
2031 
2033  long count,
2034  TagDescription& desc,
2035  MsqError& err )
2036 {
2037  int type = tokens.match_token( vtk_type_names, err ); MSQ_ERRZERO(err);
2038 
2039  long size;
2040  const char* tok = tokens.get_string( err ); MSQ_ERRZERO(err);
2041  const char* end = 0;
2042  size = strtol( tok, (char**)&end, 0 );
2043  if (*end)
2044  {
2045  size = 1;
2046  tokens.unget_token();
2047  }
2048 
2049  // VTK spec says cannot be greater than 4--do we care?
2050  if (size < 1 || size > 4)
2051  {
2053  "Scalar count out of range [1,4]"
2054  " at line %d", tokens.line_number());
2055  return 0;
2056  }
2057 
2058  tokens.match_token("LOOKUP_TABLE",err); MSQ_ERRZERO(err);
2059  tok = tokens.get_string(err); MSQ_ERRZERO(err);
2060 
2061  // If no lookup table, just read and return the data
2062  if (!strcmp( tok, "default" ))
2063  {
2064  void* ptr = vtk_read_typed_data( tokens, type, size, count, desc, err );
2065  MSQ_ERRZERO(err);
2066  return ptr;
2067  }
2068 
2069  // If we got this far, then the data has a lookup
2070  // table. First read the lookup table and convert
2071  // to integers.
2072  string name = tok;
2073  vector<long> table( size*count );
2074  if (type > 0 && type < 10) // Is an integer type
2075  {
2076  tokens.get_long_ints( table.size(), &table[0], err );
2077  MSQ_ERRZERO(err);
2078  }
2079  else // Is a real-number type
2080  {
2081  for (msq_std::vector<long>::iterator iter = table.begin(); iter != table.end(); ++iter)
2082  {
2083  double data;
2084  tokens.get_doubles( 1, &data, err );
2085  MSQ_ERRZERO(err);
2086 
2087  *iter = (long)data;
2088  if ((double)*iter != data)
2089  {
2091  "Invalid lookup index (%.0f) at line %d",
2092  data, tokens.line_number() );
2093  return 0;
2094  }
2095  }
2096  }
2097 
2098  // Now read the data - must be float RGBA color triples
2099 
2100  long table_count;
2101  tokens.match_token( "LOOKUP_TABLE", err ); MSQ_ERRZERO(err);
2102  tokens.match_token( name.c_str(), err ); MSQ_ERRZERO(err);
2103  tokens.get_long_ints( 1, &table_count, err ); MSQ_ERRZERO(err);
2104 
2105  vector<float> table_data(table_count*4);
2106  tokens.get_floats( table_data.size(), &table_data[0], err );MSQ_ERRZERO(err);
2107 
2108  // Create list from indexed data
2109 
2110  float* data = (float*)malloc( sizeof(float)*count*size*4 );
2111  float* data_iter = data;
2112  for (std::vector<long>::iterator idx = table.begin(); idx != table.end(); ++idx)
2113  {
2114  if (*idx < 0 || *idx >= table_count)
2115  {
2117  "LOOKUP_TABLE index %ld out of range.",
2118  *idx );
2119  free( data );
2120  return 0;
2121  }
2122 
2123  for (int i = 0; i < 4; i++)
2124  {
2125  *data_iter = table_data[4 * *idx + i];
2126  ++data_iter;
2127  }
2128  }
2129 
2130  desc.size = size * 4 * sizeof(float);
2131  desc.type = DOUBLE;
2132  return data;
2133 }
2134 
2136  long count,
2137  TagDescription& tag,
2138  MsqError& err )
2139 {
2140  long size;
2141  tokens.get_long_ints( 1, &size, err ); MSQ_ERRZERO(err);
2142 
2143  if (size < 1)
2144  {
2146  "Invalid size (%ld) at line %d",
2147  size, tokens.line_number() );
2148  return 0;
2149  }
2150 
2151  float* data = (float*)malloc( sizeof(float)*count*size );
2152  tokens.get_floats( count*size, data, err );
2153  if (MSQ_CHKERR(err))
2154  {
2155  free( data );
2156  return 0;
2157  }
2158 
2159  tag.size = size*sizeof(float);
2160  tag.type = DOUBLE;
2161  return data;
2162 }
2163 
2165  long count,
2166  TagDescription& tag,
2167  MsqError& err )
2168 {
2169  int type = tokens.match_token( vtk_type_names, err );
2170  MSQ_ERRZERO(err);
2171 
2172  void* result = vtk_read_typed_data( tokens, type, 3, count, tag, err );
2173  MSQ_ERRZERO(err);
2174  return result;
2175 }
2176 
2178  long count,
2179  TagDescription& tag,
2180  MsqError& err )
2181 {
2182  int type, dim;
2183  tokens.get_integers( 1, &dim, err );
2184  MSQ_ERRZERO(err);
2185  type = tokens.match_token( vtk_type_names, err );
2186  MSQ_ERRZERO(err);
2187 
2188  if (dim < 1 || dim > 3)
2189  {
2191  "Invalid dimension (%d) at line %d.",
2192  dim, tokens.line_number() );
2193  return 0;
2194  }
2195 
2196  void* result = vtk_read_typed_data( tokens, type, dim, count, tag, err );
2197  MSQ_ERRZERO(err);
2198  return result;
2199 }
2200 
2202  long count,
2203  TagDescription& tag,
2204  MsqError& err )
2205 {
2206  int type = tokens.match_token( vtk_type_names, err );
2207  MSQ_ERRZERO(err);
2208 
2209  void* result = vtk_read_typed_data( tokens, type, 9, count, tag, err );
2210  MSQ_ERRZERO(err);
2211  return result;
2212 }
2213 
2214 void MeshImpl::vtk_write_attrib_data( msq_stdio::ostream& file,
2215  const TagDescription& desc,
2216  const void* data, size_t count,
2217  MsqError& err ) const
2218 {
2219  if (desc.type == HANDLE)
2220  {
2221  MSQ_SETERR(err)("Cannot write HANDLE tag data to VTK file.",
2223  return;
2224  }
2225 
2226 
2227  TagDescription::VtkType vtk_type = desc.vtkType;
2228  unsigned vlen = desc.size / MeshImplTags::size_from_tag_type(desc.type);
2229  // guess one from data length if not set
2230  if (vtk_type == TagDescription::NONE)
2231  {
2232  switch ( vlen )
2233  {
2234  default: vtk_type = TagDescription::SCALAR; break;
2235  case 3: vtk_type = TagDescription::VECTOR; break;
2236  case 9: vtk_type = TagDescription::TENSOR; break;
2237  return;
2238  }
2239  }
2240 
2241  const char* const typenames[] = { "unsigned_char", "bit", "int", "double" };
2242 
2243  int num_per_line;
2244  switch (vtk_type)
2245  {
2246  case TagDescription::SCALAR:
2247  num_per_line = vlen;
2248  file << "SCALARS " << desc.name << " " << typenames[desc.type] << " " << vlen << "\n";
2249  break;
2250  case TagDescription::COLOR :
2251  num_per_line = vlen;
2252  file << "COLOR_SCALARS " << desc.name << " " << vlen << "\n";
2253  break;
2255  num_per_line = 3;
2256  if (vlen != 3)
2257  {
2259  "Tag \"%s\" is labeled as a VTK vector attribute but has %u values.",
2260  desc.name.c_str(), vlen);
2261  return;
2262  }
2263  file << "VECTORS " << desc.name << " " << typenames[desc.type] << "\n";
2264  break;
2266  num_per_line = 3;
2267  if (vlen != 3)
2268  {
2270  "Tag \"%s\" is labeled as a VTK normal attribute but has %u values.",
2271  desc.name.c_str(), vlen);
2272  return;
2273  }
2274  file << "NORMALS " << desc.name << " " << typenames[desc.type] << "\n";
2275  break;
2277  num_per_line = vlen;
2278  file << "TEXTURE_COORDINATES " << desc.name << " " << typenames[desc.type] << " " << vlen << "\n";
2279  break;
2281  num_per_line = 3;
2282  if (vlen != 9)
2283  {
2285  "Tag \"%s\" is labeled as a VTK tensor attribute but has %u values.",
2286  desc.name.c_str(), vlen);
2287  return;
2288  }
2289  file << "TENSORS " << desc.name << " " << typenames[desc.type] << "\n";
2290  break;
2291  default:
2292  MSQ_SETERR(err)("Unknown VTK attribute type for tag.", MsqError::INTERNAL_ERROR );
2293  return;
2294  }
2295 
2296  size_t i = 0, total = count*vlen;
2297  char* space = new char[num_per_line];
2298  memset( space, ' ', num_per_line );
2299  space[0] = '\n';
2300  const unsigned char* odata = (const unsigned char*)data;
2301  const bool* bdata = (const bool*)data;
2302  const int* idata = (const int*)data;
2303  const double* ddata = (const double*)data;
2304  switch ( desc.type )
2305  {
2306  case BYTE:
2307  while (i < total)
2308  file << (unsigned int)odata[i++] << space[i%num_per_line];
2309  break;
2310  case BOOL:
2311  while (i < total)
2312  file << (bdata[i++] ? '1' : '0') << space[i%num_per_line];
2313  break;
2314  case INT:
2315  while (i < total)
2316  file << idata[i++] << space[i%num_per_line];
2317  break;
2318  case DOUBLE:
2319  while (i < total)
2320  file << ddata[i++] << space[i%num_per_line];
2321  break;
2322  default:
2323  MSQ_SETERR(err)("Unknown tag type.", MsqError::INTERNAL_ERROR);
2324  }
2325  delete [] space;
2326 }
2327 
2328 
2329 
2330 
2331 
2332 
2333 /**************************************************************************
2334  * TAGS
2335  **************************************************************************/
2336 
2337 
2338 TagHandle MeshImpl::tag_create( const string& name,
2339  TagType type,
2340  unsigned length,
2341  const void* defval,
2342  MsqError& err )
2343 {
2344  size_t index = myTags->create( name, type, length, defval, err ); MSQ_ERRZERO(err);
2345  return (TagHandle)index;
2346 }
2347 
2349 {
2350  myTags->destroy( (size_t)handle, err ); MSQ_CHKERR(err);
2351 }
2352 
2353 TagHandle MeshImpl::tag_get( const msq_std::string& name, MsqError& err )
2354 {
2355  size_t index = myTags->handle( name, err ); MSQ_ERRZERO(err);
2356  return (TagHandle)index;
2357 }
2358 
2360  msq_std::string& name,
2361  TagType& type,
2362  unsigned& length,
2363  MsqError& err )
2364 {
2365  const TagDescription& desc
2366  = myTags->properties( (size_t)handle, err ); MSQ_ERRRTN(err);
2367 
2368  name = desc.name;
2369  type = desc.type;
2370  length = (unsigned)(desc.size / MeshImplTags::size_from_tag_type( desc.type ));
2371 }
2372 
2373 
2375  size_t num_elems,
2376  const ElementHandle* elem_array,
2377  const void* values,
2378  MsqError& err )
2379 {
2380  myTags->set_element_data( (size_t)handle,
2381  num_elems,
2382  (const size_t*)elem_array,
2383  values,
2384  err ); MSQ_CHKERR(err);
2385 }
2386 
2388  size_t num_elems,
2389  const ElementHandle* elem_array,
2390  void* values,
2391  MsqError& err )
2392 {
2393  myTags->get_element_data( (size_t)handle,
2394  num_elems,
2395  (const size_t*)elem_array,
2396  values,
2397  err ); MSQ_CHKERR(err);
2398 }
2399 
2401  size_t num_elems,
2402  const VertexHandle* elem_array,
2403  const void* values,
2404  MsqError& err )
2405 {
2406  myTags->set_vertex_data( (size_t)handle,
2407  num_elems,
2408  (const size_t*)elem_array,
2409  values,
2410  err ); MSQ_CHKERR(err);
2411 }
2412 
2414  size_t num_elems,
2415  const VertexHandle* elem_array,
2416  void* values,
2417  MsqError& err )
2418 {
2419  myTags->get_vertex_data( (size_t)handle,
2420  num_elems,
2421  (const size_t*)elem_array,
2422  values,
2423  err ); MSQ_CHKERR(err);
2424 }
2425 
2426 
2427 
2428 
2429 } // namespace Mesquite
2430 
2431 
An I/O error occured (e.g.
Iterates through a set of entities. An EntityIterator is typically obtained via Mesh::vertex_iterator...
void * vtk_read_tensor_attrib(FileTokenizer &file, long count, TagDescription &tag_out, MsqError &err)
Read tensor (3x3 matrix) data Initializes size and type fields of passed TagDescroption.
virtual void vertices_set_byte(VertexHandle *vert_array, unsigned char *byte_array, size_t array_size, MsqError &err)
void * vtk_read_attrib_data(FileTokenizer &file, long num_data_to_read, TagDescription &tag_out, MsqError &err)
Read actual data for both vtk_read_point_data and vtk_read_cell_data Initializes all fields of passed...
void swap(int &a, int &b)
Definition: buildface.cpp:88
int line_number() const
Get the line number the last token was read from.
void unget_token()
Put current token back in buffer.
unsigned char get_vertex_byte(size_t index, MsqError &err) const
Get vertex byte.
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
void all_elements(msq_std::vector< size_t > &list, MsqError &err) const
Get all elements.
size_t handle(const msq_std::string &name, MsqError &err) const
Get tag index from name.
void destroy(size_t tag_index, MsqError &err)
Remove a tag.
void * vtk_read_texture_attrib(FileTokenizer &file, long count, TagDescription &tag_out, MsqError &err)
Read texture attribute data Initializes size and type fields of passed TagDescroption.
void clear()
Clear all data.
void fix_vertex(size_t index, bool flag, MsqError &err)
Set vertex fixed flag.
void vtk_read_field(FileTokenizer &file, MsqError &err)
Read file-level field data.
const NT & d
void * vtk_read_color_attrib(FileTokenizer &file, long count, TagDescription &tag_out, MsqError &err)
Read color attribute data Initializes size and type fields of passed TagDescroption.
virtual size_t get_vertex_use_count(ElementHandle *elem_array, size_t elem_array_length, MsqError &err)
Get sum of number of vertices in each element.
j indices k indices k
Definition: Indexing.h:6
bool match_token(const char *string, MsqError &err)
Match current token to passed string.
void int int REAL REAL * y
Definition: read.cpp:74
Used to hold the error state and return it to the application.
TagType
The type of a tag.
EntityTopology
Definition: Mesquite.hpp:92
virtual TagHandle tag_create(const msq_std::string &tag_name, TagType type, unsigned length, const void *default_value, MsqError &err)
Create a tag.
virtual void tag_set_vertex_data(TagHandle handle, size_t num_elems, const VertexHandle *node_array, const void *tag_data, MsqError &err)
Set tag values on vertices.
virtual void vertices_get_byte(VertexHandle *vertex, unsigned char *byte_array, size_t array_size, MsqError &err)
void vtk_read_dataset(FileTokenizer &file, MsqError &err)
Read a data block from the file.
void vtk_read_unstructured_grid(FileTokenizer &file, MsqError &err)
Read unstructured mesh.
msq_std::string name
Tag name.
Class to store mesh representation for MeshImpl.
VtkType vtkType
Attribute type from VTK file.
const msq_std::vector< size_t > & element_connectivity(size_t index, MsqError &err) const
Get element connectivity list, including mid-nodes.
requested functionality is not (yet) implemented
EntityHandle VertexHandle
virtual void vertex_set_byte(VertexHandle vertex, unsigned char byte, MsqError &err)
Each vertex has a byte-sized flag that can be used to store flags.
size_t num_vertices() const
Get number of vertices, does not include mid-nodes.
virtual void vertex_get_attached_elements(VertexHandle vertex, ElementHandle *elem_array, size_t sizeof_elem_array, MsqError &err)
Gets the elements attached to this vertex.
virtual void vertex_get_byte(VertexHandle vertex, unsigned char *byte, MsqError &err)
Retrieve the byte value for the specified vertex or vertices.
EntityHandle ElementHandle
Vector3D is the object that effeciently stores information about about three-deminsional vectors...
void reset_element(size_t index, const msq_std::vector< size_t > &vertices, EntityTopology topology, MsqError &err)
Clear element at specified index (if any) including connectivity and adjacency data, and re-initialize with passed data.
void element_get_connectivity(ElementHandle element, VertexHandle *vert_handles, size_t sizeof_vert_handles, MsqError &err)
bool get_newline(MsqError &err)
check for newline
void * EntityHandle
Opaque EntityHandle type and tag type.
virtual VertexIterator * vertex_iterator(MsqError &err)
Returns a pointer to an iterator that iterates over the set of all vertices in this mesh...
void * vtk_read_vector_attrib(FileTokenizer &file, long count, TagDescription &tag_out, MsqError &err)
Read vector or normal attribute data Initializes size and type fields of passed TagDescroption.
int fclose(std::FILE *file)
Close a file, and check for possible errors.
Definition: CImg.h:5507
virtual void vertices_get_coordinates(const Mesh::VertexHandle vert_array[], Mesquite::MsqVertex *coordinates, size_t num_vtx, MsqError &err)
Get/set location of a vertex.
bool get_floats(size_t count, float *array, MsqError &err)
Parse a sequence of float values.
void write_vtk(const char *out_filename, Mesquite::MsqError &err)
void allocate_vertices(size_t count, MsqError &err)
Allocate space for specified number of vertices.
double length(Vector3D *const v, int n)
bool tag_has_vertex_data(size_t index, MsqError &err)
Check if any vertices have tag.
bool get_doubles(size_t count, double *array, MsqError &err)
Parse a sequence of double values.
virtual void elements_get_attached_vertices(ElementHandle *elem_handles, size_t num_elems, VertexHandle *vert_handles, size_t &sizeof_vert_handles, size_t *csr_data, size_t &sizeof_csr_data, size_t *csr_offsets, MsqError &err)
Returns the vertices that are part of the topological definition of each element in the &quot;elem_handles...
const char * get_string(MsqError &err)
get next token
virtual void tag_get_element_data(TagHandle handle, size_t num_elems, const ElementHandle *elem_array, void *tag_data, MsqError &err)
Get tag values on elements.
void clear()
Clear all data.
EntityTopology element_topology(size_t index, MsqError &err) const
Get element type.
virtual void get_all_sizes(size_t &vertex_count, size_t &element_count, size_t &vertex_use_count, MsqError &err)
get sizes for calling get_all_mesh
invalid function argument passed
const msq_std::vector< size_t > & vertex_adjacencies(size_t index, MsqError &err) const
Get vertex adjacency list.
NVec< 3, double > Vector3D
void * vtk_read_typed_data(FileTokenizer &file, int type, size_t per_elem, size_t num_elem, TagDescription &tag_out, MsqError &err)
Read a 2-D array of data of the specified type from the file Initializes size and type fields of pass...
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
virtual void tag_delete(TagHandle handle, MsqError &err)
Remove a tag and all corresponding data.
VertexIterator for MeshImpl.
void int int int REAL REAL REAL * z
Definition: write.cpp:76
void read_exodus(const char *in_filename, Mesquite::MsqError &err)
virtual void tag_set_element_data(TagHandle handle, size_t num_elems, const ElementHandle *elem_array, const void *tag_data, MsqError &err)
Set tag values on elements.
virtual size_t vertex_get_attached_element_count(VertexHandle vertex, MsqError &err)
Gets the number of elements attached to this vertex.
void get_vertex_data(size_t tag_handle, size_t num_indices, const size_t *elem_indices, void *tag_data, MsqError &err) const
Get tag data on vertices.
void vtk_create_structured_elems(const long *dims, MsqError &err)
Helper function for readers of structured mesh - create elements.
void vtk_read_polygons(FileTokenizer &file, MsqError &err)
Helper function for vtk_read_polydata - reads polygon subsection.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
bool get_long_ints(size_t count, long *array, MsqError &err)
Parse a sequence of integer values.
void set_vertex_coords(size_t index, const Vector3D &coords, MsqError &err)
Set vertex coordinates.
bool is_vertex_valid(size_t index) const
Check if passed vertex index is valid.
blockLoc i
Definition: read.cpp:79
size_t create(const msq_std::string &name, Mesh::TagType type, unsigned length, const void *defval, MsqError &err)
Create a new tag.
void int int REAL * x
Definition: read.cpp:74
int numCoords
Coordinate values per vertex.
void * vtk_read_scalar_attrib(FileTokenizer &file, long count, TagDescription &tag_out, MsqError &err)
Read scalar attribute data Initializes size and type fields of passed TagDescroption.
virtual bool vertex_is_fixed(VertexHandle vertex, MsqError &err)
Returns true or false, indicating whether the vertex is allowed to be repositioned.
const Vector3D & get_vertex_coords(size_t index, MsqError &err) const
Get vertex coordinates.
void set_vertex_byte(size_t index, unsigned char value, MsqError &err)
Set vertex byte.
Iterate over list of valid tag handles.
void vtk_read_cell_data(FileTokenizer &file, MsqError &err)
Read attribute data for elements.
File cannot be opened/created.
virtual int get_geometric_dimension(MsqError &err)
Returns whether this mesh lies in a 2D or 3D coordinate system.
bool vertex_is_fixed(size_t index, MsqError &err) const
Get vertex fixed flag.
void vtk_write_attrib_data(msq_stdio::ostream &file, const TagDescription &desc, const void *data, size_t count, MsqError &err) const
Write tag data to VTK attributes.
virtual void vertices_are_on_boundary(VertexHandle vert_array[], bool on_bnd[], size_t num_vtx, MsqError &err)
Returns true or false, indicating whether the vertex is on the boundary.
j indices j
Definition: Indexing.h:6
const char *const vtk_type_names[]
#define MSQ_PRINT(flag)
Check debug flag and print printf-style formatted output.
void vtk_read_polydata(FileTokenizer &file, MsqError &err)
Read polydata mesh.
virtual ElementIterator * element_iterator(MsqError &err)
Returns a pointer to an iterator that iterates over the set of all top-level elements in this mesh...
object is in an invalid state
void clear()
resets error object to non-active state (no error).
const double * to_array() const
virtual EntityTopology element_get_topology(ElementHandle entity_handle, MsqError &err)
Returns the topology of the given entity.
virtual void tag_properties(TagHandle handle, msq_std::string &name_out, TagType &type_out, unsigned &length_out, MsqError &err)
Get properites of tag.
void read_vtk(const char *in_filename, Mesquite::MsqError &err)
void vtk_read_point_data(FileTokenizer &file, MsqError &err)
Read attribute data for vertices.
bool tag_has_element_data(size_t index, MsqError &err)
Check if any elements have tag.
static size_t size_from_tag_type(Mesh::TagType type)
Get the size of the passed data type.
void * TagHandle
Type used to refer to a tag defintion.
void allocate_elements(size_t count, MsqError &err)
Allocate space for specified number of elements.
virtual void get_all_mesh(VertexHandle *vert_array, size_t vert_len, ElementHandle *elem_array, size_t elem_len, size_t *elem_conn_offsets, size_t offset_len, size_t *elem_conn_indices, size_t index_len, MsqError &err)
Get entities and connectivity.
ElementIterator for MeshImpl.
virtual bool is_at_end() const =0
Returns false until the iterator has been advanced PAST the last entity.
const TagDescription & properties(size_t tag_handle, MsqError &err) const
Get tag properties.
virtual void release()
Instead of deleting a Mesh when you think you are done, call release().
bool get_booleans(size_t count, bool *array, MsqError &err)
Parse a sequence of bit or boolean values.
void reset_vertex(size_t index, const Vector3D &coords, bool fixed, MsqError &err)
Set allocated but unset veretx to specified values.
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
virtual void elements_get_topologies(ElementHandle *element_handle_array, EntityTopology *element_topologies, size_t num_elements, MsqError &err)
Returns the topologies of the given entities.
void copy_mesh(size_t *vertex_handle_array, size_t *element_hanlde_array, size_t *element_conn_offsets, size_t *element_conn_indices)
Copy internal representation into CSR rep Does not include mid-nodes.
virtual void restart()=0
Moves the iterator back to the first entity in the list.
MsqVertex is the Mesquite object that stores information about the vertices in the mesh...
void set_vertex_data(size_t tag_handle, size_t num_indices, const size_t *elem_indices, const void *tag_data, MsqError &err)
Set tag data on vertices.
void set_element_data(size_t tag_handle, size_t num_indices, const size_t *elem_indices, const void *tag_data, MsqError &err)
Set tag data on elements.
void all_vertices(msq_std::vector< size_t > &list, MsqError &err) const
Get all vertices, including mid-nodes.
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
void vtk_read_structured_grid(FileTokenizer &file, MsqError &err)
Read structured grid mesh.
virtual size_t element_get_attached_vertex_count(ElementHandle elem, MsqError &err)
Gets the number of vertices in this element.
size_t size
Size of tag data (sizeof(type)*array_length)
void write_exodus(const char *out_filename, Mesquite::MsqError &err)
Writes an exodus file of the mesh.
void vtk_read_structured_points(FileTokenizer &file, MsqError &err)
Read structured point mesh.
virtual TagHandle tag_get(const msq_std::string &name, MsqError &err)
Get handle for existing tag, by name.
void vtk_read_rectilinear_grid(FileTokenizer &file, MsqError &err)
Read rectilinear grid structured mesh.
virtual void tag_get_vertex_data(TagHandle handle, size_t num_elems, const VertexHandle *node_array, void *tag_data, MsqError &err)
Get tag values on vertices.
void get_element_data(size_t tag_handle, size_t num_indices, const size_t *elem_indices, void *tag_data, MsqError &err) const
Get tag data on elements.
std::FILE * fopen(const char *const path, const char *const mode)
Open a file, and check for possible errors.
Definition: CImg.h:5494
size_t num_vertex_uses() const
Get number of vertex uses (sum of connectivity length for all elements) Does not count mid-nodes...
virtual void vertex_set_coordinates(VertexHandle vertex, const Vector3D &coordinates, MsqError &err)
virtual void release_entity_handles(EntityHandle *handle_array, size_t num_handles, MsqError &err)
Tells the mesh that the client is finished with a given entity handle.
bool get_integers(size_t count, int *array, MsqError &err)
Parse a sequence of integer values.
Error parsing input (or input file)
Mesh::TagType type
Tag data type.
Store tags and tag data for Mesquite&#39;s native mesh representation.
bool is_element_valid(size_t index) const
Check if passed element index is valid.
size_t num_elements() const
Get number of elements.
bool eof() const
Check for end-of-file condition.
Parse a file as space-separated tokens.