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