Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
Tqdcfr.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain 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  */
15 
16 #include "Tqdcfr.hpp"
17 #include "moab/Core.hpp"
18 #include "moab/Range.hpp"
19 #include "moab/FileOptions.hpp"
20 #include <iostream>
21 #include <string>
22 
23 #ifdef MOAB_HAVE_MPI
24 #include "moab_mpi.h"
25 #endif
26 
27 #include "moab/ReadUtilIface.hpp"
28 #include "SequenceManager.hpp"
29 #include "moab/GeomTopoTool.hpp"
30 #include "MBTagConventions.hpp"
31 #include "moab/CN.hpp"
32 #include "Internals.hpp"
34 #include "exodus_order.h"
35 
36 #include <sstream>
37 #include <cassert>
38 #include <cstring>
39 
40 namespace moab
41 {
42 
43 static bool debug = false;
44 
45 const char Tqdcfr::geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0" };
46 
47 // Will be used in a static function, so declared outside class members :(
48 // major/minor cubit version that wrote this file
49 static int major = -1, minor = -1;
50 const EntityType Tqdcfr::group_type_to_mb_type[] = { MBENTITYSET, MBENTITYSET, MBENTITYSET, // group, body, volume
51  MBENTITYSET, MBENTITYSET, MBENTITYSET, // surface, curve, vertex
53  MBTRI, MBEDGE, MBVERTEX };
54 
55 const EntityType Tqdcfr::block_type_to_mb_type[] = {
56  MBVERTEX, // sphere
57  MBEDGE, MBEDGE, MBEDGE, // bars
58  MBEDGE, MBEDGE, MBEDGE, // beams
59  MBEDGE, MBEDGE, MBEDGE, // truss
60  MBEDGE, // spring
61  MBTRI, MBTRI, MBTRI, MBTRI, // tri
62  MBTRI, MBTRI, MBTRI, MBTRI, // trishell
63  MBQUAD, MBQUAD, MBQUAD, MBQUAD, // shell
64  MBQUAD, MBQUAD, MBQUAD, MBQUAD, MBQUAD, // quad
65  MBTET, MBTET, MBTET, MBTET, MBTET, // tet
67  MBHEX, MBHEX, MBHEX, MBHEX, MBHEX, // hex
68  MBHEX, // hexshell
69  MBMAXTYPE // last
70 };
71 
72 // Mapping from mesh packet type to moab type
73 const EntityType Tqdcfr::mp_type_to_mb_type[] = { MBHEX, MBHEX, MBHEX, MBHEX, MBHEX, MBHEX, MBHEX,
78 
79 const int Tqdcfr::cub_elem_num_verts[] = { 1, // sphere
80  2, 2, 3, // bars
81  2, 2, 3, // beams
82  2, 2, 3, // truss
83  2, // spring
84  3, 3, 6, 7, // tris
85  3, 3, 6, 7, // trishells
86  4, 4, 8, 9, // shells
87  4, 4, 5, 8, 9, // quads
88  4, 4, 8, 10, 14, // tets
89  5, 5, 8, 13, 18, // pyramids
90  8, 8, 9, 20, 27, 12, // hexes (incl. hexshell at end)
91  0 };
92 
93 const int Tqdcfr::cub_elem_num_verts_len = sizeof( cub_elem_num_verts ) / sizeof( cub_elem_num_verts[0] );
94 
95 // Define node-order map from Cubit to CN. Table is indexed
96 // by EntityType and number of nodes. Entries are NULL if Cubit order
97 // is the same as CN ordering. Non-null entries contain the
98 // index into the MOAB node order for the corresponding vertex
99 // in the Cubit connectivity list. Thus for a 27-node hex:
100 // moab_conn[ cub_hex27_order[i] ] = cubit_conn[ i ];
101 const int* const* const* const cub_elem_order_map = exodus_elem_order_map;
102 
103 const char* const BLOCK_NODESET_OFFSET_TAG_NAME = "BLOCK_NODESET_OFFSET";
104 const char* const BLOCK_SIDESET_OFFSET_TAG_NAME = "BLOCK_SIDESET_OFFSET";
105 
106 #define RR \
107  if( MB_SUCCESS != result ) return result
108 
109 // acis dimensions for each entity type, to match
110 // enum {BODY, LUMP, SHELL, FACE, LOOP, COEDGE, EDGE, VERTEX, ATTRIB, UNKNOWN}
111 
112 #define IO_ASSERT( C ) INT_IO_ERROR( C, __LINE__ )
113 
114 static inline void INT_IO_ERROR( bool condition, unsigned line )
115 {
116  if( !condition )
117  {
118  char buffer[] = __FILE__ " ";
119  sprintf( buffer, "%s:%u", __FILE__, line );
120  fflush( stderr );
121  perror( buffer );
122  abort();
123  }
124 }
125 
126 void Tqdcfr::FSEEK( unsigned int offset )
127 {
128  int rval = fseek( cubFile, offset, SEEK_SET );
129  IO_ASSERT( !rval );
130 }
131 
132 void Tqdcfr::FREADI( unsigned num_ents )
133 {
134  if( uint_buf.size() < num_ents )
135  {
136  uint_buf.resize( num_ents );
137  int_buf = (int*)&uint_buf[0];
138  }
139  FREADIA( num_ents, &uint_buf[0] );
140 }
141 
142 void Tqdcfr::FREADD( unsigned num_ents )
143 {
144  dbl_buf.resize( num_ents );
145  FREADDA( num_ents, &dbl_buf[0] );
146 }
147 
148 void Tqdcfr::FREADC( unsigned num_ents )
149 {
150  char_buf.resize( num_ents );
151  FREADCA( num_ents, &char_buf[0] );
152 }
153 
154 // Used for swapping
155 static void swap8_voff( long* data )
156 {
157  unsigned char tmp, *cdat = (unsigned char*)data;
158  tmp = cdat[0];
159  cdat[0] = cdat[7], cdat[7] = tmp;
160  tmp = cdat[1];
161  cdat[1] = cdat[6], cdat[6] = tmp;
162  tmp = cdat[2];
163  cdat[2] = cdat[5], cdat[5] = tmp;
164  tmp = cdat[3];
165  cdat[3] = cdat[4], cdat[4] = tmp;
166 }
167 
168 static void swap4_uint( unsigned int* data )
169 {
170  unsigned char tmp, *cdat = (unsigned char*)data;
171  tmp = cdat[0];
172  cdat[0] = cdat[3], cdat[3] = tmp;
173  tmp = cdat[1];
174  cdat[1] = cdat[2], cdat[2] = tmp;
175 }
176 
177 /*
178 static void swap2_ushort(unsigned short *data)
179 {
180  unsigned char tmp, *cdat = (unsigned char *) data;
181  tmp = cdat[0]; cdat[0] = cdat[1], cdat[1] = tmp;
182 }
183 */
184 
185 void Tqdcfr::FREADIA( unsigned num_ents, unsigned int* array )
186 {
187  unsigned rval = fread( array, sizeof( unsigned int ), num_ents, cubFile );
188  IO_ASSERT( rval == num_ents );
189  if( swapForEndianness )
190  {
191  unsigned int* pt = array;
192  for( unsigned int i = 0; i < num_ents; i++ )
193  {
194  swap4_uint( (unsigned int*)pt );
195  pt++;
196  }
197  }
198 }
199 
200 void Tqdcfr::FREADDA( unsigned num_ents, double* array )
201 {
202  unsigned rval = fread( array, sizeof( double ), num_ents, cubFile );
203  IO_ASSERT( rval == num_ents );
204  if( swapForEndianness )
205  {
206  double* pt = array;
207  for( unsigned int i = 0; i < num_ents; i++ )
208  {
209  swap8_voff( (long*)pt );
210  pt++;
211  }
212  }
213 }
214 
215 void Tqdcfr::FREADCA( unsigned num_ents, char* array )
216 {
217  unsigned rval = fread( array, sizeof( char ), num_ents, cubFile );
218  IO_ASSERT( rval == num_ents );
219 }
220 
221 void Tqdcfr::CONVERT_TO_INTS( unsigned int num_ents )
222 {
223  for( unsigned int i = 0; i < num_ents; i++ )
224  int_buf[i] = uint_buf[i];
225 }
226 
228 {
229  return new Tqdcfr( iface );
230 }
231 
233  : cubFile( NULL ), globalIdTag( 0 ), cubIdTag( 0 ), geomTag( 0 ), uniqueIdTag( 0 ), blockTag( 0 ), nsTag( 0 ),
234  ssTag( 0 ), attribVectorTag( 0 ), entityNameTag( 0 ), categoryTag( 0 ), hasMidNodesTag( 0 ),
235  swapForEndianness( false ), int_buf( NULL ), mFileSet( 0 ), printedSeqWarning( false ),
236  printedElemWarning( false ), acisDumpFile( NULL )
237 {
238  assert( NULL != impl );
239  mdbImpl = impl;
241  assert( NULL != readUtilIface );
242 
243  currVHandleOffset = -1;
244  for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
245  currElementIdOffset[this_type] = -1;
246 
247  ErrorCode rval;
248  rval = mdbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, blockTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
249  rval = mdbImpl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, nsTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
250  rval = mdbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ssTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
251 
252  if( 0 == entityNameTag )
253  {
255  MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
256  }
257 
258  cubMOABVertexMap = NULL;
259 }
260 
262 {
264 
265  if( NULL != cubMOABVertexMap ) delete cubMOABVertexMap;
266  if( attribVectorTag )
267  {
268  // get all sets, and release the string vectors
269  Range allSets; // although only geom sets should have these attributes
270  // can't error in a destructor
271  ErrorCode rval = mdbImpl->get_entities_by_type( 0, MBENTITYSET, allSets );
272  if( rval != MB_SUCCESS ) std::cerr << "WARNING: Could not get_entities_by_type" << std::endl;
273  for( Range::iterator sit = allSets.begin(); sit != allSets.end(); ++sit )
274  {
275  EntityHandle gset = *sit;
276  std::vector< std::string >* dum_vec;
277  // can't error in a destructor
278  rval = mdbImpl->tag_get_data( attribVectorTag, &gset, 1, &dum_vec );
279  if( rval != MB_SUCCESS ) std::cerr << "WARNING: Could not tag_get_data" << std::endl;
280  if( NULL != dum_vec ) delete dum_vec; //
281  }
283  attribVectorTag = NULL;
284  }
285 }
286 
287 ErrorCode Tqdcfr::read_tag_values( const char* /* file_name */,
288  const char* /* tag_name */,
289  const FileOptions& /* opts */,
290  std::vector< int >& /* tag_values_out */,
291  const SubsetList* /* subset_list */ )
292 {
293  return MB_NOT_IMPLEMENTED;
294 }
295 
296 ErrorCode Tqdcfr::load_file( const char* file_name,
297  const EntityHandle*,
298  const FileOptions& opts,
299  const ReaderIface::SubsetList* subset_list,
300  const Tag* file_id_tag )
301 {
302  ErrorCode result;
303 
304  int tmpval;
305  if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) )
306  {
307  if( 0 < tmpval ) debug = true;
308  }
309 
310  if( subset_list )
311  {
312  MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for CUB files" );
313  }
314 
315  // Open file
316  cubFile = fopen( file_name, "rb" );
317  if( NULL == cubFile )
318  {
319  MB_SET_ERR( MB_FAILURE, "File not found" );
320  }
321 
322  // Verify magic string
323  FREADC( 4 );
324  if( !( char_buf[0] == 'C' && char_buf[1] == 'U' && char_buf[2] == 'B' && char_buf[3] == 'E' ) )
325  {
326  fclose( cubFile );
327  MB_SET_ERR( MB_FAILURE, "This doesn't appear to be a .cub file" );
328  }
329 
330  // Get "before" entities
331  result = mdbImpl->get_entities_by_handle( 0, beforeEnts );MB_CHK_SET_ERR( result, "Couldn't get \"before\" entities" );
332 
333  // ***********************
334  // Read model header type information...
335  // ***********************
336  if( debug ) std::cout << "Reading file header." << std::endl;
337  result = read_file_header();RR;
338 
339  if( debug ) std::cout << "Reading model entries." << std::endl;
340  result = read_model_entries();RR;
341 
342  // Read model metadata
343  if( debug ) std::cout << "Reading model metadata." << std::endl;
345 
346  double data_version;
347  int md_index = modelMetaData.get_md_entry( 2, "DataVersion" );
348  if( -1 == md_index )
349  data_version = 1.0;
350  else
351  data_version = modelMetaData.metadataEntries[md_index].mdDblValue;
352 
353  // Get the major/minor cubit version that wrote this file
354  // int major = -1, minor = -1;
355  md_index = modelMetaData.get_md_entry( 2, "CubitVersion" );
356  if( md_index >= 0 && !modelMetaData.metadataEntries[md_index].mdStringValue.empty() )
357  sscanf( modelMetaData.metadataEntries[md_index].mdStringValue.c_str(), "%d.%d", &major, &minor );
358 
359  // ***********************
360  // Read mesh...
361  // ***********************
362  int index = find_model( mesh );
363  if( -1 == index ) return MB_FAILURE;
364  ModelEntry* mesh_model = &modelEntries[index];
365 
366  // First the header & metadata info
367  if( debug ) std::cout << "Reading mesh model header and metadata." << std::endl;
368  result = mesh_model->read_header_info( this, data_version );
369  if( MB_SUCCESS != result ) return result;
370  result = mesh_model->read_metadata_info( this );
371  if( MB_SUCCESS != result ) return result;
372 
373  // Now read in mesh for each geometry entity; read in order of increasing dimension
374  // so we have all the mesh we need
375  for( int dim = 0; dim < 4; dim++ )
376  {
377  for( unsigned int gindex = 0; gindex < mesh_model->feModelHeader.geomArray.numEntities; gindex++ )
378  {
379  Tqdcfr::GeomHeader* geom_header = &mesh_model->feGeomH[gindex];
380 
381  if( geom_header->maxDim != dim ) continue;
382 
383  // Read nodes
384  if( debug ) std::cout << "Reading geom index " << gindex << " mesh: nodes... ";
385  result = read_nodes( gindex, mesh_model, geom_header );
386  if( MB_SUCCESS != result ) return result;
387 
388  // Read elements
389  if( debug ) std::cout << "elements... ";
390  result = read_elements( mesh_model, geom_header );
391  if( MB_SUCCESS != result ) return result;
392  if( debug ) std::cout << std::endl;
393  }
394  }
395 
396  // ***********************
397  // Read acis records...
398  // ***********************
399  std::string sat_file_name;
400  if( MB_SUCCESS != opts.get_str_option( "SAT_FILE", sat_file_name ) ) sat_file_name.clear();
401  result = read_acis_records( sat_file_name.empty() ? NULL : sat_file_name.c_str() );RR;
402 
403  // ***********************
404  // Read groups...
405  // ***********************
406  if( debug ) std::cout << "Reading groups... ";
407  for( unsigned int grindex = 0; grindex < mesh_model->feModelHeader.groupArray.numEntities; grindex++ )
408  {
409  GroupHeader* group_header = &mesh_model->feGroupH[grindex];
410  result = read_group( grindex, mesh_model, group_header );
411  if( MB_SUCCESS != result ) return result;
412  }
413  if( debug ) std::cout << mesh_model->feModelHeader.groupArray.numEntities << " read successfully." << std::endl;
414 
415  // ***********************
416  // Read blocks...
417  // ***********************
418  if( debug ) std::cout << "Reading blocks... ";
419  Range ho_entities;
420  for( unsigned int blindex = 0; blindex < mesh_model->feModelHeader.blockArray.numEntities; blindex++ )
421  {
422  BlockHeader* block_header = &mesh_model->feBlockH[blindex];
423  result = read_block( blindex, data_version, mesh_model, block_header );
424  if( MB_SUCCESS != result ) return result;
425  }
426 
427  if( debug ) std::cout << mesh_model->feModelHeader.blockArray.numEntities << " read successfully." << std::endl;
428 
429  // ***********************
430  // Read nodesets...
431  // ***********************
432  if( debug ) std::cout << "Reading nodesets... ";
433  for( unsigned int nsindex = 0; nsindex < mesh_model->feModelHeader.nodesetArray.numEntities; nsindex++ )
434  {
435  NodesetHeader* nodeset_header = &mesh_model->feNodeSetH[nsindex];
436  result = read_nodeset( nsindex, mesh_model, nodeset_header );
437  if( MB_SUCCESS != result ) return result;
438  }
439  if( debug ) std::cout << mesh_model->feModelHeader.nodesetArray.numEntities << " read successfully." << std::endl;
440 
441  // ***********************
442  // Read sidesets...
443  // ***********************
444  if( debug ) std::cout << "Reading sidesets...";
445  for( unsigned int ssindex = 0; ssindex < mesh_model->feModelHeader.sidesetArray.numEntities; ssindex++ )
446  {
447  SidesetHeader* sideset_header = &mesh_model->feSideSetH[ssindex];
448  result = read_sideset( ssindex, data_version, mesh_model, sideset_header );
449  if( MB_SUCCESS != result ) return result;
450  }
451  if( debug ) std::cout << mesh_model->feModelHeader.sidesetArray.numEntities << " read successfully." << std::endl;
452 
453  if( debug )
454  {
455  std::cout << "Read the following mesh:" << std::endl;
456  mdbImpl->list_entities( 0, 0 );
457  }
458 
459  // Convert blocks to nodesets/sidesets if tag is set
460  result = convert_nodesets_sidesets();
461  if( MB_SUCCESS != result ) return result;
462 
463  Range after_ents;
464  result = mdbImpl->get_entities_by_handle( 0, after_ents );
465  if( MB_SUCCESS != result ) return result;
466 
467  after_ents = subtract( after_ents, beforeEnts );
468 
469  if( file_id_tag ) readUtilIface->assign_ids( *file_id_tag, after_ents );
470 
471  if( MB_SUCCESS != opts.get_null_option( "SKIP_TOPOLOGY" ) )
472  {
473  // **************************
474  // Restore geometric topology
475  // **************************
476  GeomTopoTool gtt( mdbImpl, true, 0, true, false );
477  result = gtt.restore_topology_from_adjacency();
478  if( MB_SUCCESS != result )
479  {
480  std::cout << "Failed to restore topology " << std::endl;
481  }
482  }
483 
484  // done with the cubit file
485  fclose( cubFile );
486  return result;
487 }
488 
490 {
491  // Look first for the nodeset and sideset offset flags; if they're not
492  // set, we don't need to convert
493  const EntityHandle msh = 0;
494  unsigned int nodeset_offset, sideset_offset;
495  Tag tmp_tag;
497  if( MB_SUCCESS != result )
498  nodeset_offset = 0;
499  else
500  {
501  result = mdbImpl->tag_get_data( tmp_tag, &msh, 1, &nodeset_offset );
502  if( MB_SUCCESS != result ) return result;
503  }
504 
506  if( MB_SUCCESS != result )
507  sideset_offset = 0;
508  else
509  {
510  result = mdbImpl->tag_get_data( tmp_tag, &msh, 1, &sideset_offset );
511  if( MB_SUCCESS != result ) return result;
512  }
513 
514  if( 0 == nodeset_offset && 0 == sideset_offset ) return MB_SUCCESS;
515 
516  // Look for all blocks
517  Range blocks;
518  result = mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &blockTag, NULL, 1, blocks );
519  if( MB_SUCCESS != result || blocks.empty() ) return result;
520 
521  // Get the id tag for them
522  std::vector< int > block_ids( blocks.size() );
523  result = mdbImpl->tag_get_data( globalIdTag, blocks, &block_ids[0] );
524  if( MB_SUCCESS != result ) return result;
525 
526  unsigned int i = 0;
527  Range::iterator rit = blocks.begin();
528  Range new_nodesets, new_sidesets;
529  std::vector< int > new_nodeset_ids, new_sideset_ids;
530  for( ; rit != blocks.end(); i++, ++rit )
531  {
532  if( 0 != nodeset_offset && block_ids[i] >= (int)nodeset_offset &&
533  ( nodeset_offset > sideset_offset || block_ids[i] < (int)sideset_offset ) )
534  {
535  // This is a nodeset
536  new_nodesets.insert( *rit );
537  new_nodeset_ids.push_back( block_ids[i] );
538  }
539  else if( 0 != sideset_offset && block_ids[i] >= (int)sideset_offset &&
540  ( sideset_offset > nodeset_offset || block_ids[i] < (int)nodeset_offset ) )
541  {
542  // This is a sideset
543  new_sidesets.insert( *rit );
544  new_sideset_ids.push_back( block_ids[i] );
545  }
546  }
547 
548  // OK, have the new nodesets and sidesets; now remove the block tags, and
549  // add nodeset and sideset tags
550  ErrorCode tmp_result = MB_SUCCESS;
551  if( 0 != nodeset_offset )
552  {
553  if( 0 == nsTag )
554  {
555  int default_val = 0;
557  MB_TAG_SPARSE | MB_TAG_CREAT, &default_val );
558  if( MB_SUCCESS != tmp_result ) result = tmp_result;
559  }
560  if( MB_SUCCESS == tmp_result ) tmp_result = mdbImpl->tag_set_data( nsTag, new_nodesets, &new_nodeset_ids[0] );
561  if( MB_SUCCESS != tmp_result ) result = tmp_result;
562  tmp_result = mdbImpl->tag_delete_data( blockTag, new_nodesets );
563  if( MB_SUCCESS != tmp_result ) result = tmp_result;
564  }
565  if( 0 != sideset_offset )
566  {
567  if( 0 == ssTag )
568  {
569  int default_val = 0;
571  MB_TAG_SPARSE | MB_TAG_CREAT, &default_val );
572  if( MB_SUCCESS != tmp_result ) result = tmp_result;
573  }
574  if( MB_SUCCESS == tmp_result ) tmp_result = mdbImpl->tag_set_data( ssTag, new_sidesets, &new_sideset_ids[0] );
575  if( MB_SUCCESS != tmp_result ) result = tmp_result;
576  tmp_result = mdbImpl->tag_delete_data( blockTag, new_sidesets );
577  if( MB_SUCCESS != tmp_result ) result = tmp_result;
578  }
579 
580  return result;
581 }
582 
583 ErrorCode Tqdcfr::read_nodeset( const unsigned int nsindex, Tqdcfr::ModelEntry* model, Tqdcfr::NodesetHeader* nodeseth )
584 {
585  if( nodeseth->memTypeCt == 0 ) return MB_SUCCESS;
586 
587  // Position file
588  FSEEK( model->modelOffset + nodeseth->memOffset );
589 
590  // Read ids for each entity type
591  unsigned int this_type, num_ents; //, uid;
592  std::vector< char > bc_data;
593  unsigned int num_read = 0;
594  std::vector< EntityHandle > ns_entities, excl_entities;
595  for( unsigned int i = 0; i < nodeseth->memTypeCt; i++ )
596  {
597  // Get how many and what type
598  FREADI( 2 );
599  num_read += 2 * sizeof( int );
600  this_type = uint_buf[0];
601  num_ents = uint_buf[1];
602 
603  // Now get the ids
604  FREADI( num_ents );
605  num_read += sizeof( int );
606  CONVERT_TO_INTS( num_ents );
607 
608  ErrorCode result = get_entities( this_type + 2, &int_buf[0], num_ents, ns_entities, excl_entities );
609  if( MB_SUCCESS != result ) return result;
610  }
611  // Check for more data
612  if( num_read < nodeseth->nsLength )
613  {
614  FREADC( 2 ); // num_read += 2;
615  if( char_buf[0] == 'i' && char_buf[1] == 'd' )
616  {
617  FREADI( 1 ); // num_read += sizeof(int);
618  // uid = int_buf[0];
619  }
620  else
621  {
622  if( char_buf[0] == 'b' && char_buf[1] == 'c' )
623  {
624  FREADI( 1 ); // num_read += sizeof(int);
625  int num_bcs = uint_buf[0];
626  bc_data.resize( num_bcs );
627  FREADCA( num_bcs, &bc_data[0] ); // num_read += num_bcs;
628  }
629  }
630  }
631 
632  if( debug )
633  {
634  nodeseth->print();
635  if( !bc_data.empty() )
636  {
637  std::cout << "bc_data = ";
638  std::vector< char >::iterator vit = bc_data.begin();
639  for( ; vit != bc_data.end(); ++vit )
640  {
641  std::cout << std::hex << (int)( (unsigned char)*vit ) << " ";
642  }
643  std::cout << ": ";
644  vit = bc_data.begin();
645  for( ; vit != bc_data.end(); ++vit )
646  {
647  std::cout << *vit;
648  }
649  std::cout << std::endl;
650  }
651  }
652 
653  // And put entities into this nodeset's set
654  ErrorCode result = put_into_set( nodeseth->setHandle, ns_entities, excl_entities );
655  if( MB_SUCCESS != result ) return result;
656 
657  result = get_names( model->nodesetMD, nsindex, nodeseth->setHandle );
658  if( MB_SUCCESS != result ) return result;
659 
660  const int def_bc_data_len = 0;
661  std::string tag_name = std::string( DIRICHLET_SET_TAG_NAME ) + "__BC_DATA";
662  Tag nbc_data;
663  result = mdbImpl->tag_get_handle( tag_name.c_str(), def_bc_data_len, MB_TYPE_OPAQUE, nbc_data,
665  if( MB_SUCCESS != result ) return result;
666  void const* tag_data[] = { ( bc_data.empty() ) ? NULL : &( bc_data[0] ) };
667  int tag_size = bc_data.size();
668  result = mdbImpl->tag_set_by_ptr( nbc_data, &nodeseth->setHandle, 1, tag_data, &tag_size );
669  if( MB_SUCCESS != result ) return result;
670 
671  return result;
672 }
673 
674 ErrorCode Tqdcfr::read_sideset( const unsigned int ssindex,
675  const double data_version,
676  Tqdcfr::ModelEntry* model,
677  Tqdcfr::SidesetHeader* sideseth )
678 {
679  if( sideseth->memCt == 0 ) return MB_SUCCESS;
680 
681  ErrorCode result;
682 
683  // Position file
684  FSEEK( model->modelOffset + sideseth->memOffset );
685 
686  // Read ids for each entity type
687  unsigned int this_type, num_ents, sense_size;
688 
689  std::vector< char > bc_data;
690  unsigned int num_read = 0; //, uid;
691  std::vector< EntityHandle > ss_entities, excl_entities;
692  if( data_version <= 1.0 )
693  {
694  for( unsigned int i = 0; i < sideseth->memTypeCt; i++ )
695  {
696  // Get how many and what type
697  FREADI( 3 );
698  num_read += 3 * sizeof( int );
699  this_type = uint_buf[0];
700  num_ents = uint_buf[1];
701  sense_size = uint_buf[2];
702 
703  // Now get the ids
704  FREADI( num_ents );
705  num_read += sizeof( int );
706  CONVERT_TO_INTS( num_ents );
707 
708  result = get_entities( this_type + 2, &int_buf[0], num_ents, ss_entities, excl_entities );
709  if( MB_SUCCESS != result ) return result;
710 
711  if( sense_size == 1 )
712  {
713  // Byte-size sense flags; make sure read ends aligned...
714  unsigned int read_length = ( num_ents / 8 ) * 8;
715  if( read_length < num_ents ) read_length += 8;
716  FREADC( read_length );
717  num_read += read_length;
718  }
719  else if( sense_size == 2 )
720  {
721  // Int-size sense flags
722  FREADI( num_ents );
723  num_read += sizeof( int );
724  }
725 
726  // Now do something with them...
727  process_sideset_10( this_type, num_ents, sense_size, ss_entities, sideseth );
728  }
729  }
730  else
731  {
732  for( unsigned int i = 0; i < sideseth->memTypeCt; i++ )
733  {
734  // Get how many and what type
735  FREADI( 1 );
736  num_read += sizeof( int );
737  num_ents = uint_buf[0];
738 
739  // Get the types, and ids
740  std::vector< unsigned int > mem_types( num_ents ), mem_ids( num_ents );
741  FREADIA( num_ents, &mem_types[0] );
742  num_read += num_ents * sizeof( int );
743  FREADI( num_ents );
744  num_read += sizeof( int );
745 
746  result = get_entities( &mem_types[0], &int_buf[0], num_ents, false, ss_entities );
747  if( MB_SUCCESS != result ) return result;
748 
749  // Byte-size sense flags; make sure read ends aligned...
750  unsigned int read_length = ( num_ents / 8 ) * 8;
751  if( read_length < num_ents ) read_length += 8;
752  FREADC( read_length );
753  num_read += read_length;
754 
755  // wrt entities
756  FREADI( 1 );
757  num_read += sizeof( int );
758  int num_wrts = uint_buf[0];
759  FREADI( num_wrts );
760  num_read += num_wrts * sizeof( int );
761 
762  result = process_sideset_11( ss_entities, num_wrts, sideseth );
763  if( MB_SUCCESS != result ) return result;
764  }
765  }
766 
767  // Now set the dist factors
768  if( sideseth->numDF > 0 )
769  {
770  // Have to read dist factors
771  FREADD( sideseth->numDF );
772  num_read += sideseth->numDF * sizeof( double );
773  Tag distFactorTag;
774  result = mdbImpl->tag_get_handle( "distFactor", 0, MB_TYPE_DOUBLE, distFactorTag,
776  if( MB_SUCCESS != result ) return result;
777  const void* dist_data = &dbl_buf[0];
778  const int dist_size = sideseth->numDF;
779  result = mdbImpl->tag_set_by_ptr( distFactorTag, &sideseth->setHandle, 1, &dist_data, &dist_size );
780  if( MB_SUCCESS != result ) return result;
781  }
782 
783  // Check for more data
784  if( data_version > 1.0 && num_read < sideseth->ssLength )
785  {
786  FREADC( 2 ); // num_read += 2;
787  if( char_buf[0] == 'i' && char_buf[1] == 'd' )
788  {
789  FREADI( 1 ); // num_read += sizeof(int);
790  // uid = int_buf[0];
791  }
792  else
793  {
794  // Check for bc_data
795  if( char_buf[0] == 'b' && char_buf[1] == 'c' )
796  {
797  FREADI( 1 ); // num_read += sizeof(int);
798  int num_bcs = uint_buf[0];
799  bc_data.resize( num_bcs );
800  FREADCA( num_bcs, &bc_data[0] ); // num_read += num_bcs;
801  }
802  }
803  }
804 
805  if( debug )
806  {
807  sideseth->print();
808  if( !bc_data.empty() )
809  {
810  std::cout << "bc_data = ";
811  std::vector< char >::iterator vit = bc_data.begin();
812  for( ; vit != bc_data.end(); ++vit )
813  {
814  std::cout << std::hex << (int)( (unsigned char)*vit ) << " ";
815  }
816  std::cout << ": ";
817  vit = bc_data.begin();
818  for( ; vit != bc_data.end(); ++vit )
819  {
820  std::cout << *vit;
821  }
822  std::cout << std::endl;
823  }
824  }
825 
826  result = get_names( model->sidesetMD, ssindex, sideseth->setHandle );
827  if( MB_SUCCESS != result ) return result;
828 
829  const int def_bc_data_len = 0;
830  std::string tag_name = std::string( NEUMANN_SET_TAG_NAME ) + "__BC_DATA";
831  Tag nbc_data;
832  result = mdbImpl->tag_get_handle( tag_name.c_str(), def_bc_data_len, MB_TYPE_OPAQUE, nbc_data,
834  if( MB_SUCCESS != result ) return result;
835  void const* tag_data[] = { ( bc_data.empty() ) ? NULL : &( bc_data[0] ) };
836  int tag_size = bc_data.size();
837  result = mdbImpl->tag_set_by_ptr( nbc_data, &sideseth->setHandle, 1, tag_data, &tag_size );
838  if( MB_SUCCESS != result ) return result;
839 
840  return MB_SUCCESS;
841 }
842 
844  const int num_ents,
845  const int sense_size,
846  std::vector< EntityHandle >& ss_entities,
847  Tqdcfr::SidesetHeader* sideseth )
848 {
849  std::vector< EntityHandle > forward, reverse;
850  if( this_type == 3 // Surface
851  && sense_size == 1 // Byte size
852  )
853  {
854  // Interpret sense flags w/o reference to anything
855  for( int i = 0; i < num_ents; i++ )
856  {
857  if( (int)char_buf[i] == 0 )
858  forward.push_back( ss_entities[i] );
859  else if( (int)char_buf[i] == 1 )
860  reverse.push_back( ss_entities[i] );
861  else if( (int)char_buf[i] == -1 )
862  { // -1 means "unknown", which means both
863  forward.push_back( ss_entities[i] );
864  reverse.push_back( ss_entities[i] );
865  }
866  }
867  }
868  else if( this_type == 4 // Curve
869  && sense_size == 2 // int32 size
870  )
871  {
872  for( int i = 0; i < num_ents; i++ )
873  {
874  if( uint_buf[i] == 0 )
875  forward.push_back( ss_entities[i] );
876  else if( uint_buf[i] == 1 )
877  reverse.push_back( ss_entities[i] );
878  else if( *( (int*)&uint_buf[i] ) == -1 )
879  { // -1 means "unknown", which means both
880  forward.push_back( ss_entities[i] );
881  reverse.push_back( ss_entities[i] );
882  }
883  }
884  }
885 
886  // Now actually put them in the set
887  ErrorCode result = MB_SUCCESS;
888  if( !forward.empty() )
889  {
890  ErrorCode tmp_result = mdbImpl->add_entities( sideseth->setHandle, &forward[0], forward.size() );
891  if( tmp_result != MB_SUCCESS ) result = tmp_result;
892  }
893  if( !reverse.empty() )
894  {
895  // Need to make a new set, add a reverse sense tag, then add to the sideset
896  EntityHandle reverse_set;
897  ErrorCode tmp_result = create_set( reverse_set );
898  if( MB_SUCCESS != tmp_result ) result = tmp_result;
899  tmp_result = mdbImpl->add_entities( reverse_set, &reverse[0], reverse.size() );
900  if( tmp_result != MB_SUCCESS ) result = tmp_result;
901  int def_val = 1;
902  Tag sense_tag;
903  tmp_result = mdbImpl->tag_get_handle( "NEUSET_SENSE", 1, MB_TYPE_INTEGER, sense_tag,
904  MB_TAG_SPARSE | MB_TAG_CREAT, &def_val );
905  if( tmp_result != MB_SUCCESS ) result = tmp_result;
906  def_val = -1;
907  tmp_result = mdbImpl->tag_set_data( sense_tag, &reverse_set, 1, &def_val );
908  if( tmp_result != MB_SUCCESS ) result = tmp_result;
909  tmp_result = mdbImpl->add_entities( sideseth->setHandle, &reverse_set, 1 );
910  if( tmp_result != MB_SUCCESS ) result = tmp_result;
911  }
912 
913  return result;
914 }
915 
916 ErrorCode Tqdcfr::process_sideset_11( std::vector< EntityHandle >& ss_entities,
917  int num_wrts,
918  Tqdcfr::SidesetHeader* sideseth )
919 {
920  std::vector< EntityHandle > forward, reverse;
921 
922  unsigned int num_ents = ss_entities.size();
923  unsigned int* wrt_it = &uint_buf[0];
924 
925  for( unsigned int i = 0; i < num_ents; i++ )
926  {
927  unsigned int num_wrt = 0;
928  if( 0 != num_wrts ) num_wrt = *wrt_it++;
929  for( unsigned int j = 0; j < num_wrt; j++ )
930  wrt_it += 2;
931  // Assume here that if it's in the list twice, we get both senses
932  if( num_wrt > 1 )
933  {
934  forward.push_back( ss_entities[i] );
935  reverse.push_back( ss_entities[i] );
936  }
937  else
938  {
939  // Else interpret the sense flag
940  if( (int)char_buf[i] == 0 )
941  forward.push_back( ss_entities[i] );
942  else if( (int)char_buf[i] == 1 )
943  reverse.push_back( ss_entities[i] );
944  else if( (int)char_buf[i] == -1 )
945  { // -1 means "unknown", which means both
946  forward.push_back( ss_entities[i] );
947  reverse.push_back( ss_entities[i] );
948  }
949  }
950  }
951 
952  // Now actually put them in the set
953  ErrorCode result = MB_SUCCESS;
954  if( !forward.empty() )
955  {
956  ErrorCode tmp_result = mdbImpl->add_entities( sideseth->setHandle, &forward[0], forward.size() );
957  if( tmp_result != MB_SUCCESS ) result = tmp_result;
958  }
959  if( !reverse.empty() )
960  {
961  // Need to make a new set, add a reverse sense tag, then add to the sideset
962  EntityHandle reverse_set;
963  ErrorCode tmp_result = create_set( reverse_set );
964  if( MB_SUCCESS != tmp_result ) result = tmp_result;
965  tmp_result = mdbImpl->add_entities( reverse_set, &reverse[0], reverse.size() );
966  if( tmp_result != MB_SUCCESS ) result = tmp_result;
967  int def_val = 1;
968  Tag sense_tag;
969  tmp_result = mdbImpl->tag_get_handle( "NEUSET_SENSE", 1, MB_TYPE_INTEGER, sense_tag,
970  MB_TAG_SPARSE | MB_TAG_CREAT, &def_val );
971  if( tmp_result != MB_SUCCESS && tmp_result != MB_ALREADY_ALLOCATED ) result = tmp_result;
972  def_val = -1;
973  tmp_result = mdbImpl->tag_set_data( sense_tag, &reverse_set, 1, &def_val );
974  if( tmp_result != MB_SUCCESS ) result = tmp_result;
975  tmp_result = mdbImpl->add_entities( sideseth->setHandle, &reverse_set, 1 );
976  if( tmp_result != MB_SUCCESS ) result = tmp_result;
977  }
978 
979  return result;
980 }
981 
982 ErrorCode Tqdcfr::read_block( const unsigned int blindex,
983  const double /*data_version*/,
984  Tqdcfr::ModelEntry* model,
985  Tqdcfr::BlockHeader* blockh )
986 {
987  if( blockh->memCt == 0 ) return MB_SUCCESS;
988 
989  // Position file
990  FSEEK( model->modelOffset + blockh->memOffset );
991 
992  // Read ids for each entity type
993  unsigned int num_read = 0;
994  int this_type, num_ents; //, uid;
995  std::vector< EntityHandle > block_entities, excl_entities;
996  for( unsigned int i = 0; i < blockh->memTypeCt; i++ )
997  {
998  // Get how many and what type
999  FREADI( 2 );
1000  num_read += 2 * sizeof( int );
1001  this_type = uint_buf[0];
1002  num_ents = uint_buf[1];
1003 
1004  // Now get the ids
1005  FREADI( num_ents );
1006  num_read += num_ents * sizeof( int );
1007  CONVERT_TO_INTS( num_ents );
1008 
1009  ErrorCode result = get_entities( this_type + 2, &int_buf[0], num_ents, block_entities, excl_entities );
1010  if( MB_SUCCESS != result ) return result;
1011  }
1012 
1013  // And put entities into this block's set
1014  ErrorCode result = put_into_set( blockh->setHandle, block_entities, excl_entities );
1015  if( MB_SUCCESS != result ) return result;
1016 
1017  // Read attribs if there are any
1018  Tag block_attribs;
1019  {
1020  int def_block_attributes_length = 0;
1021  result = mdbImpl->tag_get_handle( BLOCK_ATTRIBUTES, def_block_attributes_length, MB_TYPE_DOUBLE, block_attribs,
1023  if( MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result ) return result;
1024  }
1025 
1026  if( blockh->attribOrder > 0 )
1027  {
1028  FREADD( blockh->attribOrder );
1029  num_read += sizeof( double );
1030  void const* tag_data[] = { &dbl_buf[0] };
1031  int tag_sizes[] = { static_cast< int >( blockh->attribOrder ) };
1032  result = mdbImpl->tag_set_by_ptr( block_attribs, &( blockh->setHandle ), 1, tag_data, tag_sizes );
1033  if( MB_SUCCESS != result ) return result;
1034  }
1035 
1036  // Check for more data
1037  if( num_read < blockh->blockLength )
1038  {
1039  FREADC( 2 ); // num_read += 2;
1040  if( char_buf[0] == 'i' && char_buf[1] == 'd' )
1041  {
1042  FREADI( 1 ); // num_read += sizeof(int);
1043  // uid = int_buf[0];
1044  }
1045  }
1046 
1047  result = get_names( model->blockMD, blindex, blockh->setHandle );
1048  if( MB_SUCCESS != result ) return result;
1049 
1050  // Put additional higher-order nodes into element connectivity list.
1051  // Cubit saves full connectivity list only for NodeHex and NodeTet
1052  // elements. Other element types will only have the corners and
1053  // the mid-element node if there is one. Need to reconstruct additional
1054  // connectivity entries from mid-nodes of adjacent lower-order entities.
1055  int node_per_elem = cub_elem_num_verts[blockh->blockElemType];
1056  if( blockh->blockEntityType == MBMAXTYPE ) return MB_SUCCESS;
1057  if( ( 14 == major && 2 < minor ) || 15 <= major )
1058  {
1059  if( 55 == blockh->blockElemType || CN::VerticesPerEntity( blockh->blockEntityType ) == node_per_elem )
1060  return MB_SUCCESS;
1061  }
1062  else
1063  {
1064  if( 52 == blockh->blockElemType || CN::VerticesPerEntity( blockh->blockEntityType ) == node_per_elem )
1065  return MB_SUCCESS;
1066  }
1067 
1068  // Can't use Interface::convert_entities because block could contain
1069  // both entity sets and entities. convert_entities will fail if block
1070  // contains an entity set, but we still need to call it on any elements
1071  // directly in the block (rather than a geometry subset). So bypass
1072  // Interface and call HOFactory directly with an Range of entities.
1073  Range ho_entities, entities;
1074  mdbImpl->get_entities_by_type( blockh->setHandle, blockh->blockEntityType, entities, true );
1075  if( CN::Dimension( blockh->blockEntityType ) > 2 )
1076  {
1077  result = mdbImpl->get_adjacencies( entities, 2, false, ho_entities, Interface::UNION );
1078  if( MB_SUCCESS != result ) return result;
1079  }
1080  if( CN::Dimension( blockh->blockEntityType ) > 1 )
1081  {
1082  result = mdbImpl->get_adjacencies( entities, 1, false, ho_entities, Interface::UNION );
1083  if( MB_SUCCESS != result ) return result;
1084  }
1085  entities.merge( ho_entities );
1086 
1087  Core* mbcore = dynamic_cast< Core* >( mdbImpl );
1088  assert( mbcore != NULL );
1089  HigherOrderFactory ho_fact( mbcore, 0 );
1090  return ho_fact.convert( entities, !!blockh->hasMidNodes[1], !!blockh->hasMidNodes[2], !!blockh->hasMidNodes[3] );
1091 }
1092 
1093 ErrorCode Tqdcfr::get_names( MetaDataContainer& md, unsigned int set_index, EntityHandle seth )
1094 {
1095  ErrorCode result = MB_SUCCESS;
1096 
1097  // Now get block names, if any
1098  int md_index = md.get_md_entry( set_index, "Name" );
1099  if( -1 == md_index ) return result;
1100  MetaDataContainer::MetaDataEntry* md_entry = &( md.metadataEntries[md_index] );
1101  // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
1102  char name_tag_data[NAME_TAG_SIZE];
1103  memset( name_tag_data, 0, NAME_TAG_SIZE ); // Make sure any extra bytes zeroed
1104  strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
1105  result = mdbImpl->tag_set_data( entityNameTag, &seth, 1, name_tag_data );
1106  if( MB_SUCCESS != result ) return result;
1107 
1108  // Look for extra names
1109  md_index = md.get_md_entry( set_index, "NumExtraNames" );
1110  if( -1 == md_index ) return result;
1111  int num_names = md.metadataEntries[md_index].mdIntValue;
1112  for( int i = 0; i < num_names; i++ )
1113  {
1114  std::ostringstream extra_name_label( "ExtraName" );
1115  extra_name_label << i;
1116  std::ostringstream moab_extra_name( "EXTRA_" );
1117  moab_extra_name << NAME_TAG_NAME << i;
1118  md_index = md.get_md_entry( set_index, extra_name_label.str().c_str() );
1119  if( -1 != md_index )
1120  {
1121  md_entry = &( md.metadataEntries[md_index] );
1122  Tag extra_name_tag;
1123  ErrorCode rval;
1124  rval = mdbImpl->tag_get_handle( moab_extra_name.str().c_str(), NAME_TAG_SIZE, MB_TYPE_OPAQUE,
1125  extra_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
1126  memset( name_tag_data, 0, NAME_TAG_SIZE ); // Make sure any extra bytes zeroed
1127  strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
1128  result = mdbImpl->tag_set_data( extra_name_tag, &seth, 1, name_tag_data );
1129  }
1130  }
1131 
1132  return result;
1133 }
1134 
1135 ErrorCode Tqdcfr::read_group( const unsigned int group_index, Tqdcfr::ModelEntry* model, Tqdcfr::GroupHeader* grouph )
1136 {
1137  // Position file
1138  FSEEK( model->modelOffset + grouph->memOffset );
1139  char name_tag_data[NAME_TAG_SIZE];
1140 
1141  // Read ids for each entity type
1142  int this_type, num_ents;
1143  std::vector< EntityHandle > grp_entities, excl_entities;
1144  for( unsigned int i = 0; i < grouph->memTypeCt; i++ )
1145  {
1146  // Get how many and what type
1147  FREADI( 2 );
1148  this_type = uint_buf[0];
1149  num_ents = uint_buf[1];
1150 
1151  // Now get the ids
1152  FREADI( num_ents );
1153  CONVERT_TO_INTS( num_ents );
1154 
1155  // Get the entities in this group
1156  ErrorCode result = get_entities( this_type, &int_buf[0], num_ents, grp_entities, excl_entities );
1157  if( MB_SUCCESS != result ) return result;
1158  }
1159 
1160  // Now add the entities
1161  ErrorCode result = put_into_set( grouph->setHandle, grp_entities, excl_entities );
1162  if( MB_SUCCESS != result ) return result;
1163 
1164  // Now get group names, if any
1165  int md_index = model->groupMD.get_md_entry( grouph->grpID, "NAME" );
1166  if( -1 != md_index )
1167  {
1168  MetaDataContainer::MetaDataEntry* md_entry = &( model->groupMD.metadataEntries[md_index] );
1169  if( 0 == entityNameTag )
1170  {
1171  memset( name_tag_data, 0, NAME_TAG_SIZE );
1173  MB_TAG_SPARSE | MB_TAG_CREAT, name_tag_data );
1174  if( MB_SUCCESS != result ) return result;
1175  }
1176  // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
1177  memset( name_tag_data, 0, NAME_TAG_SIZE ); // Make sure any extra bytes zeroed
1178  strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
1179  result = mdbImpl->tag_set_data( entityNameTag, &grouph->setHandle, 1, name_tag_data );
1180  if( MB_SUCCESS != result ) return result;
1181 
1182  // Look for extra names
1183  md_index = model->groupMD.get_md_entry( group_index, "NumExtraNames" );
1184  if( -1 != md_index )
1185  {
1186  int num_names = model->groupMD.metadataEntries[md_index].mdIntValue;
1187  for( int i = 0; i < num_names; i++ )
1188  {
1189  std::ostringstream extra_name_label( "ExtraName" );
1190  extra_name_label << i;
1191  std::ostringstream moab_extra_name( "EXTRA_" );
1192  moab_extra_name << NAME_TAG_NAME << i;
1193  md_index = model->groupMD.get_md_entry( group_index, extra_name_label.str().c_str() );
1194  if( -1 != md_index )
1195  {
1196  md_entry = &( model->groupMD.metadataEntries[md_index] );
1197  Tag extra_name_tag;
1198  memset( name_tag_data, 0, NAME_TAG_SIZE );
1199  result = mdbImpl->tag_get_handle( moab_extra_name.str().c_str(), NAME_TAG_SIZE, MB_TYPE_OPAQUE,
1200  extra_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT, name_tag_data );
1201  if( MB_SUCCESS != result ) return result;
1202  // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
1203  memset( name_tag_data, 0, NAME_TAG_SIZE ); // Make sure any extra bytes zeroed
1204  strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
1205  result = mdbImpl->tag_set_data( extra_name_tag, &grouph->setHandle, 1, name_tag_data );
1206  }
1207  }
1208  }
1209  }
1210 
1211  return result;
1212 }
1213 
1215  std::vector< EntityHandle >& entities,
1216  std::vector< EntityHandle >& excl_entities )
1217 {
1218  // And put entities into this block's set
1219  ErrorCode result = mdbImpl->add_entities( set_handle, &entities[0], entities.size() );
1220  if( MB_SUCCESS != result ) return result;
1221 
1222  // Check for excluded entities, and add them to a vector hung off the block if there
1223  Tag excl_tag;
1224  if( !excl_entities.empty() )
1225  {
1226  result = mdbImpl->tag_get_handle( "Exclude_Entities", sizeof( std::vector< EntityHandle >* ), MB_TYPE_OPAQUE,
1227  excl_tag, MB_TAG_SPARSE | MB_TAG_CREAT );
1228  if( MB_SUCCESS != result ) return result;
1229  std::vector< EntityHandle >* new_vector = new std::vector< EntityHandle >;
1230  new_vector->swap( excl_entities );
1231  result = mdbImpl->tag_set_data( excl_tag, &set_handle, 1, &new_vector );
1232  if( MB_SUCCESS != result )
1233  {
1234  delete new_vector;
1235  return MB_FAILURE;
1236  }
1237  }
1238 
1239  return MB_SUCCESS;
1240 }
1241 
1242 ErrorCode Tqdcfr::get_entities( const unsigned int* mem_types,
1243  int* id_buf,
1244  const unsigned int id_buf_size,
1245  const bool is_group,
1246  std::vector< EntityHandle >& entities )
1247 {
1248  ErrorCode tmp_result, result = MB_SUCCESS;
1249 
1250  for( unsigned int i = 0; i < id_buf_size; i++ )
1251  {
1252  if( is_group )
1253  tmp_result = get_entities( mem_types[i], id_buf + i, 1, entities, entities );
1254  else
1255  // For blocks/nodesets/sidesets, use CSOEntityType, which is 2 greater than
1256  // group entity types
1257  tmp_result = get_entities( mem_types[i] + 2, id_buf + i, 1, entities, entities );
1258  if( MB_SUCCESS != tmp_result ) result = tmp_result;
1259  }
1260 
1261  return result;
1262 }
1263 
1264 ErrorCode Tqdcfr::get_entities( const unsigned int this_type,
1265  int* id_buf,
1266  const unsigned int id_buf_size,
1267  std::vector< EntityHandle >& entities,
1268  std::vector< EntityHandle >& excl_entities )
1269 {
1270  ErrorCode result = MB_FAILURE;
1271 
1272  if( this_type <= VERTEX )
1273  result = get_ref_entities( this_type, id_buf, id_buf_size, entities );
1274  else if( this_type >= HEX && this_type <= NODE )
1275  result = get_mesh_entities( this_type, id_buf, id_buf_size, entities, excl_entities );
1276 
1277  return result;
1278 }
1279 
1280 ErrorCode Tqdcfr::get_ref_entities( const unsigned int this_type,
1281  int* id_buf,
1282  const unsigned int id_buf_size,
1283  std::vector< EntityHandle >& entities )
1284 {
1285  for( unsigned int i = 0; i < id_buf_size; i++ )
1286  entities.push_back( ( gidSetMap[5 - this_type] )[id_buf[i]] );
1287 
1288  return MB_SUCCESS;
1289 }
1290 
1291 ErrorCode Tqdcfr::get_mesh_entities( const unsigned int this_type,
1292  int* id_buf,
1293  const unsigned int id_buf_size,
1294  std::vector< EntityHandle >& entities,
1295  std::vector< EntityHandle >& excl_entities )
1296 {
1297  ErrorCode result = MB_SUCCESS;
1298  std::vector< EntityHandle >* ent_list = NULL;
1299  EntityType this_ent_type = MBVERTEX;
1300  const unsigned int arr_len = sizeof( group_type_to_mb_type ) / sizeof( group_type_to_mb_type[0] );
1301  if( this_type > 1000 )
1302  {
1303  if( this_type - 1000 < arr_len )
1304  {
1305  this_ent_type = group_type_to_mb_type[this_type - 1000];
1306  ent_list = &excl_entities;
1307  }
1308  }
1309  else
1310  {
1311  if( this_type < arr_len )
1312  {
1313  this_ent_type = group_type_to_mb_type[this_type];
1314  ent_list = &entities;
1315  }
1316  }
1317  if( NULL == ent_list )
1318  {
1319  MB_SET_ERR( MB_FAILURE, "Entities list is NULL" );
1320  }
1321 
1322  // Get entities with this type, and get their cub id tags
1323  if( MBVERTEX == this_ent_type )
1324  {
1325  // Use either vertex offset or cubMOABVertexMap
1326  if( NULL == cubMOABVertexMap )
1327  {
1328  for( unsigned int i = 0; i < id_buf_size; i++ )
1329  ent_list->push_back( (EntityHandle)( id_buf[i] + currVHandleOffset ) );
1330  }
1331  else
1332  {
1333  for( unsigned int i = 0; i < id_buf_size; i++ )
1334  {
1335  assert( 0 != ( *cubMOABVertexMap )[id_buf[i]] );
1336  ent_list->push_back( ( *cubMOABVertexMap )[id_buf[i]] );
1337  }
1338  }
1339  }
1340  else
1341  {
1342  Range tmp_ents;
1343  result = mdbImpl->get_entities_by_type( 0, this_ent_type, tmp_ents );
1344  if( MB_SUCCESS != result ) return result;
1345  if( tmp_ents.empty() && 0 != id_buf_size ) return MB_FAILURE;
1346 
1347  std::vector< int > cub_ids( tmp_ents.size() );
1348  result = mdbImpl->tag_get_data( globalIdTag, tmp_ents, &cub_ids[0] );
1349  if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) return result;
1350 
1351  // Now go through id list, finding each entity by id
1352  for( unsigned int i = 0; i < id_buf_size; i++ )
1353  {
1354  std::vector< int >::iterator vit = std::find( cub_ids.begin(), cub_ids.end(), id_buf[i] );
1355  if( vit != cub_ids.end() )
1356  {
1357  EntityHandle this_ent = tmp_ents[vit - cub_ids.begin()];
1358  if( mdbImpl->type_from_handle( this_ent ) != MBMAXTYPE ) ent_list->push_back( this_ent );
1359  }
1360  else
1361  {
1362  std::cout << "Warning: didn't find " << CN::EntityTypeName( this_ent_type ) << " " << id_buf[i]
1363  << std::endl;
1364  }
1365  }
1366  }
1367 
1368  return result;
1369 }
1370 
1371 ErrorCode Tqdcfr::read_nodes( const unsigned int gindex, Tqdcfr::ModelEntry* model, Tqdcfr::GeomHeader* entity )
1372 {
1373  if( entity->nodeCt == 0 )
1374  {
1375  if( debug ) std::cout << "(no nodes) ";
1376  return MB_SUCCESS;
1377  }
1378 
1379  // Get the ids & coords in separate calls to minimize memory usage
1380  // Position the file
1381  FSEEK( model->modelOffset + entity->nodeOffset );
1382  // Get node ids in uint_buf
1383  FREADI( entity->nodeCt );
1384 
1385  if( debug )
1386  {
1387  std::cout << "(";
1388  for( unsigned int i = 0; i < entity->nodeCt; i++ )
1389  {
1390  std::cout << uint_buf[i];
1391  if( i != entity->nodeCt - 1 ) std::cout << ", ";
1392  }
1393  std::cout << ")...";
1394  }
1395 
1396  // Get a space for reading nodal data directly into MB, and read that data
1397  EntityHandle vhandle = 0;
1398  std::vector< double* > arrays;
1399  readUtilIface->get_node_coords( 3, entity->nodeCt, uint_buf[0], vhandle, arrays,
1401 
1402  // Get node x's in arrays[0]
1403  FREADDA( entity->nodeCt, arrays[0] );
1404  // Get node y's in arrays[1]
1405  FREADDA( entity->nodeCt, arrays[1] );
1406  // Get node z's in arrays[2]
1407  FREADDA( entity->nodeCt, arrays[2] );
1408 
1409  // Add these nodes into the entity's set
1410  Range dum_range( vhandle, vhandle + entity->nodeCt - 1 );
1411  ErrorCode result = mdbImpl->add_entities( entity->setHandle, dum_range );
1412  if( MB_SUCCESS != result ) return result;
1413 
1414  // Check for id contiguity; know that cid's will never be > 32bit, so
1415  // ids can be unsigned int
1416  unsigned int max_cid, min_cid;
1417  int contig;
1418  check_contiguous( entity->nodeCt, contig, min_cid, max_cid );
1419 
1420  // Compute the offset we get in this batch and compare to any previous one
1421  long vhandle_offset = vhandle - min_cid;
1422  if( -1 == currVHandleOffset ) currVHandleOffset = vhandle_offset;
1423 
1424  // In 2 situations we'll need to add/modify a cubit_id -> vhandle map:
1425  // case A: no map yet, and either this offset different from
1426  // previous or not contiguous
1427  if( !cubMOABVertexMap && ( currVHandleOffset != vhandle_offset || !contig ) )
1428  {
1429  // Get all vertices, removing ones in this batch
1430  Range vrange, tmp_range( dum_range );
1431  result = mdbImpl->get_entities_by_type( 0, MBVERTEX, vrange );RR;
1432  if( !beforeEnts.empty() ) tmp_range.merge( beforeEnts.subset_by_type( MBVERTEX ) );
1433  vrange = subtract( vrange, tmp_range );
1434  // Compute the max cid; map is indexed by cid, so size is max_cid + 1
1435 #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
1436 #define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
1437  // Sanity check that max vhandle is larger than offset
1438  long new_max = *vrange.rbegin() - currVHandleOffset;
1439  assert( new_max >= 0 && ( (long)*vrange.begin() ) - currVHandleOffset >= 0 );
1440  max_cid = MAX( max_cid, ( (unsigned int)new_max ) );
1441  cubMOABVertexMap = new std::vector< EntityHandle >( max_cid + 1 );
1442  // Initialize to zero then put previous vertices into the map
1443  std::fill( cubMOABVertexMap->begin(), cubMOABVertexMap->end(), 0 );
1444  Range::iterator rit;
1445  for( rit = vrange.begin(); rit != vrange.end(); ++rit )
1446  {
1447  assert( ( (long)*rit ) - currVHandleOffset >= 0 && ( (long)*rit ) - currVHandleOffset <= max_cid );
1448  ( *cubMOABVertexMap )[*rit - currVHandleOffset] = *rit;
1449  }
1450  }
1451  // case B: there is a map and we need to resize it
1452  else if( cubMOABVertexMap && max_cid + 1 > cubMOABVertexMap->size() )
1453  {
1454  unsigned int old_size = cubMOABVertexMap->size();
1455  cubMOABVertexMap->resize( max_cid + 1 );
1456  std::fill( &( *cubMOABVertexMap )[old_size], &( *cubMOABVertexMap )[0] + cubMOABVertexMap->size(), 0 );
1457  }
1458 
1459  // OK, we have a map or don't need one
1460  if( NULL == cubMOABVertexMap )
1461  {
1462  // If we're not forward-contiguous (i.e. we're reverse or
1463  // out-of-order contiguous), re-order coordinates for handles
1464  // so that they are
1465  if( -1 == contig || -2 == contig )
1466  {
1467  // In case the arrays are large, do each coord separately
1468  std::vector< double > tmp_coords( entity->nodeCt );
1469  for( unsigned int j = 0; j < 3; j++ )
1470  {
1471  // Permute the coords into new order
1472  for( unsigned int i = 0; i < entity->nodeCt; i++ )
1473  {
1474  assert( uint_buf[i] >= min_cid && max_cid - uint_buf[i] < entity->nodeCt );
1475  tmp_coords[uint_buf[i] - min_cid] = arrays[j][i];
1476  }
1477  // Copy the permuted to storage
1478  std::copy( &tmp_coords[0], &tmp_coords[0] + entity->nodeCt, arrays[j] );
1479  }
1480  // Now re-order the ids; either way just go off min, max cid
1481  for( unsigned int i = 0; i < entity->nodeCt; i++ )
1482  uint_buf[i] = min_cid + i;
1483  }
1484  else if( !contig )
1485  // Shouldn't get here, since in non-contiguous case map should be there
1486  assert( false );
1487  }
1488  else
1489  {
1490  // Put new vertices into the map
1491  // Now set the new values
1492  unsigned int* vit = &uint_buf[0];
1493  Range::iterator rit = dum_range.begin();
1494  for( ; rit != dum_range.end(); vit++, ++rit )
1495  {
1496  assert( *vit < cubMOABVertexMap->size() );
1497  ( *cubMOABVertexMap )[*vit] = *rit;
1498  }
1499  }
1500 
1501  // No longer need to use uint_buf; convert in-place to ints, so we
1502  // can assign gid tag
1503  CONVERT_TO_INTS( entity->nodeCt );
1504  result = mdbImpl->tag_set_data( globalIdTag, dum_range, &int_buf[0] );
1505  if( MB_SUCCESS != result ) return result;
1506 
1507  // Set the dimension to at least zero (entity has at least nodes) on the geom tag
1508  int max_dim = 0;
1509  result = mdbImpl->tag_set_data( geomTag, &( entity->setHandle ), 1, &max_dim );
1510  if( MB_SUCCESS != result ) return result;
1511  // Set the category tag just in case there're only vertices in this set
1512  result = mdbImpl->tag_set_data( categoryTag, &entity->setHandle, 1, &geom_categories[0] );
1513  if( MB_SUCCESS != result ) return result;
1514 
1515  // Get fixed node data and assign
1516  int md_index = model->nodeMD.get_md_entry( gindex, "FixedNodes" );
1517  if( -1 == md_index ) return MB_SUCCESS;
1518  MetaDataContainer::MetaDataEntry* md_entry = &( model->nodeMD.metadataEntries[md_index] );
1519 
1520  std::vector< int > fixed_flags( entity->nodeCt );
1521  std::fill( fixed_flags.begin(), fixed_flags.end(), 0 );
1522  if( md_entry->mdDataType != 3 ) return MB_FAILURE;
1523 
1524  for( std::vector< unsigned int >::iterator vit = md_entry->mdIntArrayValue.begin();
1525  vit != md_entry->mdIntArrayValue.end(); ++vit )
1526  {
1527 #ifndef NDEBUG
1528  EntityHandle fixed_v =
1529  ( cubMOABVertexMap ? ( *cubMOABVertexMap )[*vit] : (EntityHandle)currVHandleOffset + *vit );
1530  assert( fixed_v >= *dum_range.begin() && fixed_v <= *dum_range.rbegin() );
1531 #endif
1532  fixed_flags[*vit - *dum_range.begin()] = 1;
1533  }
1534 
1535  Tag fixedFlagTag;
1536  int dum_val = 0;
1537  result = mdbImpl->tag_get_handle( "NodeFixed", 1, MB_TYPE_INTEGER, fixedFlagTag, MB_TAG_SPARSE | MB_TAG_CREAT,
1538  &dum_val );
1539  if( MB_SUCCESS != result ) return result;
1540  result = mdbImpl->tag_set_data( fixedFlagTag, dum_range, &fixed_flags[0] );
1541 
1542  return result;
1543 }
1544 
1546 {
1547  if( entity->elemTypeCt == 0 ) return MB_SUCCESS;
1548  const int in_order_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1549  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 };
1550 
1551  // Get data in separate calls to minimize memory usage
1552  // Position the file
1553  FSEEK( model->modelOffset + entity->elemOffset );
1554 
1555  int int_type, nodes_per_elem, num_elem;
1556  int max_dim = -1;
1557  ErrorCode result;
1558  for( unsigned int i = 0; i < entity->elemTypeCt; i++ )
1559  {
1560  // For this elem type, get the type, nodes per elem, num elems
1561  FREADI( 3 );
1562  int_type = uint_buf[0];
1563  nodes_per_elem = uint_buf[1];
1564  num_elem = uint_buf[2];
1565 
1566  // Get MB element type from cub file's
1567  EntityType elem_type = mp_type_to_mb_type[int_type];
1568  max_dim = ( max_dim < CN::Dimension( elem_type ) ? CN::Dimension( elem_type ) : max_dim );
1569 
1570  if( debug ) std::cout << "type " << CN::EntityTypeName( elem_type ) << ":";
1571 
1572  const int* node_order = cub_elem_order_map[elem_type][nodes_per_elem];
1573  if( !node_order ) node_order = in_order_map;
1574 
1575  // Get element ids
1576  FREADI( num_elem );
1577 
1578  // Check to see if ids are contiguous...
1579  int contig;
1580  unsigned int max_id, min_id;
1581  check_contiguous( num_elem, contig, min_id, max_id );
1582  if( 0 == contig && !printedElemWarning )
1583  {
1584  std::cout << "Element ids are not contiguous!" << std::endl;
1585  printedElemWarning = true;
1586  }
1587 
1588  // Get a space for reading connectivity data directly into MB
1589  EntityHandle *conn, start_handle;
1590 
1591  result = readUtilIface->get_element_connect( num_elem, nodes_per_elem, elem_type, int_buf[0], start_handle,
1593  if( MB_SUCCESS != result ) return result;
1594 
1595  Range dum_range( start_handle, start_handle + num_elem - 1 );
1596 
1597  long elem_offset;
1598  elem_offset = ( 1 == contig ? start_handle - int_buf[0] : int_buf[num_elem - 1] );
1599  if( -1 == currElementIdOffset[elem_type] ) currElementIdOffset[elem_type] = elem_offset;
1600 
1601  // Set the gids on elements
1602  CONVERT_TO_INTS( num_elem );
1603  result = mdbImpl->tag_set_data( globalIdTag, dum_range, &int_buf[0] );
1604  if( MB_SUCCESS != result ) return result;
1605 
1606  // Get the connectivity array
1607  unsigned int total_conn = num_elem * nodes_per_elem;
1608  if( major >= 14 ) FREADI( num_elem ); // We need to skip num_elem in advance, it looks like
1609  FREADI( total_conn );
1610 
1611  // Post-process connectivity into handles
1612  EntityHandle new_handle;
1613  int j = 0;
1614  for( int e = 0; e < num_elem; ++e )
1615  {
1616  for( int k = 0; k < nodes_per_elem; ++k, ++j )
1617  {
1618  if( debug )
1619  {
1620  if( 0 == j ) std::cout << "Conn=";
1621  std::cout << ", " << uint_buf[j];
1622  }
1623  if( NULL == cubMOABVertexMap )
1624  new_handle = (EntityHandle)currVHandleOffset + uint_buf[j];
1625  else
1626  {
1627  assert( uint_buf[j] < cubMOABVertexMap->size() && 0 != ( *cubMOABVertexMap )[uint_buf[j]] );
1628  new_handle = ( *cubMOABVertexMap )[uint_buf[j]];
1629  }
1630 #ifndef NDEBUG
1631  EntityHandle dum_handle;
1632  assert( MB_SUCCESS ==
1633  mdbImpl->handle_from_id( MBVERTEX, mdbImpl->id_from_handle( new_handle ), dum_handle ) );
1634 #endif
1635  conn[e * nodes_per_elem + node_order[k]] = new_handle;
1636  }
1637  }
1638 
1639  // Add these elements into the entity's set
1640  result = mdbImpl->add_entities( entity->setHandle, dum_range );
1641  if( MB_SUCCESS != result ) return result;
1642 
1643  // Notify MOAB of the new elements
1644  result = readUtilIface->update_adjacencies( start_handle, num_elem, nodes_per_elem, conn );
1645  if( MB_SUCCESS != result ) return result;
1646  }
1647 
1648  // Set the dimension on the geom tag
1649  result = mdbImpl->tag_set_data( geomTag, &entity->setHandle, 1, &max_dim );
1650  if( MB_SUCCESS != result ) return result;
1651  if( max_dim != -1 )
1652  {
1653  result = mdbImpl->tag_set_data( categoryTag, &entity->setHandle, 1, &geom_categories[max_dim] );
1654  if( MB_SUCCESS != result ) return result;
1655  }
1656 
1657  return MB_SUCCESS;
1658 }
1659 
1660 void Tqdcfr::check_contiguous( const unsigned int num_ents, int& contig, unsigned int& min_id, unsigned int& max_id )
1661 {
1662  unsigned int *id_it, curr_id, i;
1663 
1664  // Check in forward-contiguous direction
1665  id_it = &uint_buf[0];
1666  curr_id = *id_it++ + 1;
1667  contig = 1;
1668  min_id = uint_buf[0];
1669  max_id = uint_buf[0];
1670  for( i = 1; i < num_ents; id_it++, i++, curr_id++ )
1671  {
1672  if( *id_it != curr_id )
1673  {
1674  contig = 0;
1675  }
1676  min_id = MIN( min_id, uint_buf[i] );
1677  max_id = MAX( max_id, uint_buf[i] );
1678  }
1679 
1680  // If we got here and we're at the end of the loop, it's forward-contiguous
1681  if( 1 == contig ) return;
1682 
1683  // Check in reverse-contiguous direction
1684  contig = -1;
1685  id_it = &uint_buf[0];
1686  curr_id = *id_it++ - 1;
1687  for( i = 1; i < num_ents; id_it++, i++, curr_id-- )
1688  {
1689  if( *id_it != curr_id )
1690  {
1691  contig = 0;
1692  break;
1693  }
1694  }
1695 
1696  // If we got here and we're at the end of the loop, it's reverse-contiguous
1697  if( -1 == contig ) return;
1698 
1699  // One final check, for contiguous but out of order
1700  if( max_id - min_id + 1 == num_ents ) contig = -2;
1701 
1702  // Else it's not contiguous at all
1703  contig = 0;
1704 }
1705 
1706 void Tqdcfr::FEModelHeader::init( const unsigned int offset, Tqdcfr* instance )
1707 {
1708  instance->FSEEK( offset );
1709  instance->FREADI( 4 );
1710  feEndian = instance->uint_buf[0];
1711  feSchema = instance->uint_buf[1];
1712  feCompressFlag = instance->uint_buf[2];
1713  feLength = instance->uint_buf[3];
1714  instance->FREADI( 3 );
1715  geomArray.init( instance->uint_buf );
1716  instance->FREADI( 2 );
1717  nodeArray.metaDataOffset = instance->uint_buf[0];
1718  elementArray.metaDataOffset = instance->uint_buf[1];
1719  instance->FREADI( 3 );
1720  groupArray.init( instance->uint_buf );
1721  instance->FREADI( 3 );
1722  blockArray.init( instance->uint_buf );
1723  instance->FREADI( 3 );
1724  nodesetArray.init( instance->uint_buf );
1725  instance->FREADI( 3 );
1726  sidesetArray.init( instance->uint_buf );
1727  instance->FREADI( 1 );
1728 }
1729 
1731 {
1732  // Read file header
1733  FSEEK( 4 );
1734  // Read the first int from the file
1735  // If it is 0, it is littleEndian
1736  unsigned rval = fread( &fileTOC.fileEndian, sizeof( unsigned int ), 1, cubFile );
1737  IO_ASSERT( rval == 1 );
1738 #ifdef WORDS_BIGENDIAN
1739  if( fileTOC.fileEndian == 0 ) swapForEndianness = true;
1740 #else
1741  if( fileTOC.fileEndian != 0 ) swapForEndianness = true;
1742 #endif
1743  if( debug ) std::cout << " swapping ? " << swapForEndianness << "\n";
1744  FREADI( 5 );
1745  // fileTOC.fileEndian = uint_buf[0];
1747  fileTOC.numModels = uint_buf[1];
1751  if( debug ) fileTOC.print();
1752 
1753  return MB_SUCCESS;
1754 }
1755 
1757 {
1758  // Read model entries
1760  FREADI( fileTOC.numModels * 6 );
1761  modelEntries.resize( fileTOC.numModels );
1762  if( modelEntries.empty() ) return MB_FAILURE;
1763  std::vector< unsigned int >::iterator int_it = uint_buf.begin();
1764  for( unsigned int i = 0; i < fileTOC.numModels; i++ )
1765  {
1766  modelEntries[i].modelHandle = *int_it++;
1767  modelEntries[i].modelOffset = *int_it++;
1768  modelEntries[i].modelLength = *int_it++;
1769  modelEntries[i].modelType = *int_it++;
1770  modelEntries[i].modelOwner = *int_it++;
1771  modelEntries[i].modelPad = *int_it++;
1772  if( int_it == uint_buf.end() && i != fileTOC.numModels - 1 ) return MB_FAILURE;
1773  if( debug ) modelEntries[i].print();
1774  }
1775 
1776  return MB_SUCCESS;
1777 }
1778 
1779 int Tqdcfr::find_model( const unsigned int model_type )
1780 {
1781  for( unsigned int i = 0; i < fileTOC.numModels; i++ )
1782  {
1783  if( modelEntries[i].modelType == model_type ) return i;
1784  }
1785 
1786  return -1;
1787 }
1788 
1789 ErrorCode Tqdcfr::read_meta_data( const unsigned int metadata_offset, Tqdcfr::MetaDataContainer& mc )
1790 {
1791  // Read the metadata header
1792  FSEEK( metadata_offset );
1793  FREADI( 3 );
1794  mc.mdSchema = uint_buf[0];
1795  mc.compressFlag = uint_buf[1];
1796 
1797  // Allocate space for the entries
1798  mc.metadataEntries.resize( uint_buf[2] );
1799 
1800  // Now read the metadata values
1801  for( unsigned int i = 0; i < mc.metadataEntries.size(); i++ )
1802  {
1803  FREADI( 2 );
1804  mc.metadataEntries[i].mdOwner = uint_buf[0];
1805  mc.metadataEntries[i].mdDataType = uint_buf[1];
1806 
1807  // Read the name string
1808  read_md_string( mc.metadataEntries[i].mdName );
1809 
1810  if( mc.metadataEntries[i].mdDataType == 0 )
1811  {
1812  // integer
1813  FREADI( 1 );
1814  mc.metadataEntries[i].mdIntValue = uint_buf[0];
1815  }
1816  else if( mc.metadataEntries[i].mdDataType == 1 )
1817  {
1818  // string
1819  read_md_string( mc.metadataEntries[i].mdStringValue );
1820  }
1821  else if( mc.metadataEntries[i].mdDataType == 2 )
1822  {
1823  // double
1824  FREADD( 1 );
1825  mc.metadataEntries[i].mdDblValue = dbl_buf[0];
1826  }
1827  else if( mc.metadataEntries[i].mdDataType == 3 )
1828  {
1829  // int array
1830  FREADI( 1 );
1831  mc.metadataEntries[i].mdIntArrayValue.resize( uint_buf[0] );
1832  FREADI( mc.metadataEntries[i].mdIntArrayValue.size() );
1833  std::copy( uint_buf.begin(), uint_buf.begin() + mc.metadataEntries[i].mdIntArrayValue.size(),
1834  mc.metadataEntries[i].mdIntArrayValue.begin() );
1835  }
1836  else if( mc.metadataEntries[i].mdDataType == 4 )
1837  {
1838  // double array
1839  FREADI( 1 );
1840  mc.metadataEntries[i].mdDblArrayValue.resize( uint_buf[0] );
1841  FREADD( mc.metadataEntries[i].mdDblArrayValue.size() );
1842  std::copy( dbl_buf.begin(), dbl_buf.begin() + mc.metadataEntries[i].mdDblArrayValue.size(),
1843  mc.metadataEntries[i].mdDblArrayValue.begin() );
1844  }
1845  else
1846  return MB_FAILURE;
1847  }
1848  if( debug ) mc.print();
1849 
1850  return MB_SUCCESS;
1851 }
1852 
1853 ErrorCode Tqdcfr::read_md_string( std::string& name )
1854 {
1855  FREADI( 1 );
1856  int str_size = uint_buf[0];
1857  if( str_size > 0 )
1858  {
1859  FREADC( str_size );
1860  if( char_buf.size() <= (unsigned int)str_size ) char_buf.resize( str_size + 1 );
1861  char_buf[str_size] = '\0';
1862  name = (char*)&char_buf[0];
1863  // Read pad if any
1864  int extra = str_size % sizeof( int );
1865  if( extra )
1866  {
1867  // Read extra chars to end of pad
1868  str_size = sizeof( int ) - extra;
1869  FREADC( str_size );
1870  }
1871  }
1872 
1873  return MB_SUCCESS;
1874 }
1875 
1876 ErrorCode Tqdcfr::GeomHeader::read_info_header( const unsigned int model_offset,
1878  Tqdcfr* instance,
1879  Tqdcfr::GeomHeader*& geom_headers )
1880 {
1881  geom_headers = new GeomHeader[info.numEntities];
1882  instance->FSEEK( model_offset + info.tableOffset );
1883  int dum_int;
1884  ErrorCode result;
1885 
1886  if( 0 == instance->categoryTag )
1887  {
1888  static const char val[CATEGORY_TAG_SIZE] = { 0 };
1890  instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
1891  if( MB_SUCCESS != result ) return result;
1892  }
1893 
1894  for( unsigned int i = 0; i < info.numEntities; i++ )
1895  {
1896  instance->FREADI( 8 );
1897  geom_headers[i].nodeCt = instance->uint_buf[0];
1898  geom_headers[i].nodeOffset = instance->uint_buf[1];
1899  geom_headers[i].elemCt = instance->uint_buf[2];
1900  geom_headers[i].elemOffset = instance->uint_buf[3];
1901  geom_headers[i].elemTypeCt = instance->uint_buf[4];
1902  geom_headers[i].elemLength = instance->uint_buf[5];
1903  geom_headers[i].geomID = instance->uint_buf[6];
1904 
1905  // Don't represent in MOAB if no mesh
1906  if( geom_headers[i].nodeCt == 0 && geom_headers[i].elemCt == 0 ) continue;
1907 
1908  // Create an entity set for this entity
1909  result = instance->create_set( geom_headers[i].setHandle );
1910  if( MB_SUCCESS != result ) return result;
1911 
1912  // Set the dimension to -1; will have to reset later, after elements are read
1913  dum_int = -1;
1914  result = instance->mdbImpl->tag_set_data( instance->geomTag, &( geom_headers[i].setHandle ), 1, &dum_int );
1915  if( MB_SUCCESS != result ) return result;
1916 
1917  // Set a unique id tag
1918  result = instance->mdbImpl->tag_set_data( instance->uniqueIdTag, &( geom_headers[i].setHandle ), 1,
1919  &( geom_headers[i].geomID ) );
1920  if( MB_SUCCESS != result ) return result;
1921 
1922  // Put the set and uid into a map for later
1923  instance->uidSetMap[geom_headers[i].geomID] = geom_headers[i].setHandle;
1924  }
1925 
1926  // Now get the dimensions of elements for each geom entity
1927  for( unsigned int i = 0; i < info.numEntities; i++ )
1928  {
1929  if( geom_headers[i].elemTypeCt == 0 ) continue;
1930  instance->FSEEK( model_offset + geom_headers[i].elemOffset );
1931  for( unsigned int j = 0; j < geom_headers[i].elemTypeCt; j++ )
1932  {
1933  // For this elem type, get the type, nodes per elem, num elems
1934  instance->FREADI( 3 );
1935  int int_type = instance->uint_buf[0];
1936  int nodes_per_elem = instance->uint_buf[1];
1937  int num_elem = instance->uint_buf[2];
1938  EntityType elem_type = mp_type_to_mb_type[int_type];
1939  geom_headers[i].maxDim = std::max( geom_headers[i].maxDim, (int)CN::Dimension( elem_type ) );
1940  if( j < geom_headers[i].elemTypeCt - 1 )
1941  {
1942  int num_skipped_ints = num_elem + num_elem * nodes_per_elem;
1943  if( major >= 14 ) num_skipped_ints += num_elem;
1944  instance->FREADI( num_skipped_ints );
1945  }
1946  }
1947  }
1948 
1949  return MB_SUCCESS;
1950 }
1951 
1952 ErrorCode Tqdcfr::GroupHeader::read_info_header( const unsigned int model_offset,
1954  Tqdcfr* instance,
1955  Tqdcfr::GroupHeader*& group_headers )
1956 {
1957  group_headers = new GroupHeader[info.numEntities];
1958  instance->FSEEK( model_offset + info.tableOffset );
1959  ErrorCode result;
1960 
1961  if( 0 == instance->categoryTag )
1962  {
1963  static const char val[CATEGORY_TAG_SIZE] = { 0 };
1965  instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
1966  if( MB_SUCCESS != result ) return result;
1967  }
1968 
1969  for( unsigned int i = 0; i < info.numEntities; i++ )
1970  {
1971  // Create an entity set for this entity
1972  result = instance->create_set( group_headers[i].setHandle );
1973  if( MB_SUCCESS != result ) return result;
1974  static const char group_category[CATEGORY_TAG_SIZE] = "Group\0";
1975 
1976  instance->FREADI( 6 );
1977  group_headers[i].grpID = instance->uint_buf[0];
1978  group_headers[i].grpType = instance->uint_buf[1];
1979  group_headers[i].memCt = instance->uint_buf[2];
1980  group_headers[i].memOffset = instance->uint_buf[3];
1981  group_headers[i].memTypeCt = instance->uint_buf[4];
1982  group_headers[i].grpLength = instance->uint_buf[5];
1983 
1984  // Set the category tag to signify this is a group
1985  result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( group_headers[i].setHandle ), 1,
1986  group_category );
1987  if( MB_SUCCESS != result ) return result;
1988 
1989  // Set a global id tag
1990  result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( group_headers[i].setHandle ), 1,
1991  &( group_headers[i].grpID ) );
1992  if( MB_SUCCESS != result ) return result;
1993 
1994  instance->gidSetMap[5][group_headers[i].grpID] = group_headers[i].setHandle;
1995  }
1996 
1997  return MB_SUCCESS;
1998 }
1999 
2001  const unsigned int model_offset,
2003  Tqdcfr* instance,
2004  Tqdcfr::BlockHeader*& block_headers )
2005 {
2006  block_headers = new BlockHeader[info.numEntities];
2007  instance->FSEEK( model_offset + info.tableOffset );
2008  ErrorCode result;
2009 
2010  if( 0 == instance->categoryTag )
2011  {
2012  static const char val[CATEGORY_TAG_SIZE] = { 0 };
2014  instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
2015  if( MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result ) return result;
2016  }
2017 
2018  for( unsigned int i = 0; i < info.numEntities; i++ )
2019  {
2020  // Create an entity set for this entity
2021  result = instance->create_set( block_headers[i].setHandle );
2022  if( MB_SUCCESS != result ) return result;
2023  static const char material_category[CATEGORY_TAG_SIZE] = "Material Set\0";
2024 
2025  instance->FREADI( 12 );
2026  block_headers[i].blockID = instance->uint_buf[0];
2027  block_headers[i].blockElemType = instance->uint_buf[1];
2028  block_headers[i].memCt = instance->uint_buf[2];
2029  block_headers[i].memOffset = instance->uint_buf[3];
2030  block_headers[i].memTypeCt = instance->uint_buf[4];
2031  block_headers[i].attribOrder = instance->uint_buf[5]; // Attrib order
2032  block_headers[i].blockCol = instance->uint_buf[6];
2033  block_headers[i].blockMixElemType = instance->uint_buf[7]; // Mixed elem type
2034  block_headers[i].blockPyrType = instance->uint_buf[8];
2035  block_headers[i].blockMat = instance->uint_buf[9];
2036  block_headers[i].blockLength = instance->uint_buf[10];
2037  block_headers[i].blockDim = instance->uint_buf[11];
2038 
2039  Tag bhTag_header;
2040  {
2041  std::vector< int > def_uint_zero( 3, 0 );
2042  result = instance->mdbImpl->tag_get_handle( BLOCK_HEADER, 3 * sizeof( unsigned int ), MB_TYPE_INTEGER,
2043  bhTag_header, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_BYTES,
2044  &def_uint_zero[0] );
2045  if( MB_SUCCESS != result ) return result;
2046  int block_header_data[] = { static_cast< int >( block_headers[i].blockCol ),
2047  static_cast< int >( block_headers[i].blockMat ),
2048  static_cast< int >( block_headers[i].blockDim ) };
2049  result =
2050  instance->mdbImpl->tag_set_data( bhTag_header, &( block_headers[i].setHandle ), 1, block_header_data );
2051  }
2052 
2053  if( MB_SUCCESS != result ) return result;
2054 
2055  // Adjust element type for data version; older element types didn't include
2056  // 4 new trishell element types
2057  if( data_version <= 1.0 && block_headers[i].blockElemType >= 15 ) block_headers[i].blockElemType += 4;
2058 
2059  if( block_headers[i].blockElemType >= (unsigned)cub_elem_num_verts_len )
2060  {
2061  // Block element type unassigned, will have to infer from verts/element; make sure it's
2062  // the expected value of 52
2063  if( ( 14 == major && 2 < minor ) || 15 <= major )
2064  {
2065  if( 55 != block_headers[i].blockElemType )
2066  MB_SET_ERR( MB_FAILURE, "Invalid block element type: " << block_headers[i].blockElemType );
2067  }
2068  else
2069  {
2070  if( 52 != block_headers[i].blockElemType )
2071  MB_SET_ERR( MB_FAILURE, "Invalid block element type: " << block_headers[i].blockElemType );
2072  }
2073  }
2074 
2075  // Set the material set tag and id tag both to id
2076  result = instance->mdbImpl->tag_set_data( instance->blockTag, &( block_headers[i].setHandle ), 1,
2077  &( block_headers[i].blockID ) );
2078  if( MB_SUCCESS != result ) return result;
2079  result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( block_headers[i].setHandle ), 1,
2080  &( block_headers[i].blockID ) );
2081  if( MB_SUCCESS != result ) return result;
2082  result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( block_headers[i].setHandle ), 1,
2083  material_category );
2084  if( MB_SUCCESS != result ) return result;
2085 
2086  // If this block is empty, continue
2087  if( !block_headers[i].memCt ) continue;
2088 
2089  // Check the number of vertices in the element type, and set the has mid nodes tag
2090  // accordingly; if element type wasn't set, they're unlikely to have mid nodes
2091  // 52 is for CUBIT versions below 14.1, 55 for CUBIT version 14.9 and above
2092  if( 52 != block_headers[i].blockElemType && 55 != block_headers[i].blockElemType )
2093  {
2094  int num_verts = cub_elem_num_verts[block_headers[i].blockElemType];
2095  block_headers[i].blockEntityType = block_type_to_mb_type[block_headers[i].blockElemType];
2096  if( ( block_headers[i].blockEntityType < MBMAXTYPE ) &&
2097  ( num_verts != CN::VerticesPerEntity( block_headers[i].blockEntityType ) ) )
2098  {
2099  // Not a linear element; try to find hasMidNodes values
2100  for( int j = 0; j < 4; j++ )
2101  block_headers[i].hasMidNodes[j] = 0;
2102  if( 0 == instance->hasMidNodesTag )
2103  {
2106  block_headers[i].hasMidNodes );
2107  if( MB_SUCCESS != result ) return result;
2108  }
2109 
2110  CN::HasMidNodes( block_headers[i].blockEntityType, num_verts, block_headers[i].hasMidNodes );
2111 
2112  // Now set the tag on this set
2113  result = instance->mdbImpl->tag_set_data( instance->hasMidNodesTag, &block_headers[i].setHandle, 1,
2114  block_headers[i].hasMidNodes );
2115  if( MB_SUCCESS != result ) return result;
2116  }
2117  }
2118  }
2119 
2120  return MB_SUCCESS;
2121 }
2122 
2123 ErrorCode Tqdcfr::NodesetHeader::read_info_header( const unsigned int model_offset,
2125  Tqdcfr* instance,
2126  Tqdcfr::NodesetHeader*& nodeset_headers )
2127 {
2128  nodeset_headers = new NodesetHeader[info.numEntities];
2129  instance->FSEEK( model_offset + info.tableOffset );
2130  ErrorCode result;
2131 
2132  if( 0 == instance->categoryTag )
2133  {
2134  static const char val[CATEGORY_TAG_SIZE] = { 0 };
2136  instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
2137  if( MB_SUCCESS != result ) return result;
2138  }
2139 
2140  for( unsigned int i = 0; i < info.numEntities; i++ )
2141  {
2142  // Create an entity set for this entity
2143  result = instance->create_set( nodeset_headers[i].setHandle );
2144  if( MB_SUCCESS != result ) return result;
2145  static const char dirichlet_category[CATEGORY_TAG_SIZE] = "Dirichlet Set\0";
2146 
2147  instance->FREADI( 8 );
2148  nodeset_headers[i].nsID = instance->uint_buf[0];
2149  nodeset_headers[i].memCt = instance->uint_buf[1];
2150  nodeset_headers[i].memOffset = instance->uint_buf[2];
2151  nodeset_headers[i].memTypeCt = instance->uint_buf[3];
2152  nodeset_headers[i].pointSym = instance->uint_buf[4]; // Point sym
2153  nodeset_headers[i].nsCol = instance->uint_buf[5];
2154  nodeset_headers[i].nsLength = instance->uint_buf[6];
2155  // Pad
2156 
2157  // Set the dirichlet set tag and id tag both to id
2158  result = instance->mdbImpl->tag_set_data( instance->nsTag, &( nodeset_headers[i].setHandle ), 1,
2159  &( nodeset_headers[i].nsID ) );
2160  if( MB_SUCCESS != result ) return result;
2161  result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( nodeset_headers[i].setHandle ), 1,
2162  &( nodeset_headers[i].nsID ) );
2163  if( MB_SUCCESS != result ) return result;
2164  result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( nodeset_headers[i].setHandle ), 1,
2165  dirichlet_category );
2166  if( MB_SUCCESS != result ) return result;
2167  }
2168 
2169  return MB_SUCCESS;
2170 }
2171 
2172 ErrorCode Tqdcfr::SidesetHeader::read_info_header( const unsigned int model_offset,
2174  Tqdcfr* instance,
2175  Tqdcfr::SidesetHeader*& sideset_headers )
2176 {
2177  sideset_headers = new SidesetHeader[info.numEntities];
2178  instance->FSEEK( model_offset + info.tableOffset );
2179  ErrorCode result;
2180 
2181  if( 0 == instance->categoryTag )
2182  {
2183  static const char val[CATEGORY_TAG_SIZE] = { 0 };
2185  instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
2186  if( MB_SUCCESS != result ) return result;
2187  }
2188 
2189  for( unsigned int i = 0; i < info.numEntities; i++ )
2190  {
2191  // Create an entity set for this entity
2192  result = instance->create_set( sideset_headers[i].setHandle );
2193  if( MB_SUCCESS != result ) return result;
2194  static const char neumann_category[CATEGORY_TAG_SIZE] = "Neumann Set\0";
2195 
2196  instance->FREADI( 8 );
2197  sideset_headers[i].ssID = instance->uint_buf[0];
2198  sideset_headers[i].memCt = instance->uint_buf[1];
2199  sideset_headers[i].memOffset = instance->uint_buf[2];
2200  sideset_headers[i].memTypeCt = instance->uint_buf[3];
2201  sideset_headers[i].numDF = instance->uint_buf[4]; // Num dist factors
2202  sideset_headers[i].ssCol = instance->uint_buf[5];
2203  sideset_headers[i].useShell = instance->uint_buf[6];
2204  sideset_headers[i].ssLength = instance->uint_buf[7];
2205 
2206  // Set the neumann set tag and id tag both to id
2207  result = instance->mdbImpl->tag_set_data( instance->ssTag, &( sideset_headers[i].setHandle ), 1,
2208  &( sideset_headers[i].ssID ) );
2209  if( MB_SUCCESS != result ) return result;
2210  result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( sideset_headers[i].setHandle ), 1,
2211  &( sideset_headers[i].ssID ) );
2212  if( MB_SUCCESS != result ) return result;
2213  result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( sideset_headers[i].setHandle ), 1,
2214  neumann_category );
2215  if( MB_SUCCESS != result ) return result;
2216  }
2217 
2218  return MB_SUCCESS;
2219 }
2220 
2221 void Tqdcfr::ModelEntry::print_geom_headers( const char* prefix, GeomHeader* header, const unsigned int num_headers )
2222 {
2223  if( !debug ) return;
2224  std::cout << prefix << std::endl;
2225  if( NULL != header )
2226  {
2227  for( unsigned int i = 0; i < num_headers; i++ )
2228  {
2229  std::cout << "Index " << i << std::endl;
2230  header[i].print();
2231  }
2232  }
2233 }
2234 
2235 void Tqdcfr::ModelEntry::print_group_headers( const char* prefix, GroupHeader* header, const unsigned int num_headers )
2236 {
2237  if( !debug ) return;
2238  std::cout << prefix << std::endl;
2239  if( NULL != header )
2240  {
2241  for( unsigned int i = 0; i < num_headers; i++ )
2242  header[i].print();
2243  }
2244 }
2245 
2246 void Tqdcfr::ModelEntry::print_block_headers( const char* prefix, BlockHeader* header, const unsigned int num_headers )
2247 {
2248  if( !debug ) return;
2249  std::cout << prefix << std::endl;
2250  if( NULL != header )
2251  {
2252  for( unsigned int i = 0; i < num_headers; i++ )
2253  header[i].print();
2254  }
2255 }
2256 
2258  NodesetHeader* header,
2259  const unsigned int num_headers )
2260 {
2261  if( !debug ) return;
2262  std::cout << prefix << std::endl;
2263  if( NULL != header )
2264  {
2265  for( unsigned int i = 0; i < num_headers; i++ )
2266  header[i].print();
2267  }
2268 }
2269 
2271  SidesetHeader* header,
2272  const unsigned int num_headers )
2273 {
2274  if( !debug ) return;
2275  std::cout << prefix << std::endl;
2276  if( NULL != header )
2277  {
2278  for( unsigned int i = 0; i < num_headers; i++ )
2279  header[i].print();
2280  }
2281 }
2282 
2283 ErrorCode Tqdcfr::ModelEntry::read_header_info( Tqdcfr* instance, const double data_version )
2284 {
2285  feModelHeader.init( modelOffset, instance );
2286  int negone = -1;
2287  ErrorCode result;
2288  instance->globalIdTag = instance->mdbImpl->globalId_tag();
2289 
2290  if( feModelHeader.geomArray.numEntities > 0 )
2291  {
2292  result = instance->mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, instance->geomTag,
2293  MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
2294  if( MB_SUCCESS != result ) return result;
2295 
2296  result = instance->mdbImpl->tag_get_handle( "UNIQUE_ID", 1, MB_TYPE_INTEGER, instance->uniqueIdTag,
2297  MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
2298  if( MB_SUCCESS != result ) return result;
2299 
2300  result = Tqdcfr::GeomHeader::read_info_header( modelOffset, feModelHeader.geomArray, instance, feGeomH );
2301  print_geom_headers( "Geom headers:", feGeomH, feModelHeader.geomArray.numEntities );
2302  if( MB_SUCCESS != result ) return result;
2303  }
2304 
2305  if( feModelHeader.groupArray.numEntities > 0 )
2306  {
2307  result = Tqdcfr::GroupHeader::read_info_header( modelOffset, feModelHeader.groupArray, instance, feGroupH );
2308  print_group_headers( "Group headers:", feGroupH, feModelHeader.groupArray.numEntities );
2309  if( MB_SUCCESS != result ) return result;
2310  }
2311 
2312  if( feModelHeader.blockArray.numEntities > 0 )
2313  {
2314  result = instance->mdbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->blockTag,
2315  MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
2316  if( MB_SUCCESS != result ) return result;
2317 
2318  result = Tqdcfr::BlockHeader::read_info_header( data_version, modelOffset, feModelHeader.blockArray, instance,
2319  feBlockH );
2320  print_block_headers( "Block headers:", feBlockH, feModelHeader.blockArray.numEntities );
2321  if( MB_SUCCESS != result ) return result;
2322  }
2323  if( feModelHeader.nodesetArray.numEntities > 0 )
2324  {
2325  result = instance->mdbImpl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->nsTag,
2326  MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
2327  if( MB_SUCCESS != result ) return result;
2328 
2329  result =
2330  Tqdcfr::NodesetHeader::read_info_header( modelOffset, feModelHeader.nodesetArray, instance, feNodeSetH );
2331  if( MB_SUCCESS != result ) return result;
2332  print_nodeset_headers( "Nodeset headers:", feNodeSetH, feModelHeader.nodesetArray.numEntities );
2333  }
2334  if( feModelHeader.sidesetArray.numEntities > 0 )
2335  {
2336  result = instance->mdbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->ssTag,
2337  MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
2338  if( MB_SUCCESS != result ) return result;
2339 
2340  result =
2341  Tqdcfr::SidesetHeader::read_info_header( modelOffset, feModelHeader.sidesetArray, instance, feSideSetH );
2342  print_sideset_headers( "SideSet headers:", feSideSetH, feModelHeader.sidesetArray.numEntities );
2343  }
2344 
2345  return MB_SUCCESS;
2346 }
2347 
2349 {
2350  if( debug ) std::cout << "Geom metadata:" << std::endl;
2351  tqd->read_meta_data( modelOffset + feModelHeader.geomArray.metaDataOffset, geomMD );
2352  if( debug ) std::cout << "Node metadata:" << std::endl;
2353  tqd->read_meta_data( modelOffset + feModelHeader.nodeArray.metaDataOffset, nodeMD );
2354  if( debug ) std::cout << "Elem metadata:" << std::endl;
2355  tqd->read_meta_data( modelOffset + feModelHeader.elementArray.metaDataOffset, elementMD );
2356  if( debug ) std::cout << "Group metadata:" << std::endl;
2357  tqd->read_meta_data( modelOffset + feModelHeader.groupArray.metaDataOffset, groupMD );
2358  if( debug ) std::cout << "Block metadata:" << std::endl;
2359  tqd->read_meta_data( modelOffset + feModelHeader.blockArray.metaDataOffset, blockMD );
2360  if( debug ) std::cout << "Nodeset metadata:" << std::endl;
2361  tqd->read_meta_data( modelOffset + feModelHeader.nodesetArray.metaDataOffset, nodesetMD );
2362  if( debug ) std::cout << "Sideset metadata:" << std::endl;
2363  tqd->read_meta_data( modelOffset + feModelHeader.sidesetArray.metaDataOffset, sidesetMD );
2364 
2365  return MB_SUCCESS;
2366 }
2367 
2368 ErrorCode Tqdcfr::read_acis_records( const char* sat_filename )
2369 {
2370  // Get the acis model location
2371  unsigned int acis_model_offset = 0, acis_model_length = 0, acis_model_handle = 1, acis_sat_type = 1;
2372  for( unsigned int i = 0; i < fileTOC.numModels; i++ )
2373  {
2374  if( modelEntries[i].modelHandle == acis_model_handle && modelEntries[i].modelType == acis_sat_type )
2375  {
2376  acis_model_offset = modelEntries[i].modelOffset;
2377  acis_model_length = modelEntries[i].modelLength;
2378  break;
2379  }
2380  }
2381 
2382  if( acis_model_length == 0 ) return MB_SUCCESS;
2383 
2384  std::vector< AcisRecord > records;
2385 
2386  acisDumpFile = NULL;
2387  if( sat_filename )
2388  {
2389  acisDumpFile = fopen( sat_filename, "w+" );
2390  if( NULL == acisDumpFile ) return MB_FAILURE;
2391  }
2392 
2393  // Position the file at the start of the acis model
2394  FSEEK( acis_model_offset );
2395 
2396  unsigned int bytes_left = acis_model_length;
2397 
2398  struct AcisRecord this_record;
2399  reset_record( this_record );
2400  char* ret;
2401 
2402  // Make the char buffer at least buf_size + 1 long, to fit null char
2403  const unsigned int buf_size = 1023;
2404 
2405  // CHECK_SIZE(char_buf, buf_size + 1);
2406  char_buf.resize( buf_size + 1 );
2407 
2408  while( 0 != bytes_left )
2409  {
2410  // Read the next buff characters, or bytes_left if smaller
2411  unsigned int next_buf = ( bytes_left > buf_size ? buf_size : bytes_left );
2412  FREADC( next_buf );
2413 
2414  if( NULL != acisDumpFile ) fwrite( &char_buf[0], sizeof( char ), next_buf, acisDumpFile );
2415 
2416  // Put null at end of string to stop searches
2417  char_buf.resize( next_buf + 1 );
2418  char_buf[next_buf] = '\0';
2419  unsigned int buf_pos = 0;
2420 
2421  // Check for first read, and if so, get rid of the header
2422  if( bytes_left == acis_model_length )
2423  {
2424  // Look for 3 newlines
2425  ret = strchr( &( char_buf[0] ), '\n' );
2426  ret = strchr( ret + 1, '\n' );
2427  ret = strchr( ret + 1, '\n' );
2428  if( NULL == ret ) return MB_FAILURE;
2429  buf_pos += ret - &( char_buf[0] ) + 1;
2430  }
2431 
2432  bytes_left -= next_buf;
2433 
2434  // Now start grabbing records
2435  do
2436  {
2437  // Get next occurrence of '#' (record terminator)
2438  ret = strchr( &( char_buf[buf_pos] ), '#' );
2439  while( ret && (unsigned int)( ret + 1 - &char_buf[0] ) < bytes_left && *( ret + 1 ) != '\n' &&
2440  *( ret + 1 ) != '\r' && *( ret + 1 ) != 0 ) // CR added for windows
2441  ret = strchr( ret + 1, '#' );
2442  if( NULL != ret )
2443  {
2444  // Grab the string (inclusive of the record terminator and the line feed) and
2445  // complete the record
2446  int num_chars = ret - &( char_buf[buf_pos] ) + 2;
2447  if( *( ret + 1 ) == '\r' ) num_chars++; // add more one character for Windows CR
2448  this_record.att_string.append( &( char_buf[buf_pos] ), num_chars );
2449  buf_pos += num_chars;
2450  process_record( this_record );
2451 
2452  // Put the record in the list...
2453  records.push_back( this_record );
2454 
2455  // And reset the record
2456  reset_record( this_record );
2457  }
2458  else
2459  {
2460  // Reached end of buffer; cache string then go get another; discard last character,
2461  // which will be the null character
2462  this_record.att_string.append( &( char_buf[buf_pos] ), next_buf - buf_pos );
2463  buf_pos = next_buf;
2464  }
2465  } while( buf_pos < next_buf );
2466  }
2467 
2468  if( NULL != acisDumpFile )
2469  fwrite( "\n======================\nSorted acis records:\n======================\n", 1, 68, acisDumpFile );
2470 
2471  // Now interpret the records
2472  interpret_acis_records( records );
2473 
2474  if( NULL != acisDumpFile ) fclose( acisDumpFile );
2475 
2476  return MB_SUCCESS;
2477 }
2478 
2479 ErrorCode Tqdcfr::interpret_acis_records( std::vector< AcisRecord >& records )
2480 {
2481  // Make a tag for the vector holding unrecognized attributes
2482  void* default_val = NULL;
2483  ErrorCode result = mdbImpl->tag_get_handle( "ATTRIB_VECTOR", sizeof( void* ), MB_TYPE_OPAQUE, attribVectorTag,
2484  MB_TAG_CREAT | MB_TAG_SPARSE, &default_val );
2485  if( MB_SUCCESS != result ) return result;
2486 
2487  unsigned int current_record = 0;
2488 
2489 #define REC records[current_record]
2490 
2491  while( current_record != records.size() )
2492  {
2493  // If this record's been processed, or if it's an attribute, continue
2494  if( REC.processed || REC.rec_type == Tqdcfr::ATTRIB )
2495  {
2496  current_record++;
2497  continue;
2498  }
2499 
2500  if( REC.rec_type == Tqdcfr::UNKNOWN )
2501  {
2502  REC.processed = true;
2503  current_record++;
2504  continue;
2505  }
2506 
2507  // It's a known, non-attrib rec type; parse for any attribs
2508  parse_acis_attribs( current_record, records );
2509 
2510  REC.processed = true;
2511 
2512  current_record++;
2513  }
2514 
2515  return MB_SUCCESS;
2516 }
2517 
2518 ErrorCode Tqdcfr::parse_acis_attribs( const unsigned int entity_rec_num, std::vector< AcisRecord >& records )
2519 {
2520  unsigned int num_read;
2521  std::vector< std::string > attrib_vec;
2522  char temp_name[1024];
2523  char name_tag_val[NAME_TAG_SIZE];
2524  std::string name_tag;
2525  int id = -1;
2526  int uid = -1;
2527  int next_attrib = -1;
2528  ErrorCode result;
2529 
2530  int current_attrib = records[entity_rec_num].first_attrib;
2531  if( -1 == current_attrib ) return MB_SUCCESS;
2532 
2533  if( NULL != acisDumpFile )
2534  {
2535  fwrite( "-----------------------------------------------------------------------\n", 1, 72, acisDumpFile );
2536  fwrite( records[entity_rec_num].att_string.c_str(), sizeof( char ), records[entity_rec_num].att_string.length(),
2537  acisDumpFile );
2538  }
2539 
2540  while( -1 != current_attrib )
2541  {
2542  if( records[current_attrib].rec_type != Tqdcfr::UNKNOWN &&
2543  ( records[current_attrib].att_next != next_attrib ||
2544  records[current_attrib].att_ent_num != (int)entity_rec_num ) )
2545  return MB_FAILURE;
2546 
2547  if( NULL != acisDumpFile )
2548  fwrite( records[current_attrib].att_string.c_str(), sizeof( char ),
2549  records[current_attrib].att_string.length(), acisDumpFile );
2550 
2551  // Is the attrib one we already recognize?
2552  if( strncmp( records[current_attrib].att_string.c_str(), "ENTITY_NAME", 11 ) == 0 )
2553  {
2554  // Parse name
2555  int num_chars;
2556  num_read =
2557  sscanf( records[current_attrib].att_string.c_str(), "ENTITY_NAME @%d %s", &num_chars, temp_name );
2558  if( num_read != 2 )
2559  num_read =
2560  sscanf( records[current_attrib].att_string.c_str(), "ENTITY_NAME %d %s", &num_chars, temp_name );
2561  if( num_read != 2 ) return MB_FAILURE;
2562 
2563  // Put the name on the entity
2564  name_tag = std::string( temp_name, num_chars );
2565  }
2566  else if( strncmp( records[current_attrib].att_string.c_str(), "ENTITY_ID", 9 ) == 0 )
2567  {
2568  // Parse id
2569  int bounding_uid, bounding_sense;
2570  num_read = sscanf( records[current_attrib].att_string.c_str(), "ENTITY_ID 0 3 %d %d %d", &id, &bounding_uid,
2571  &bounding_sense );
2572  if( 3 != num_read )
2573  {
2574  // Try reading updated entity_id format, which has coordinate triple embedded in it
2575  // too
2576  float dumx, dumy, dumz;
2577  num_read = sscanf( records[current_attrib].att_string.c_str(), "ENTITY_ID 3 %f %f %f 3 %d %d %d", &dumx,
2578  &dumy, &dumz, &id, &bounding_uid, &bounding_sense );
2579  num_read -= 3;
2580  }
2581 
2582  if( 3 != num_read )
2583  std::cout << "Warning: bad ENTITY_ID attribute in .sat file, record number " << entity_rec_num
2584  << ", record follows:" << std::endl
2585  << records[current_attrib].att_string.c_str() << std::endl;
2586  }
2587  else if( strncmp( records[current_attrib].att_string.c_str(), "UNIQUE_ID", 9 ) == 0 )
2588  {
2589  // Parse uid
2590  if( major >= 14 ) // Change of format for cubit 14:
2591  num_read = sscanf( records[current_attrib].att_string.c_str(), "UNIQUE_ID 0 1 %d", &uid );
2592  else
2593  num_read = sscanf( records[current_attrib].att_string.c_str(), "UNIQUE_ID 1 0 1 %d", &uid );
2594  if( 1 != num_read ) return MB_FAILURE;
2595  }
2596  else if( strncmp( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 UNIQUE_ID", 29 ) == 0 )
2597  {
2598  // Parse uid
2599  int dum1, dum2, dum3, dum4;
2600  num_read = sscanf( records[current_attrib].att_string.c_str(),
2601  "COMPOSITE_ATTRIB @9 UNIQUE_ID %d %d %d %d %d", &dum1, &dum2, &dum3, &dum4, &uid );
2602  if( 5 != num_read ) return MB_FAILURE;
2603  }
2604  else if( strncmp( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 ENTITY_ID", 29 ) == 0 )
2605  {
2606  // Parse id
2607  int dum1, dum2, dum3;
2608  num_read = sscanf( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 ENTITY_ID %d %d %d %d",
2609  &dum1, &dum2, &dum3, &id );
2610  if( 4 != num_read ) return MB_FAILURE;
2611  }
2612  else
2613  {
2614  attrib_vec.push_back( records[current_attrib].att_string );
2615  }
2616 
2617  records[current_attrib].processed = true;
2618  next_attrib = current_attrib;
2619  current_attrib = records[current_attrib].att_prev;
2620  }
2621 
2622  // At this point, there aren't entity sets for entity types which don't contain mesh
2623  // in this case, just return
2624  if( records[entity_rec_num].rec_type == aBODY || ( records[entity_rec_num].entity == 0 && uid == -1 ) )
2625  {
2626  return MB_SUCCESS;
2627  // Warning: couldn't resolve entity of type 1 because no uid was found.
2628  // ddriv: GeomTopoTool.cpp:172: ErrorCode GeomTopoTool::separate_by_dimension(const Range&,
2629  // Range*, void**): Assertion `false' failed. xxx
2630  }
2631 
2632  // Parsed the data; now put on mdb entities; first we need to find the entity
2633  if( records[entity_rec_num].entity == 0 )
2634  {
2635  records[entity_rec_num].entity = uidSetMap[uid];
2636  }
2637 
2638  if( 0 == records[entity_rec_num].entity ) return MB_SUCCESS; // We do not have a MOAB entity for this, skip
2639 
2640  // assert(records[entity_rec_num].entity);
2641 
2642  // Set the id
2643  if( id != -1 )
2644  {
2645  result = mdbImpl->tag_set_data( globalIdTag, &( records[entity_rec_num].entity ), 1, &id );
2646  if( MB_SUCCESS != result ) return result;
2647 
2648  int ent_dim = -1;
2649  if( records[entity_rec_num].rec_type == aBODY )
2650  ent_dim = 4;
2651  else if( records[entity_rec_num].rec_type == LUMP )
2652  ent_dim = 3;
2653  else if( records[entity_rec_num].rec_type == FACE )
2654  ent_dim = 2;
2655  else if( records[entity_rec_num].rec_type == aEDGE )
2656  ent_dim = 1;
2657  else if( records[entity_rec_num].rec_type == aVERTEX )
2658  ent_dim = 0;
2659  if( -1 != ent_dim ) gidSetMap[ent_dim][id] = records[entity_rec_num].entity;
2660  }
2661 
2662  // Set the name
2663  if( !name_tag.empty() )
2664  {
2665  if( 0 == entityNameTag )
2666  {
2667  char dum_val[NAME_TAG_SIZE] = { 0 };
2669  MB_TAG_SPARSE | MB_TAG_CREAT, dum_val );
2670  if( MB_SUCCESS != result ) return result;
2671  }
2672 
2673  size_t len = name_tag.size();
2674  if( len >= NAME_TAG_SIZE ) len = NAME_TAG_SIZE - 1; // Truncate a name that is too big
2675  memcpy( name_tag_val, name_tag.c_str(), len );
2676  memset( name_tag_val + len, '\0', NAME_TAG_SIZE - len );
2677  result = mdbImpl->tag_set_data( entityNameTag, &( records[entity_rec_num].entity ), 1, name_tag_val );
2678  if( MB_SUCCESS != result ) return result;
2679  }
2680 
2681  if( !attrib_vec.empty() )
2682  {
2683  // Put the attrib vector in a tag on the entity
2684  std::vector< std::string >* dum_vec;
2685  result = mdbImpl->tag_get_data( attribVectorTag, &( records[entity_rec_num].entity ), 1, &dum_vec );
2686  if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) return result;
2687  if( MB_TAG_NOT_FOUND == result || dum_vec == NULL )
2688  {
2689  // Put this list directly on the entity
2690  dum_vec = new std::vector< std::string >;
2691  dum_vec->swap( attrib_vec );
2692  result = mdbImpl->tag_set_data( attribVectorTag, &( records[entity_rec_num].entity ), 1, &dum_vec );
2693  if( MB_SUCCESS != result )
2694  {
2695  delete dum_vec;
2696  return result;
2697  }
2698  }
2699  else
2700  {
2701  // Copy this list over, and delete this list
2702  std::copy( attrib_vec.begin(), attrib_vec.end(), std::back_inserter( *dum_vec ) );
2703  }
2704  }
2705 
2706  return MB_SUCCESS;
2707 }
2708 
2710 {
2711  this_record.rec_type = Tqdcfr::UNKNOWN;
2712  this_record.att_string.clear();
2713  this_record.first_attrib = this_record.att_prev = this_record.att_next = this_record.att_ent_num = -1;
2714  this_record.processed = false;
2715  this_record.entity = 0;
2716 
2717  return MB_SUCCESS;
2718 }
2719 
2721 {
2722  // Get the entity type
2723  const char* type_substr;
2724 
2725  // Try attribs first, since the others have some common processing between them
2726  if( ( type_substr = strstr( this_record.att_string.c_str(), "attrib" ) ) != NULL &&
2727  type_substr - this_record.att_string.c_str() < 20 )
2728  {
2729  this_record.rec_type = Tqdcfr::ATTRIB;
2730  bool simple_attrib = false;
2731  bool generic_attrib = false;
2732  if( ( type_substr = strstr( this_record.att_string.c_str(), "simple-snl-attrib" ) ) != NULL )
2733  simple_attrib = true;
2734  else if( ( type_substr = strstr( this_record.att_string.c_str(), "integer_attrib-name_attrib-gen-attrib" ) ) !=
2735  NULL )
2736  generic_attrib = true;
2737  else
2738  {
2739  this_record.rec_type = Tqdcfr::UNKNOWN;
2740  return MB_SUCCESS;
2741  }
2742 
2743  // Find next space
2744  type_substr = strchr( type_substr, ' ' );
2745  if( NULL == type_substr ) return MB_FAILURE;
2746 
2747  // Read the numbers from there
2748  int num_converted = sscanf( type_substr, " $-1 -1 $%d $%d $%d -1", &( this_record.att_prev ),
2749  &( this_record.att_next ), &( this_record.att_ent_num ) );
2750  if( num_converted != 3 ) return MB_FAILURE;
2751 
2752  // Trim the string to the attribute, if it's a simple attrib
2753  if( simple_attrib )
2754  {
2755  type_substr = strstr( this_record.att_string.c_str(), "NEW_SIMPLE_ATTRIB" );
2756  if( NULL == type_substr ) return MB_FAILURE;
2757  type_substr = strstr( type_substr, "@" );
2758  if( NULL == type_substr ) return MB_FAILURE;
2759  type_substr = strstr( type_substr, " " ) + 1;
2760  // Copy the rest of the string to a dummy string
2761  std::string dum_str( type_substr );
2762  this_record.att_string = dum_str;
2763  }
2764  else if( generic_attrib )
2765  {
2766  type_substr = strstr( this_record.att_string.c_str(), "CUBIT_ID" );
2767  if( NULL == type_substr ) return MB_FAILURE;
2768  // Copy the rest of the string to a dummy string
2769  std::string dum_str( type_substr );
2770  this_record.att_string = dum_str;
2771  }
2772  }
2773  else
2774  {
2775  // Else it's a topological entity, I think
2776  if( ( type_substr = strstr( this_record.att_string.c_str(), "body" ) ) != NULL &&
2777  type_substr - this_record.att_string.c_str() < 20 )
2778  {
2779  this_record.rec_type = Tqdcfr::aBODY;
2780  }
2781  else if( ( type_substr = strstr( this_record.att_string.c_str(), "lump" ) ) != NULL &&
2782  type_substr - this_record.att_string.c_str() < 20 )
2783  {
2784  this_record.rec_type = Tqdcfr::LUMP;
2785  }
2786  else if( ( type_substr = strstr( this_record.att_string.c_str(), "shell" ) ) != NULL &&
2787  type_substr - this_record.att_string.c_str() < 20 )
2788  {
2789  // Don't care about shells
2790  this_record.rec_type = Tqdcfr::UNKNOWN;
2791  }
2792  else if( ( type_substr = strstr( this_record.att_string.c_str(), "surface" ) ) != NULL &&
2793  type_substr - this_record.att_string.c_str() < 20 )
2794  {
2795  // Don't care about surfaces
2796  this_record.rec_type = Tqdcfr::UNKNOWN;
2797  }
2798  else if( ( type_substr = strstr( this_record.att_string.c_str(), "face" ) ) != NULL &&
2799  type_substr - this_record.att_string.c_str() < 20 )
2800  {
2801  this_record.rec_type = Tqdcfr::FACE;
2802  }
2803  else if( ( type_substr = strstr( this_record.att_string.c_str(), "loop" ) ) != NULL &&
2804  type_substr - this_record.att_string.c_str() < 20 )
2805  {
2806  // Don't care about loops
2807  this_record.rec_type = Tqdcfr::UNKNOWN;
2808  }
2809  else if( ( type_substr = strstr( this_record.att_string.c_str(), "coedge" ) ) != NULL &&
2810  type_substr - this_record.att_string.c_str() < 20 )
2811  {
2812  // Don't care about coedges
2813  this_record.rec_type = Tqdcfr::UNKNOWN;
2814  }
2815  else if( ( type_substr = strstr( this_record.att_string.c_str(), "edge" ) ) != NULL &&
2816  type_substr - this_record.att_string.c_str() < 20 )
2817  {
2818  this_record.rec_type = Tqdcfr::aEDGE;
2819  }
2820  else if( ( type_substr = strstr( this_record.att_string.c_str(), "vertex" ) ) != NULL &&
2821  type_substr - this_record.att_string.c_str() < 20 )
2822  {
2823  this_record.rec_type = Tqdcfr::aVERTEX;
2824  }
2825  else
2826  this_record.rec_type = Tqdcfr::UNKNOWN;
2827 
2828  if( this_record.rec_type != Tqdcfr::UNKNOWN )
2829  {
2830  // Print a warning if it looks like there are sequence numbers
2831  if( type_substr != this_record.att_string.c_str() && !printedSeqWarning )
2832  {
2833  std::cout << "Warning: acis file has sequence numbers!" << std::endl;
2834  printedSeqWarning = true;
2835  }
2836 
2837  // Scan ahead to the next white space
2838  type_substr = strchr( type_substr, ' ' );
2839  if( NULL == type_substr ) return MB_FAILURE;
2840 
2841  // Get the id of the first attrib
2842  int num_converted = sscanf( type_substr, " $%d", &( this_record.first_attrib ) );
2843  if( num_converted != 1 ) return MB_FAILURE;
2844  }
2845  }
2846 
2847  return MB_SUCCESS;
2848 }
2849 
2851  : fileEndian( 0 ), fileSchema( 0 ), numModels( 0 ), modelTableOffset( 0 ), modelMetaDataOffset( 0 ),
2852  activeFEModel( 0 )
2853 {
2854 }
2855 
2857 {
2858  std::cout << "FileTOC:End, Sch, #Mdl, TabOff, "
2859  << "MdlMDOff, actFEMdl = ";
2860  std::cout << fileEndian << ", " << fileSchema << ", " << numModels << ", " << modelTableOffset << ", "
2861  << modelMetaDataOffset << ", " << activeFEModel << std::endl;
2862 }
2863 
2864 Tqdcfr::FEModelHeader::ArrayInfo::ArrayInfo() : numEntities( 0 ), tableOffset( 0 ), metaDataOffset( 0 ) {}
2865 
2867 {
2868  std::cout << "ArrayInfo:numEntities, tableOffset, metaDataOffset = " << numEntities << ", " << tableOffset << ", "
2869  << metaDataOffset << std::endl;
2870 }
2871 
2872 void Tqdcfr::FEModelHeader::ArrayInfo::init( const std::vector< unsigned int >& uint_buf_in )
2873 {
2874  numEntities = uint_buf_in[0];
2875  tableOffset = uint_buf_in[1];
2876  metaDataOffset = uint_buf_in[2];
2877 }
2878 
2880 {
2881  std::cout << "FEModelHeader:feEndian, feSchema, feCompressFlag, feLength = " << feEndian << ", " << feSchema << ", "
2882  << feCompressFlag << ", " << feLength << std::endl;
2883  std::cout << "geomArray: ";
2884  geomArray.print();
2885  std::cout << "nodeArray: ";
2886  nodeArray.print();
2887  std::cout << "elementArray: ";
2888  elementArray.print();
2889  std::cout << "groupArray: ";
2890  groupArray.print();
2891  std::cout << "blockArray: ";
2892  blockArray.print();
2893  std::cout << "nodesetArray: ";
2894  nodesetArray.print();
2895  std::cout << "sidesetArray: ";
2896  sidesetArray.print();
2897 }
2898 
2900  : geomID( 0 ), nodeCt( 0 ), nodeOffset( 0 ), elemCt( 0 ), elemOffset( 0 ), elemTypeCt( 0 ), elemLength( 0 ),
2901  maxDim( 0 ), setHandle( 0 )
2902 {
2903 }
2904 
2906 {
2907  std::cout << "geomID = " << geomID << std::endl;
2908  std::cout << "nodeCt = " << nodeCt << std::endl;
2909  std::cout << "nodeOffset = " << nodeOffset << std::endl;
2910  std::cout << "elemCt = " << elemCt << std::endl;
2911  std::cout << "elemOffset = " << elemOffset << std::endl;
2912  std::cout << "elemTypeCt = " << elemTypeCt << std::endl;
2913  std::cout << "elemLength = " << elemLength << std::endl;
2914  std::cout << "setHandle = " << setHandle << std::endl;
2915 }
2916 
2918  : grpID( 0 ), grpType( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), grpLength( 0 ), setHandle( 0 )
2919 {
2920 }
2921 
2923 {
2924  std::cout << "grpID = " << grpID << std::endl;
2925  std::cout << "grpType = " << grpType << std::endl;
2926  std::cout << "memCt = " << memCt << std::endl;
2927  std::cout << "memOffset = " << memOffset << std::endl;
2928  std::cout << "memTypeCt = " << memTypeCt << std::endl;
2929  std::cout << "grpLength = " << grpLength << std::endl;
2930  std::cout << "setHandle = " << setHandle << std::endl;
2931 }
2932 
2934  : blockID( 0 ), blockElemType( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), attribOrder( 0 ), blockCol( 0 ),
2935  blockMixElemType( 0 ), blockPyrType( 0 ), blockMat( 0 ), blockLength( 0 ), blockDim( 0 ), setHandle( 0 ),
2936  blockEntityType( MBMAXTYPE )
2937 {
2938 }
2939 
2941 {
2942  std::cout << "blockID = " << blockID << std::endl;
2943  std::cout << "blockElemType = " << blockElemType << std::endl;
2944  std::cout << "memCt = " << memCt << std::endl;
2945  std::cout << "memOffset = " << memOffset << std::endl;
2946  std::cout << "memTypeCt = " << memTypeCt << std::endl;
2947  std::cout << "attribOrder = " << attribOrder << std::endl;
2948  std::cout << "blockCol = " << blockCol << std::endl;
2949  std::cout << "blockMixElemType = " << blockMixElemType << std::endl;
2950  std::cout << "blockPyrType = " << blockPyrType << std::endl;
2951  std::cout << "blockMat = " << blockMat << std::endl;
2952  std::cout << "blockLength = " << blockLength << std::endl;
2953  std::cout << "blockDim = " << blockDim << std::endl;
2954  std::cout << "setHandle = " << setHandle << std::endl;
2955  std::cout << "blockEntityType = " << blockEntityType << std::endl;
2956 }
2957 
2959  : nsID( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), pointSym( 0 ), nsCol( 0 ), nsLength( 0 ), setHandle( 0 )
2960 {
2961 }
2962 
2964 {
2965  std::cout << "nsID = " << nsID << std::endl;
2966  std::cout << "memCt = " << memCt << std::endl;
2967  std::cout << "memOffset = " << memOffset << std::endl;
2968  std::cout << "memTypeCt = " << memTypeCt << std::endl;
2969  std::cout << "pointSym = " << pointSym << std::endl;
2970  std::cout << "nsCol = " << nsCol << std::endl;
2971  std::cout << "nsLength = " << nsLength << std::endl;
2972  std::cout << "setHandle = " << setHandle << std::endl;
2973 }
2974 
2976  : ssID( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), numDF( 0 ), ssCol( 0 ), useShell( 0 ), ssLength( 0 ),
2977  setHandle( 0 )
2978 {
2979 }
2980 
2982 {
2983  std::cout << "ssID = " << ssID << std::endl;
2984  std::cout << "memCt = " << memCt << std::endl;
2985  std::cout << "memOffset = " << memOffset << std::endl;
2986  std::cout << "memTypeCt = " << memTypeCt << std::endl;
2987  std::cout << "numDF = " << numDF << std::endl;
2988  std::cout << "ssCol = " << ssCol << std::endl;
2989  std::cout << "useShell = " << useShell << std::endl;
2990  std::cout << "ssLength = " << ssLength << std::endl;
2991  std::cout << "setHandle = " << setHandle << std::endl;
2992 }
2993 
2995  : mdOwner( 0 ), mdDataType( 0 ), mdIntValue( 0 ), mdName( "(uninit)" ), mdStringValue( "(uninit)" ), mdDblValue( 0 )
2996 {
2997 }
2998 
3000 {
3001  std::cout << "MetaDataEntry:own, typ, name, I, D, S = " << mdOwner << ", " << mdDataType << ", " << mdName << ", "
3002  << mdIntValue << ", " << mdDblValue << ", " << mdStringValue;
3003  unsigned int i;
3004  if( mdIntArrayValue.size() )
3005  {
3006  std::cout << std::endl << "IArray = " << mdIntArrayValue[0];
3007  for( i = 1; i < mdIntArrayValue.size(); i++ )
3008  std::cout << ", " << mdIntArrayValue[i];
3009  }
3010  if( mdDblArrayValue.size() )
3011  {
3012  std::cout << std::endl << "DArray = " << mdDblArrayValue[0];
3013  for( i = 1; i < mdDblArrayValue.size(); i++ )
3014  std::cout << ", " << mdDblArrayValue[i];
3015  }
3016  std::cout << std::endl;
3017 }
3018 
3020 {
3021  std::cout << "MetaDataContainer:mdSchema, compressFlag, numDatums = " << mdSchema << ", " << compressFlag << ", "
3022  << metadataEntries.size() << std::endl;
3023 
3024  for( unsigned int i = 0; i < metadataEntries.size(); i++ )
3025  metadataEntries[i].print();
3026 }
3027 
3029 
3030 int Tqdcfr::MetaDataContainer::get_md_entry( const unsigned int owner, const std::string& name )
3031 {
3032  for( unsigned int i = 0; i < metadataEntries.size(); i++ )
3033  {
3034  if( owner == metadataEntries[i].mdOwner && name == metadataEntries[i].mdName ) return i;
3035  }
3036 
3037  return -1;
3038 }
3039 
3041  : modelHandle( 0 ), modelOffset( 0 ), modelLength( 0 ), modelType( 0 ), modelOwner( 0 ), modelPad( 0 ),
3042  feGeomH( NULL ), feGroupH( NULL ), feBlockH( NULL ), feNodeSetH( NULL ), feSideSetH( NULL )
3043 {
3044 }
3045 
3047 {
3048  delete[] feGeomH;
3049  delete[] feGroupH;
3050  delete[] feBlockH;
3051  delete[] feNodeSetH;
3052  delete[] feSideSetH;
3053 }
3054 
3056 {
3057  std::cout << "ModelEntry: Han, Of, Len, Tp, Own, Pd = " << modelHandle << ", " << modelOffset << ", " << modelLength
3058  << ", " << modelType << ", " << modelOwner << ", " << modelPad << std::endl;
3059 }
3060 
3061 ErrorCode Tqdcfr::create_set( EntityHandle& h, unsigned int flags )
3062 {
3063  return mdbImpl->create_meshset( flags, h );
3064 }
3065 
3066 } // namespace moab