Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
Tqdcfr.cpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 #include "Tqdcfr.hpp"
00017 #include "moab/Core.hpp"
00018 #include "moab/Range.hpp"
00019 #include "moab/FileOptions.hpp"
00020 #include <iostream>
00021 #include <string>
00022 
00023 #ifdef MOAB_HAVE_MPI
00024 #include "moab_mpi.h"
00025 #endif
00026 
00027 #include "moab/ReadUtilIface.hpp"
00028 #include "SequenceManager.hpp"
00029 #include "moab/GeomTopoTool.hpp"
00030 #include "MBTagConventions.hpp"
00031 #include "moab/CN.hpp"
00032 #include "Internals.hpp"
00033 #include "moab/HigherOrderFactory.hpp"
00034 #include "exodus_order.h"
00035 
00036 #include <sstream>
00037 #include <cassert>
00038 #include <cstring>
00039 
00040 namespace moab
00041 {
00042 
00043 static bool debug = false;
00044 
00045 const char Tqdcfr::geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0" };
00046 
00047 // Will be used in a static function, so declared outside class members :(
00048 // major/minor cubit version that wrote this file
00049 static int major = -1, minor = -1;
00050 const EntityType Tqdcfr::group_type_to_mb_type[] = { MBENTITYSET, MBENTITYSET, MBENTITYSET,  // group, body, volume
00051                                                      MBENTITYSET, MBENTITYSET, MBENTITYSET,  // surface, curve, vertex
00052                                                      MBHEX,       MBTET,       MBPYRAMID,   MBQUAD,
00053                                                      MBTRI,       MBEDGE,      MBVERTEX };
00054 
00055 const EntityType Tqdcfr::block_type_to_mb_type[] = {
00056     MBVERTEX,                                               // sphere
00057     MBEDGE,    MBEDGE,    MBEDGE,                           // bars
00058     MBEDGE,    MBEDGE,    MBEDGE,                           // beams
00059     MBEDGE,    MBEDGE,    MBEDGE,                           // truss
00060     MBEDGE,                                                 // spring
00061     MBTRI,     MBTRI,     MBTRI,     MBTRI,                 // tri
00062     MBTRI,     MBTRI,     MBTRI,     MBTRI,                 // trishell
00063     MBQUAD,    MBQUAD,    MBQUAD,    MBQUAD,                // shell
00064     MBQUAD,    MBQUAD,    MBQUAD,    MBQUAD,    MBQUAD,     // quad
00065     MBTET,     MBTET,     MBTET,     MBTET,     MBTET,      // tet
00066     MBPYRAMID, MBPYRAMID, MBPYRAMID, MBPYRAMID, MBPYRAMID,  // pyramid
00067     MBHEX,     MBHEX,     MBHEX,     MBHEX,     MBHEX,      // hex
00068     MBHEX,                                                  // hexshell
00069     MBMAXTYPE                                               // last
00070 };
00071 
00072 // Mapping from mesh packet type to moab type
00073 const EntityType Tqdcfr::mp_type_to_mb_type[] = { MBHEX,  MBHEX,  MBHEX,     MBHEX,     MBHEX,     MBHEX,     MBHEX,
00074                                                   MBHEX,  MBTET,  MBTET,     MBTET,     MBTET,     MBTET,     MBTET,
00075                                                   MBTET,  MBTET,  MBPYRAMID, MBPYRAMID, MBPYRAMID, MBPYRAMID, MBQUAD,
00076                                                   MBQUAD, MBQUAD, MBQUAD,    MBTRI,     MBTRI,     MBTRI,     MBTRI,
00077                                                   MBEDGE, MBEDGE, MBVERTEX };
00078 
00079 const int Tqdcfr::cub_elem_num_verts[] = { 1,                    // sphere
00080                                            2, 2, 3,              // bars
00081                                            2, 2, 3,              // beams
00082                                            2, 2, 3,              // truss
00083                                            2,                    // spring
00084                                            3, 3, 6, 7,           // tris
00085                                            3, 3, 6, 7,           // trishells
00086                                            4, 4, 8, 9,           // shells
00087                                            4, 4, 5, 8,  9,       // quads
00088                                            4, 4, 8, 10, 14,      // tets
00089                                            5, 5, 8, 13, 18,      // pyramids
00090                                            8, 8, 9, 20, 27, 12,  // hexes (incl. hexshell at end)
00091                                            0 };
00092 
00093 const int Tqdcfr::cub_elem_num_verts_len = sizeof( cub_elem_num_verts ) / sizeof( cub_elem_num_verts[0] );
00094 
00095 // Define node-order map from Cubit to CN. Table is indexed
00096 // by EntityType and number of nodes. Entries are NULL if Cubit order
00097 // is the same as CN ordering. Non-null entries contain the
00098 // index into the MOAB node order for the corresponding vertex
00099 // in the Cubit connectivity list. Thus for a 27-node hex:
00100 // moab_conn[ cub_hex27_order[i] ] = cubit_conn[ i ];
00101 const int* const* const* const cub_elem_order_map = exodus_elem_order_map;
00102 
00103 const char* const BLOCK_NODESET_OFFSET_TAG_NAME = "BLOCK_NODESET_OFFSET";
00104 const char* const BLOCK_SIDESET_OFFSET_TAG_NAME = "BLOCK_SIDESET_OFFSET";
00105 
00106 #define RR \
00107     if( MB_SUCCESS != result ) return result
00108 
00109 // acis dimensions for each entity type, to match
00110 // enum {BODY, LUMP, SHELL, FACE, LOOP, COEDGE, EDGE, VERTEX, ATTRIB, UNKNOWN}
00111 
00112 #define IO_ASSERT( C ) INT_IO_ERROR( C, __LINE__ )
00113 
00114 static inline void INT_IO_ERROR( bool condition, unsigned line )
00115 {
00116     if( !condition )
00117     {
00118         char buffer[] = __FILE__ "             ";
00119         sprintf( buffer, "%s:%u", __FILE__, line );
00120         fflush( stderr );
00121         perror( buffer );
00122         abort();
00123     }
00124 }
00125 
00126 void Tqdcfr::FSEEK( unsigned int offset )
00127 {
00128     int rval = fseek( cubFile, offset, SEEK_SET );
00129     IO_ASSERT( !rval );
00130 }
00131 
00132 void Tqdcfr::FREADI( unsigned num_ents )
00133 {
00134     if( uint_buf.size() < num_ents )
00135     {
00136         uint_buf.resize( num_ents );
00137         int_buf = (int*)&uint_buf[0];
00138     }
00139     FREADIA( num_ents, &uint_buf[0] );
00140 }
00141 
00142 void Tqdcfr::FREADD( unsigned num_ents )
00143 {
00144     dbl_buf.resize( num_ents );
00145     FREADDA( num_ents, &dbl_buf[0] );
00146 }
00147 
00148 void Tqdcfr::FREADC( unsigned num_ents )
00149 {
00150     char_buf.resize( num_ents );
00151     FREADCA( num_ents, &char_buf[0] );
00152 }
00153 
00154 // Used for swapping
00155 static void swap8_voff( long* data )
00156 {
00157     unsigned char tmp, *cdat = (unsigned char*)data;
00158     tmp     = cdat[0];
00159     cdat[0] = cdat[7], cdat[7] = tmp;
00160     tmp     = cdat[1];
00161     cdat[1] = cdat[6], cdat[6] = tmp;
00162     tmp     = cdat[2];
00163     cdat[2] = cdat[5], cdat[5] = tmp;
00164     tmp     = cdat[3];
00165     cdat[3] = cdat[4], cdat[4] = tmp;
00166 }
00167 
00168 static void swap4_uint( unsigned int* data )
00169 {
00170     unsigned char tmp, *cdat = (unsigned char*)data;
00171     tmp     = cdat[0];
00172     cdat[0] = cdat[3], cdat[3] = tmp;
00173     tmp     = cdat[1];
00174     cdat[1] = cdat[2], cdat[2] = tmp;
00175 }
00176 
00177 /*
00178 static void swap2_ushort(unsigned short *data)
00179 {
00180   unsigned char tmp, *cdat = (unsigned char *) data;
00181   tmp = cdat[0]; cdat[0] = cdat[1], cdat[1] = tmp;
00182 }
00183 */
00184 
00185 void Tqdcfr::FREADIA( unsigned num_ents, unsigned int* array )
00186 {
00187     unsigned rval = fread( array, sizeof( unsigned int ), num_ents, cubFile );
00188     IO_ASSERT( rval == num_ents );
00189     if( swapForEndianness )
00190     {
00191         unsigned int* pt = array;
00192         for( unsigned int i = 0; i < num_ents; i++ )
00193         {
00194             swap4_uint( (unsigned int*)pt );
00195             pt++;
00196         }
00197     }
00198 }
00199 
00200 void Tqdcfr::FREADDA( unsigned num_ents, double* array )
00201 {
00202     unsigned rval = fread( array, sizeof( double ), num_ents, cubFile );
00203     IO_ASSERT( rval == num_ents );
00204     if( swapForEndianness )
00205     {
00206         double* pt = array;
00207         for( unsigned int i = 0; i < num_ents; i++ )
00208         {
00209             swap8_voff( (long*)pt );
00210             pt++;
00211         }
00212     }
00213 }
00214 
00215 void Tqdcfr::FREADCA( unsigned num_ents, char* array )
00216 {
00217     unsigned rval = fread( array, sizeof( char ), num_ents, cubFile );
00218     IO_ASSERT( rval == num_ents );
00219 }
00220 
00221 void Tqdcfr::CONVERT_TO_INTS( unsigned int num_ents )
00222 {
00223     for( unsigned int i = 0; i < num_ents; i++ )
00224         int_buf[i] = uint_buf[i];
00225 }
00226 
00227 ReaderIface* Tqdcfr::factory( Interface* iface )
00228 {
00229     return new Tqdcfr( iface );
00230 }
00231 
00232 Tqdcfr::Tqdcfr( Interface* impl )
00233     : cubFile( NULL ), globalIdTag( 0 ), cubIdTag( 0 ), geomTag( 0 ), uniqueIdTag( 0 ), blockTag( 0 ), nsTag( 0 ),
00234       ssTag( 0 ), attribVectorTag( 0 ), entityNameTag( 0 ), categoryTag( 0 ), hasMidNodesTag( 0 ),
00235       swapForEndianness( false ), int_buf( NULL ), mFileSet( 0 ), printedSeqWarning( false ),
00236       printedElemWarning( false ), acisDumpFile( NULL )
00237 {
00238     assert( NULL != impl );
00239     mdbImpl = impl;
00240     impl->query_interface( readUtilIface );
00241     assert( NULL != readUtilIface );
00242 
00243     currVHandleOffset = -1;
00244     for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
00245         currElementIdOffset[this_type] = -1;
00246 
00247     ErrorCode rval;
00248     rval = mdbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, blockTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
00249     rval = mdbImpl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, nsTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
00250     rval = mdbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ssTag );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
00251 
00252     if( 0 == entityNameTag )
00253     {
00254         rval = mdbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, entityNameTag,
00255                                         MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR_RET( rval, "Failed to tag_get_handle." );
00256     }
00257 
00258     cubMOABVertexMap = NULL;
00259 }
00260 
00261 Tqdcfr::~Tqdcfr()
00262 {
00263     mdbImpl->release_interface( readUtilIface );
00264 
00265     if( NULL != cubMOABVertexMap ) delete cubMOABVertexMap;
00266     if( attribVectorTag )
00267     {
00268         // get all sets, and release the string vectors
00269         Range allSets;  // although only geom sets should have these attributes
00270         // can't error in a destructor
00271         ErrorCode rval = mdbImpl->get_entities_by_type( 0, MBENTITYSET, allSets );
00272         if( rval != MB_SUCCESS ) std::cerr << "WARNING: Could not get_entities_by_type" << std::endl;
00273         for( Range::iterator sit = allSets.begin(); sit != allSets.end(); ++sit )
00274         {
00275             EntityHandle gset = *sit;
00276             std::vector< std::string >* dum_vec;
00277             // can't error in a destructor
00278             rval = mdbImpl->tag_get_data( attribVectorTag, &gset, 1, &dum_vec );
00279             if( rval != MB_SUCCESS ) std::cerr << "WARNING: Could not tag_get_data" << std::endl;
00280             if( NULL != dum_vec ) delete dum_vec;  //
00281         }
00282         mdbImpl->tag_delete( attribVectorTag );
00283         attribVectorTag = NULL;
00284     }
00285 }
00286 
00287 ErrorCode Tqdcfr::read_tag_values( const char* /* file_name */,
00288                                    const char* /* tag_name */,
00289                                    const FileOptions& /* opts */,
00290                                    std::vector< int >& /* tag_values_out */,
00291                                    const SubsetList* /* subset_list */ )
00292 {
00293     return MB_NOT_IMPLEMENTED;
00294 }
00295 
00296 ErrorCode Tqdcfr::load_file( const char* file_name,
00297                              const EntityHandle*,
00298                              const FileOptions& opts,
00299                              const ReaderIface::SubsetList* subset_list,
00300                              const Tag* file_id_tag )
00301 {
00302     ErrorCode result;
00303 
00304     int tmpval;
00305     if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) )
00306     {
00307         if( 0 < tmpval ) debug = true;
00308     }
00309 
00310     if( subset_list )
00311     {
00312         MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for CUB files" );
00313     }
00314 
00315     // Open file
00316     cubFile = fopen( file_name, "rb" );
00317     if( NULL == cubFile )
00318     {
00319         MB_SET_ERR( MB_FAILURE, "File not found" );
00320     }
00321 
00322     // Verify magic string
00323     FREADC( 4 );
00324     if( !( char_buf[0] == 'C' && char_buf[1] == 'U' && char_buf[2] == 'B' && char_buf[3] == 'E' ) )
00325     {
00326         fclose( cubFile );
00327         MB_SET_ERR( MB_FAILURE, "This doesn't appear to be a .cub file" );
00328     }
00329 
00330     // Get "before" entities
00331     result = mdbImpl->get_entities_by_handle( 0, beforeEnts );MB_CHK_SET_ERR( result, "Couldn't get \"before\" entities" );
00332 
00333     // ***********************
00334     // Read model header type information...
00335     // ***********************
00336     if( debug ) std::cout << "Reading file header." << std::endl;
00337     result = read_file_header();RR;
00338 
00339     if( debug ) std::cout << "Reading model entries." << std::endl;
00340     result = read_model_entries();RR;
00341 
00342     // Read model metadata
00343     if( debug ) std::cout << "Reading model metadata." << std::endl;
00344     result = read_meta_data( fileTOC.modelMetaDataOffset, modelMetaData );RR;
00345 
00346     double data_version;
00347     int md_index = modelMetaData.get_md_entry( 2, "DataVersion" );
00348     if( -1 == md_index )
00349         data_version = 1.0;
00350     else
00351         data_version = modelMetaData.metadataEntries[md_index].mdDblValue;
00352 
00353     // Get the major/minor cubit version that wrote this file
00354     // int major = -1, minor = -1;
00355     md_index = modelMetaData.get_md_entry( 2, "CubitVersion" );
00356     if( md_index >= 0 && !modelMetaData.metadataEntries[md_index].mdStringValue.empty() )
00357         sscanf( modelMetaData.metadataEntries[md_index].mdStringValue.c_str(), "%d.%d", &major, &minor );
00358 
00359     // ***********************
00360     // Read mesh...
00361     // ***********************
00362     int index = find_model( mesh );
00363     if( -1 == index ) return MB_FAILURE;
00364     ModelEntry* mesh_model = &modelEntries[index];
00365 
00366     // First the header & metadata info
00367     if( debug ) std::cout << "Reading mesh model header and metadata." << std::endl;
00368     result = mesh_model->read_header_info( this, data_version );
00369     if( MB_SUCCESS != result ) return result;
00370     result = mesh_model->read_metadata_info( this );
00371     if( MB_SUCCESS != result ) return result;
00372 
00373     // Now read in mesh for each geometry entity; read in order of increasing dimension
00374     // so we have all the mesh we need
00375     for( int dim = 0; dim < 4; dim++ )
00376     {
00377         for( unsigned int gindex = 0; gindex < mesh_model->feModelHeader.geomArray.numEntities; gindex++ )
00378         {
00379             Tqdcfr::GeomHeader* geom_header = &mesh_model->feGeomH[gindex];
00380 
00381             if( geom_header->maxDim != dim ) continue;
00382 
00383             // Read nodes
00384             if( debug ) std::cout << "Reading geom index " << gindex << " mesh: nodes... ";
00385             result = read_nodes( gindex, mesh_model, geom_header );
00386             if( MB_SUCCESS != result ) return result;
00387 
00388             // Read elements
00389             if( debug ) std::cout << "elements... ";
00390             result = read_elements( mesh_model, geom_header );
00391             if( MB_SUCCESS != result ) return result;
00392             if( debug ) std::cout << std::endl;
00393         }
00394     }
00395 
00396     // ***********************
00397     // Read acis records...
00398     // ***********************
00399     std::string sat_file_name;
00400     if( MB_SUCCESS != opts.get_str_option( "SAT_FILE", sat_file_name ) ) sat_file_name.clear();
00401     result = read_acis_records( sat_file_name.empty() ? NULL : sat_file_name.c_str() );RR;
00402 
00403     // ***********************
00404     // Read groups...
00405     // ***********************
00406     if( debug ) std::cout << "Reading groups... ";
00407     for( unsigned int grindex = 0; grindex < mesh_model->feModelHeader.groupArray.numEntities; grindex++ )
00408     {
00409         GroupHeader* group_header = &mesh_model->feGroupH[grindex];
00410         result                    = read_group( grindex, mesh_model, group_header );
00411         if( MB_SUCCESS != result ) return result;
00412     }
00413     if( debug ) std::cout << mesh_model->feModelHeader.groupArray.numEntities << " read successfully." << std::endl;
00414 
00415     // ***********************
00416     // Read blocks...
00417     // ***********************
00418     if( debug ) std::cout << "Reading blocks... ";
00419     Range ho_entities;
00420     for( unsigned int blindex = 0; blindex < mesh_model->feModelHeader.blockArray.numEntities; blindex++ )
00421     {
00422         BlockHeader* block_header = &mesh_model->feBlockH[blindex];
00423         result                    = read_block( blindex, data_version, mesh_model, block_header );
00424         if( MB_SUCCESS != result ) return result;
00425     }
00426 
00427     if( debug ) std::cout << mesh_model->feModelHeader.blockArray.numEntities << " read successfully." << std::endl;
00428 
00429     // ***********************
00430     // Read nodesets...
00431     // ***********************
00432     if( debug ) std::cout << "Reading nodesets... ";
00433     for( unsigned int nsindex = 0; nsindex < mesh_model->feModelHeader.nodesetArray.numEntities; nsindex++ )
00434     {
00435         NodesetHeader* nodeset_header = &mesh_model->feNodeSetH[nsindex];
00436         result                        = read_nodeset( nsindex, mesh_model, nodeset_header );
00437         if( MB_SUCCESS != result ) return result;
00438     }
00439     if( debug ) std::cout << mesh_model->feModelHeader.nodesetArray.numEntities << " read successfully." << std::endl;
00440 
00441     // ***********************
00442     // Read sidesets...
00443     // ***********************
00444     if( debug ) std::cout << "Reading sidesets...";
00445     for( unsigned int ssindex = 0; ssindex < mesh_model->feModelHeader.sidesetArray.numEntities; ssindex++ )
00446     {
00447         SidesetHeader* sideset_header = &mesh_model->feSideSetH[ssindex];
00448         result                        = read_sideset( ssindex, data_version, mesh_model, sideset_header );
00449         if( MB_SUCCESS != result ) return result;
00450     }
00451     if( debug ) std::cout << mesh_model->feModelHeader.sidesetArray.numEntities << " read successfully." << std::endl;
00452 
00453     if( debug )
00454     {
00455         std::cout << "Read the following mesh:" << std::endl;
00456         mdbImpl->list_entities( 0, 0 );
00457     }
00458 
00459     // Convert blocks to nodesets/sidesets if tag is set
00460     result = convert_nodesets_sidesets();
00461     if( MB_SUCCESS != result ) return result;
00462 
00463     Range after_ents;
00464     result = mdbImpl->get_entities_by_handle( 0, after_ents );
00465     if( MB_SUCCESS != result ) return result;
00466 
00467     after_ents = subtract( after_ents, beforeEnts );
00468 
00469     if( file_id_tag ) readUtilIface->assign_ids( *file_id_tag, after_ents );
00470 
00471     if( MB_SUCCESS != opts.get_null_option( "SKIP_TOPOLOGY" ) )
00472     {
00473         // **************************
00474         // Restore geometric topology
00475         // **************************
00476         GeomTopoTool gtt( mdbImpl, true, 0, true, false );
00477         result = gtt.restore_topology_from_adjacency();
00478         if( MB_SUCCESS != result )
00479         {
00480             std::cout << "Failed to restore topology " << std::endl;
00481         }
00482     }
00483 
00484     // done with the cubit file
00485     fclose( cubFile );
00486     return result;
00487 }
00488 
00489 ErrorCode Tqdcfr::convert_nodesets_sidesets()
00490 {
00491     // Look first for the nodeset and sideset offset flags; if they're not
00492     // set, we don't need to convert
00493     const EntityHandle msh = 0;
00494     unsigned int nodeset_offset, sideset_offset;
00495     Tag tmp_tag;
00496     ErrorCode result = mdbImpl->tag_get_handle( BLOCK_NODESET_OFFSET_TAG_NAME, 1, MB_TYPE_INTEGER, tmp_tag );
00497     if( MB_SUCCESS != result )
00498         nodeset_offset = 0;
00499     else
00500     {
00501         result = mdbImpl->tag_get_data( tmp_tag, &msh, 1, &nodeset_offset );
00502         if( MB_SUCCESS != result ) return result;
00503     }
00504 
00505     result = mdbImpl->tag_get_handle( BLOCK_SIDESET_OFFSET_TAG_NAME, 1, MB_TYPE_INTEGER, tmp_tag );
00506     if( MB_SUCCESS != result )
00507         sideset_offset = 0;
00508     else
00509     {
00510         result = mdbImpl->tag_get_data( tmp_tag, &msh, 1, &sideset_offset );
00511         if( MB_SUCCESS != result ) return result;
00512     }
00513 
00514     if( 0 == nodeset_offset && 0 == sideset_offset ) return MB_SUCCESS;
00515 
00516     // Look for all blocks
00517     Range blocks;
00518     result = mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &blockTag, NULL, 1, blocks );
00519     if( MB_SUCCESS != result || blocks.empty() ) return result;
00520 
00521     // Get the id tag for them
00522     std::vector< int > block_ids( blocks.size() );
00523     result = mdbImpl->tag_get_data( globalIdTag, blocks, &block_ids[0] );
00524     if( MB_SUCCESS != result ) return result;
00525 
00526     unsigned int i      = 0;
00527     Range::iterator rit = blocks.begin();
00528     Range new_nodesets, new_sidesets;
00529     std::vector< int > new_nodeset_ids, new_sideset_ids;
00530     for( ; rit != blocks.end(); i++, ++rit )
00531     {
00532         if( 0 != nodeset_offset && block_ids[i] >= (int)nodeset_offset &&
00533             ( nodeset_offset > sideset_offset || block_ids[i] < (int)sideset_offset ) )
00534         {
00535             // This is a nodeset
00536             new_nodesets.insert( *rit );
00537             new_nodeset_ids.push_back( block_ids[i] );
00538         }
00539         else if( 0 != sideset_offset && block_ids[i] >= (int)sideset_offset &&
00540                  ( sideset_offset > nodeset_offset || block_ids[i] < (int)nodeset_offset ) )
00541         {
00542             // This is a sideset
00543             new_sidesets.insert( *rit );
00544             new_sideset_ids.push_back( block_ids[i] );
00545         }
00546     }
00547 
00548     // OK, have the new nodesets and sidesets; now remove the block tags, and
00549     // add nodeset and sideset tags
00550     ErrorCode tmp_result = MB_SUCCESS;
00551     if( 0 != nodeset_offset )
00552     {
00553         if( 0 == nsTag )
00554         {
00555             int default_val = 0;
00556             tmp_result      = mdbImpl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, nsTag,
00557                                                        MB_TAG_SPARSE | MB_TAG_CREAT, &default_val );
00558             if( MB_SUCCESS != tmp_result ) result = tmp_result;
00559         }
00560         if( MB_SUCCESS == tmp_result ) tmp_result = mdbImpl->tag_set_data( nsTag, new_nodesets, &new_nodeset_ids[0] );
00561         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00562         tmp_result = mdbImpl->tag_delete_data( blockTag, new_nodesets );
00563         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00564     }
00565     if( 0 != sideset_offset )
00566     {
00567         if( 0 == ssTag )
00568         {
00569             int default_val = 0;
00570             tmp_result      = mdbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ssTag,
00571                                                        MB_TAG_SPARSE | MB_TAG_CREAT, &default_val );
00572             if( MB_SUCCESS != tmp_result ) result = tmp_result;
00573         }
00574         if( MB_SUCCESS == tmp_result ) tmp_result = mdbImpl->tag_set_data( ssTag, new_sidesets, &new_sideset_ids[0] );
00575         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00576         tmp_result = mdbImpl->tag_delete_data( blockTag, new_sidesets );
00577         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00578     }
00579 
00580     return result;
00581 }
00582 
00583 ErrorCode Tqdcfr::read_nodeset( const unsigned int nsindex, Tqdcfr::ModelEntry* model, Tqdcfr::NodesetHeader* nodeseth )
00584 {
00585     if( nodeseth->memTypeCt == 0 ) return MB_SUCCESS;
00586 
00587     // Position file
00588     FSEEK( model->modelOffset + nodeseth->memOffset );
00589 
00590     // Read ids for each entity type
00591     unsigned int this_type, num_ents;  //, uid;
00592     std::vector< char > bc_data;
00593     unsigned int num_read = 0;
00594     std::vector< EntityHandle > ns_entities, excl_entities;
00595     for( unsigned int i = 0; i < nodeseth->memTypeCt; i++ )
00596     {
00597         // Get how many and what type
00598         FREADI( 2 );
00599         num_read += 2 * sizeof( int );
00600         this_type = uint_buf[0];
00601         num_ents  = uint_buf[1];
00602 
00603         // Now get the ids
00604         FREADI( num_ents );
00605         num_read += sizeof( int );
00606         CONVERT_TO_INTS( num_ents );
00607 
00608         ErrorCode result = get_entities( this_type + 2, &int_buf[0], num_ents, ns_entities, excl_entities );
00609         if( MB_SUCCESS != result ) return result;
00610     }
00611     // Check for more data
00612     if( num_read < nodeseth->nsLength )
00613     {
00614         FREADC( 2 );  // num_read += 2;
00615         if( char_buf[0] == 'i' && char_buf[1] == 'd' )
00616         {
00617             FREADI( 1 );  // num_read += sizeof(int);
00618             // uid = int_buf[0];
00619         }
00620         else
00621         {
00622             if( char_buf[0] == 'b' && char_buf[1] == 'c' )
00623             {
00624                 FREADI( 1 );  // num_read += sizeof(int);
00625                 int num_bcs = uint_buf[0];
00626                 bc_data.resize( num_bcs );
00627                 FREADCA( num_bcs, &bc_data[0] );  // num_read += num_bcs;
00628             }
00629         }
00630     }
00631 
00632     if( debug )
00633     {
00634         nodeseth->print();
00635         if( !bc_data.empty() )
00636         {
00637             std::cout << "bc_data = ";
00638             std::vector< char >::iterator vit = bc_data.begin();
00639             for( ; vit != bc_data.end(); ++vit )
00640             {
00641                 std::cout << std::hex << (int)( (unsigned char)*vit ) << " ";
00642             }
00643             std::cout << ": ";
00644             vit = bc_data.begin();
00645             for( ; vit != bc_data.end(); ++vit )
00646             {
00647                 std::cout << *vit;
00648             }
00649             std::cout << std::endl;
00650         }
00651     }
00652 
00653     // And put entities into this nodeset's set
00654     ErrorCode result = put_into_set( nodeseth->setHandle, ns_entities, excl_entities );
00655     if( MB_SUCCESS != result ) return result;
00656 
00657     result = get_names( model->nodesetMD, nsindex, nodeseth->setHandle );
00658     if( MB_SUCCESS != result ) return result;
00659 
00660     const int def_bc_data_len = 0;
00661     std::string tag_name      = std::string( DIRICHLET_SET_TAG_NAME ) + "__BC_DATA";
00662     Tag nbc_data;
00663     result = mdbImpl->tag_get_handle( tag_name.c_str(), def_bc_data_len, MB_TYPE_OPAQUE, nbc_data,
00664                                       MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_VARLEN, NULL );
00665     if( MB_SUCCESS != result ) return result;
00666     void const* tag_data[] = { ( bc_data.empty() ) ? NULL : &( bc_data[0] ) };
00667     int tag_size           = bc_data.size();
00668     result                 = mdbImpl->tag_set_by_ptr( nbc_data, &nodeseth->setHandle, 1, tag_data, &tag_size );
00669     if( MB_SUCCESS != result ) return result;
00670 
00671     return result;
00672 }
00673 
00674 ErrorCode Tqdcfr::read_sideset( const unsigned int ssindex,
00675                                 const double data_version,
00676                                 Tqdcfr::ModelEntry* model,
00677                                 Tqdcfr::SidesetHeader* sideseth )
00678 {
00679     if( sideseth->memCt == 0 ) return MB_SUCCESS;
00680 
00681     ErrorCode result;
00682 
00683     // Position file
00684     FSEEK( model->modelOffset + sideseth->memOffset );
00685 
00686     // Read ids for each entity type
00687     unsigned int this_type, num_ents, sense_size;
00688 
00689     std::vector< char > bc_data;
00690     unsigned int num_read = 0;  //, uid;
00691     std::vector< EntityHandle > ss_entities, excl_entities;
00692     if( data_version <= 1.0 )
00693     {
00694         for( unsigned int i = 0; i < sideseth->memTypeCt; i++ )
00695         {
00696             // Get how many and what type
00697             FREADI( 3 );
00698             num_read += 3 * sizeof( int );
00699             this_type  = uint_buf[0];
00700             num_ents   = uint_buf[1];
00701             sense_size = uint_buf[2];
00702 
00703             // Now get the ids
00704             FREADI( num_ents );
00705             num_read += sizeof( int );
00706             CONVERT_TO_INTS( num_ents );
00707 
00708             result = get_entities( this_type + 2, &int_buf[0], num_ents, ss_entities, excl_entities );
00709             if( MB_SUCCESS != result ) return result;
00710 
00711             if( sense_size == 1 )
00712             {
00713                 // Byte-size sense flags; make sure read ends aligned...
00714                 unsigned int read_length = ( num_ents / 8 ) * 8;
00715                 if( read_length < num_ents ) read_length += 8;
00716                 FREADC( read_length );
00717                 num_read += read_length;
00718             }
00719             else if( sense_size == 2 )
00720             {
00721                 // Int-size sense flags
00722                 FREADI( num_ents );
00723                 num_read += sizeof( int );
00724             }
00725 
00726             // Now do something with them...
00727             process_sideset_10( this_type, num_ents, sense_size, ss_entities, sideseth );
00728         }
00729     }
00730     else
00731     {
00732         for( unsigned int i = 0; i < sideseth->memTypeCt; i++ )
00733         {
00734             // Get how many and what type
00735             FREADI( 1 );
00736             num_read += sizeof( int );
00737             num_ents = uint_buf[0];
00738 
00739             // Get the types, and ids
00740             std::vector< unsigned int > mem_types( num_ents ), mem_ids( num_ents );
00741             FREADIA( num_ents, &mem_types[0] );
00742             num_read += num_ents * sizeof( int );
00743             FREADI( num_ents );
00744             num_read += sizeof( int );
00745 
00746             result = get_entities( &mem_types[0], &int_buf[0], num_ents, false, ss_entities );
00747             if( MB_SUCCESS != result ) return result;
00748 
00749             // Byte-size sense flags; make sure read ends aligned...
00750             unsigned int read_length = ( num_ents / 8 ) * 8;
00751             if( read_length < num_ents ) read_length += 8;
00752             FREADC( read_length );
00753             num_read += read_length;
00754 
00755             // wrt entities
00756             FREADI( 1 );
00757             num_read += sizeof( int );
00758             int num_wrts = uint_buf[0];
00759             FREADI( num_wrts );
00760             num_read += num_wrts * sizeof( int );
00761 
00762             result = process_sideset_11( ss_entities, num_wrts, sideseth );
00763             if( MB_SUCCESS != result ) return result;
00764         }
00765     }
00766 
00767     // Now set the dist factors
00768     if( sideseth->numDF > 0 )
00769     {
00770         // Have to read dist factors
00771         FREADD( sideseth->numDF );
00772         num_read += sideseth->numDF * sizeof( double );
00773         Tag distFactorTag;
00774         result = mdbImpl->tag_get_handle( "distFactor", 0, MB_TYPE_DOUBLE, distFactorTag,
00775                                           MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_CREAT );
00776         if( MB_SUCCESS != result ) return result;
00777         const void* dist_data = &dbl_buf[0];
00778         const int dist_size   = sideseth->numDF;
00779         result = mdbImpl->tag_set_by_ptr( distFactorTag, &sideseth->setHandle, 1, &dist_data, &dist_size );
00780         if( MB_SUCCESS != result ) return result;
00781     }
00782 
00783     // Check for more data
00784     if( data_version > 1.0 && num_read < sideseth->ssLength )
00785     {
00786         FREADC( 2 );  // num_read += 2;
00787         if( char_buf[0] == 'i' && char_buf[1] == 'd' )
00788         {
00789             FREADI( 1 );  // num_read += sizeof(int);
00790             // uid = int_buf[0];
00791         }
00792         else
00793         {
00794             // Check for bc_data
00795             if( char_buf[0] == 'b' && char_buf[1] == 'c' )
00796             {
00797                 FREADI( 1 );  // num_read += sizeof(int);
00798                 int num_bcs = uint_buf[0];
00799                 bc_data.resize( num_bcs );
00800                 FREADCA( num_bcs, &bc_data[0] );  // num_read += num_bcs;
00801             }
00802         }
00803     }
00804 
00805     if( debug )
00806     {
00807         sideseth->print();
00808         if( !bc_data.empty() )
00809         {
00810             std::cout << "bc_data = ";
00811             std::vector< char >::iterator vit = bc_data.begin();
00812             for( ; vit != bc_data.end(); ++vit )
00813             {
00814                 std::cout << std::hex << (int)( (unsigned char)*vit ) << " ";
00815             }
00816             std::cout << ": ";
00817             vit = bc_data.begin();
00818             for( ; vit != bc_data.end(); ++vit )
00819             {
00820                 std::cout << *vit;
00821             }
00822             std::cout << std::endl;
00823         }
00824     }
00825 
00826     result = get_names( model->sidesetMD, ssindex, sideseth->setHandle );
00827     if( MB_SUCCESS != result ) return result;
00828 
00829     const int def_bc_data_len = 0;
00830     std::string tag_name      = std::string( NEUMANN_SET_TAG_NAME ) + "__BC_DATA";
00831     Tag nbc_data;
00832     result = mdbImpl->tag_get_handle( tag_name.c_str(), def_bc_data_len, MB_TYPE_OPAQUE, nbc_data,
00833                                       MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_VARLEN, NULL );
00834     if( MB_SUCCESS != result ) return result;
00835     void const* tag_data[] = { ( bc_data.empty() ) ? NULL : &( bc_data[0] ) };
00836     int tag_size           = bc_data.size();
00837     result                 = mdbImpl->tag_set_by_ptr( nbc_data, &sideseth->setHandle, 1, tag_data, &tag_size );
00838     if( MB_SUCCESS != result ) return result;
00839 
00840     return MB_SUCCESS;
00841 }
00842 
00843 ErrorCode Tqdcfr::process_sideset_10( const int this_type,
00844                                       const int num_ents,
00845                                       const int sense_size,
00846                                       std::vector< EntityHandle >& ss_entities,
00847                                       Tqdcfr::SidesetHeader* sideseth )
00848 {
00849     std::vector< EntityHandle > forward, reverse;
00850     if( this_type == 3      // Surface
00851         && sense_size == 1  // Byte size
00852     )
00853     {
00854         // Interpret sense flags w/o reference to anything
00855         for( int i = 0; i < num_ents; i++ )
00856         {
00857             if( (int)char_buf[i] == 0 )
00858                 forward.push_back( ss_entities[i] );
00859             else if( (int)char_buf[i] == 1 )
00860                 reverse.push_back( ss_entities[i] );
00861             else if( (int)char_buf[i] == -1 )
00862             {  // -1 means "unknown", which means both
00863                 forward.push_back( ss_entities[i] );
00864                 reverse.push_back( ss_entities[i] );
00865             }
00866         }
00867     }
00868     else if( this_type == 4      // Curve
00869              && sense_size == 2  // int32 size
00870     )
00871     {
00872         for( int i = 0; i < num_ents; i++ )
00873         {
00874             if( uint_buf[i] == 0 )
00875                 forward.push_back( ss_entities[i] );
00876             else if( uint_buf[i] == 1 )
00877                 reverse.push_back( ss_entities[i] );
00878             else if( *( (int*)&uint_buf[i] ) == -1 )
00879             {  // -1 means "unknown", which means both
00880                 forward.push_back( ss_entities[i] );
00881                 reverse.push_back( ss_entities[i] );
00882             }
00883         }
00884     }
00885 
00886     // Now actually put them in the set
00887     ErrorCode result = MB_SUCCESS;
00888     if( !forward.empty() )
00889     {
00890         ErrorCode tmp_result = mdbImpl->add_entities( sideseth->setHandle, &forward[0], forward.size() );
00891         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00892     }
00893     if( !reverse.empty() )
00894     {
00895         // Need to make a new set, add a reverse sense tag, then add to the sideset
00896         EntityHandle reverse_set;
00897         ErrorCode tmp_result = create_set( reverse_set );
00898         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00899         tmp_result = mdbImpl->add_entities( reverse_set, &reverse[0], reverse.size() );
00900         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00901         int def_val = 1;
00902         Tag sense_tag;
00903         tmp_result = mdbImpl->tag_get_handle( "NEUSET_SENSE", 1, MB_TYPE_INTEGER, sense_tag,
00904                                               MB_TAG_SPARSE | MB_TAG_CREAT, &def_val );
00905         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00906         def_val    = -1;
00907         tmp_result = mdbImpl->tag_set_data( sense_tag, &reverse_set, 1, &def_val );
00908         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00909         tmp_result = mdbImpl->add_entities( sideseth->setHandle, &reverse_set, 1 );
00910         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00911     }
00912 
00913     return result;
00914 }
00915 
00916 ErrorCode Tqdcfr::process_sideset_11( std::vector< EntityHandle >& ss_entities,
00917                                       int num_wrts,
00918                                       Tqdcfr::SidesetHeader* sideseth )
00919 {
00920     std::vector< EntityHandle > forward, reverse;
00921 
00922     unsigned int num_ents = ss_entities.size();
00923     unsigned int* wrt_it  = &uint_buf[0];
00924 
00925     for( unsigned int i = 0; i < num_ents; i++ )
00926     {
00927         unsigned int num_wrt = 0;
00928         if( 0 != num_wrts ) num_wrt = *wrt_it++;
00929         for( unsigned int j = 0; j < num_wrt; j++ )
00930             wrt_it += 2;
00931         // Assume here that if it's in the list twice, we get both senses
00932         if( num_wrt > 1 )
00933         {
00934             forward.push_back( ss_entities[i] );
00935             reverse.push_back( ss_entities[i] );
00936         }
00937         else
00938         {
00939             // Else interpret the sense flag
00940             if( (int)char_buf[i] == 0 )
00941                 forward.push_back( ss_entities[i] );
00942             else if( (int)char_buf[i] == 1 )
00943                 reverse.push_back( ss_entities[i] );
00944             else if( (int)char_buf[i] == -1 )
00945             {  // -1 means "unknown", which means both
00946                 forward.push_back( ss_entities[i] );
00947                 reverse.push_back( ss_entities[i] );
00948             }
00949         }
00950     }
00951 
00952     // Now actually put them in the set
00953     ErrorCode result = MB_SUCCESS;
00954     if( !forward.empty() )
00955     {
00956         ErrorCode tmp_result = mdbImpl->add_entities( sideseth->setHandle, &forward[0], forward.size() );
00957         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00958     }
00959     if( !reverse.empty() )
00960     {
00961         // Need to make a new set, add a reverse sense tag, then add to the sideset
00962         EntityHandle reverse_set;
00963         ErrorCode tmp_result = create_set( reverse_set );
00964         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00965         tmp_result = mdbImpl->add_entities( reverse_set, &reverse[0], reverse.size() );
00966         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00967         int def_val = 1;
00968         Tag sense_tag;
00969         tmp_result = mdbImpl->tag_get_handle( "NEUSET_SENSE", 1, MB_TYPE_INTEGER, sense_tag,
00970                                               MB_TAG_SPARSE | MB_TAG_CREAT, &def_val );
00971         if( tmp_result != MB_SUCCESS && tmp_result != MB_ALREADY_ALLOCATED ) result = tmp_result;
00972         def_val    = -1;
00973         tmp_result = mdbImpl->tag_set_data( sense_tag, &reverse_set, 1, &def_val );
00974         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00975         tmp_result = mdbImpl->add_entities( sideseth->setHandle, &reverse_set, 1 );
00976         if( tmp_result != MB_SUCCESS ) result = tmp_result;
00977     }
00978 
00979     return result;
00980 }
00981 
00982 ErrorCode Tqdcfr::read_block( const unsigned int blindex,
00983                               const double /*data_version*/,
00984                               Tqdcfr::ModelEntry* model,
00985                               Tqdcfr::BlockHeader* blockh )
00986 {
00987     if( blockh->memCt == 0 ) return MB_SUCCESS;
00988 
00989     // Position file
00990     FSEEK( model->modelOffset + blockh->memOffset );
00991 
00992     // Read ids for each entity type
00993     unsigned int num_read = 0;
00994     int this_type, num_ents;  //, uid;
00995     std::vector< EntityHandle > block_entities, excl_entities;
00996     for( unsigned int i = 0; i < blockh->memTypeCt; i++ )
00997     {
00998         // Get how many and what type
00999         FREADI( 2 );
01000         num_read += 2 * sizeof( int );
01001         this_type = uint_buf[0];
01002         num_ents  = uint_buf[1];
01003 
01004         // Now get the ids
01005         FREADI( num_ents );
01006         num_read += num_ents * sizeof( int );
01007         CONVERT_TO_INTS( num_ents );
01008 
01009         ErrorCode result = get_entities( this_type + 2, &int_buf[0], num_ents, block_entities, excl_entities );
01010         if( MB_SUCCESS != result ) return result;
01011     }
01012 
01013     // And put entities into this block's set
01014     ErrorCode result = put_into_set( blockh->setHandle, block_entities, excl_entities );
01015     if( MB_SUCCESS != result ) return result;
01016 
01017     // Read attribs if there are any
01018     Tag block_attribs;
01019     {
01020         int def_block_attributes_length = 0;
01021         result = mdbImpl->tag_get_handle( BLOCK_ATTRIBUTES, def_block_attributes_length, MB_TYPE_DOUBLE, block_attribs,
01022                                           MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN, NULL );
01023         if( MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result ) return result;
01024     }
01025 
01026     if( blockh->attribOrder > 0 )
01027     {
01028         FREADD( blockh->attribOrder );
01029         num_read += sizeof( double );
01030         void const* tag_data[] = { &dbl_buf[0] };
01031         int tag_sizes[]        = { static_cast< int >( blockh->attribOrder ) };
01032         result = mdbImpl->tag_set_by_ptr( block_attribs, &( blockh->setHandle ), 1, tag_data, tag_sizes );
01033         if( MB_SUCCESS != result ) return result;
01034     }
01035 
01036     // Check for more data
01037     if( num_read < blockh->blockLength )
01038     {
01039         FREADC( 2 );  // num_read += 2;
01040         if( char_buf[0] == 'i' && char_buf[1] == 'd' )
01041         {
01042             FREADI( 1 );  // num_read += sizeof(int);
01043             // uid = int_buf[0];
01044         }
01045     }
01046 
01047     result = get_names( model->blockMD, blindex, blockh->setHandle );
01048     if( MB_SUCCESS != result ) return result;
01049 
01050     // Put additional higher-order nodes into element connectivity list.
01051     // Cubit saves full connectivity list only for NodeHex and NodeTet
01052     // elements. Other element types will only have the corners and
01053     // the mid-element node if there is one. Need to reconstruct additional
01054     // connectivity entries from mid-nodes of adjacent lower-order entities.
01055     int node_per_elem = cub_elem_num_verts[blockh->blockElemType];
01056     if( blockh->blockEntityType == MBMAXTYPE ) return MB_SUCCESS;
01057     if( ( 14 == major && 2 < minor ) || 15 <= major )
01058     {
01059         if( 55 == blockh->blockElemType || CN::VerticesPerEntity( blockh->blockEntityType ) == node_per_elem )
01060             return MB_SUCCESS;
01061     }
01062     else
01063     {
01064         if( 52 == blockh->blockElemType || CN::VerticesPerEntity( blockh->blockEntityType ) == node_per_elem )
01065             return MB_SUCCESS;
01066     }
01067 
01068     // Can't use Interface::convert_entities because block could contain
01069     // both entity sets and entities. convert_entities will fail if block
01070     // contains an entity set, but we still need to call it on any elements
01071     // directly in the block (rather than a geometry subset). So bypass
01072     // Interface and call HOFactory directly with an Range of entities.
01073     Range ho_entities, entities;
01074     mdbImpl->get_entities_by_type( blockh->setHandle, blockh->blockEntityType, entities, true );
01075     if( CN::Dimension( blockh->blockEntityType ) > 2 )
01076     {
01077         result = mdbImpl->get_adjacencies( entities, 2, false, ho_entities, Interface::UNION );
01078         if( MB_SUCCESS != result ) return result;
01079     }
01080     if( CN::Dimension( blockh->blockEntityType ) > 1 )
01081     {
01082         result = mdbImpl->get_adjacencies( entities, 1, false, ho_entities, Interface::UNION );
01083         if( MB_SUCCESS != result ) return result;
01084     }
01085     entities.merge( ho_entities );
01086 
01087     Core* mbcore = dynamic_cast< Core* >( mdbImpl );
01088     assert( mbcore != NULL );
01089     HigherOrderFactory ho_fact( mbcore, 0 );
01090     return ho_fact.convert( entities, !!blockh->hasMidNodes[1], !!blockh->hasMidNodes[2], !!blockh->hasMidNodes[3] );
01091 }
01092 
01093 ErrorCode Tqdcfr::get_names( MetaDataContainer& md, unsigned int set_index, EntityHandle seth )
01094 {
01095     ErrorCode result = MB_SUCCESS;
01096 
01097     // Now get block names, if any
01098     int md_index = md.get_md_entry( set_index, "Name" );
01099     if( -1 == md_index ) return result;
01100     MetaDataContainer::MetaDataEntry* md_entry = &( md.metadataEntries[md_index] );
01101     // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
01102     char name_tag_data[NAME_TAG_SIZE];
01103     memset( name_tag_data, 0, NAME_TAG_SIZE );  // Make sure any extra bytes zeroed
01104     strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
01105     result = mdbImpl->tag_set_data( entityNameTag, &seth, 1, name_tag_data );
01106     if( MB_SUCCESS != result ) return result;
01107 
01108     // Look for extra names
01109     md_index = md.get_md_entry( set_index, "NumExtraNames" );
01110     if( -1 == md_index ) return result;
01111     int num_names = md.metadataEntries[md_index].mdIntValue;
01112     for( int i = 0; i < num_names; i++ )
01113     {
01114         std::ostringstream extra_name_label( "ExtraName" );
01115         extra_name_label << i;
01116         std::ostringstream moab_extra_name( "EXTRA_" );
01117         moab_extra_name << NAME_TAG_NAME << i;
01118         md_index = md.get_md_entry( set_index, extra_name_label.str().c_str() );
01119         if( -1 != md_index )
01120         {
01121             md_entry = &( md.metadataEntries[md_index] );
01122             Tag extra_name_tag;
01123             ErrorCode rval;
01124             rval = mdbImpl->tag_get_handle( moab_extra_name.str().c_str(), NAME_TAG_SIZE, MB_TYPE_OPAQUE,
01125                                             extra_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
01126             memset( name_tag_data, 0, NAME_TAG_SIZE );  // Make sure any extra bytes zeroed
01127             strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
01128             result = mdbImpl->tag_set_data( extra_name_tag, &seth, 1, name_tag_data );
01129         }
01130     }
01131 
01132     return result;
01133 }
01134 
01135 ErrorCode Tqdcfr::read_group( const unsigned int group_index, Tqdcfr::ModelEntry* model, Tqdcfr::GroupHeader* grouph )
01136 {
01137     // Position file
01138     FSEEK( model->modelOffset + grouph->memOffset );
01139     char name_tag_data[NAME_TAG_SIZE];
01140 
01141     // Read ids for each entity type
01142     int this_type, num_ents;
01143     std::vector< EntityHandle > grp_entities, excl_entities;
01144     for( unsigned int i = 0; i < grouph->memTypeCt; i++ )
01145     {
01146         // Get how many and what type
01147         FREADI( 2 );
01148         this_type = uint_buf[0];
01149         num_ents  = uint_buf[1];
01150 
01151         // Now get the ids
01152         FREADI( num_ents );
01153         CONVERT_TO_INTS( num_ents );
01154 
01155         // Get the entities in this group
01156         ErrorCode result = get_entities( this_type, &int_buf[0], num_ents, grp_entities, excl_entities );
01157         if( MB_SUCCESS != result ) return result;
01158     }
01159 
01160     // Now add the entities
01161     ErrorCode result = put_into_set( grouph->setHandle, grp_entities, excl_entities );
01162     if( MB_SUCCESS != result ) return result;
01163 
01164     // Now get group names, if any
01165     int md_index = model->groupMD.get_md_entry( grouph->grpID, "NAME" );
01166     if( -1 != md_index )
01167     {
01168         MetaDataContainer::MetaDataEntry* md_entry = &( model->groupMD.metadataEntries[md_index] );
01169         if( 0 == entityNameTag )
01170         {
01171             memset( name_tag_data, 0, NAME_TAG_SIZE );
01172             result = mdbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, entityNameTag,
01173                                               MB_TAG_SPARSE | MB_TAG_CREAT, name_tag_data );
01174             if( MB_SUCCESS != result ) return result;
01175         }
01176         // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
01177         memset( name_tag_data, 0, NAME_TAG_SIZE );  // Make sure any extra bytes zeroed
01178         strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
01179         result = mdbImpl->tag_set_data( entityNameTag, &grouph->setHandle, 1, name_tag_data );
01180         if( MB_SUCCESS != result ) return result;
01181 
01182         // Look for extra names
01183         md_index = model->groupMD.get_md_entry( group_index, "NumExtraNames" );
01184         if( -1 != md_index )
01185         {
01186             int num_names = model->groupMD.metadataEntries[md_index].mdIntValue;
01187             for( int i = 0; i < num_names; i++ )
01188             {
01189                 std::ostringstream extra_name_label( "ExtraName" );
01190                 extra_name_label << i;
01191                 std::ostringstream moab_extra_name( "EXTRA_" );
01192                 moab_extra_name << NAME_TAG_NAME << i;
01193                 md_index = model->groupMD.get_md_entry( group_index, extra_name_label.str().c_str() );
01194                 if( -1 != md_index )
01195                 {
01196                     md_entry = &( model->groupMD.metadataEntries[md_index] );
01197                     Tag extra_name_tag;
01198                     memset( name_tag_data, 0, NAME_TAG_SIZE );
01199                     result = mdbImpl->tag_get_handle( moab_extra_name.str().c_str(), NAME_TAG_SIZE, MB_TYPE_OPAQUE,
01200                                                       extra_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT, name_tag_data );
01201                     if( MB_SUCCESS != result ) return result;
01202                     // assert(md_entry->mdStringValue.length() + 1 <= NAME_TAG_SIZE);
01203                     memset( name_tag_data, 0, NAME_TAG_SIZE );  // Make sure any extra bytes zeroed
01204                     strncpy( name_tag_data, md_entry->mdStringValue.c_str(), NAME_TAG_SIZE - 1 );
01205                     result = mdbImpl->tag_set_data( extra_name_tag, &grouph->setHandle, 1, name_tag_data );
01206                 }
01207             }
01208         }
01209     }
01210 
01211     return result;
01212 }
01213 
01214 ErrorCode Tqdcfr::put_into_set( EntityHandle set_handle,
01215                                 std::vector< EntityHandle >& entities,
01216                                 std::vector< EntityHandle >& excl_entities )
01217 {
01218     // And put entities into this block's set
01219     ErrorCode result = mdbImpl->add_entities( set_handle, &entities[0], entities.size() );
01220     if( MB_SUCCESS != result ) return result;
01221 
01222     // Check for excluded entities, and add them to a vector hung off the block if there
01223     Tag excl_tag;
01224     if( !excl_entities.empty() )
01225     {
01226         result = mdbImpl->tag_get_handle( "Exclude_Entities", sizeof( std::vector< EntityHandle >* ), MB_TYPE_OPAQUE,
01227                                           excl_tag, MB_TAG_SPARSE | MB_TAG_CREAT );
01228         if( MB_SUCCESS != result ) return result;
01229         std::vector< EntityHandle >* new_vector = new std::vector< EntityHandle >;
01230         new_vector->swap( excl_entities );
01231         result = mdbImpl->tag_set_data( excl_tag, &set_handle, 1, &new_vector );
01232         if( MB_SUCCESS != result )
01233         {
01234             delete new_vector;
01235             return MB_FAILURE;
01236         }
01237     }
01238 
01239     return MB_SUCCESS;
01240 }
01241 
01242 ErrorCode Tqdcfr::get_entities( const unsigned int* mem_types,
01243                                 int* id_buf,
01244                                 const unsigned int id_buf_size,
01245                                 const bool is_group,
01246                                 std::vector< EntityHandle >& entities )
01247 {
01248     ErrorCode tmp_result, result = MB_SUCCESS;
01249 
01250     for( unsigned int i = 0; i < id_buf_size; i++ )
01251     {
01252         if( is_group )
01253             tmp_result = get_entities( mem_types[i], id_buf + i, 1, entities, entities );
01254         else
01255             // For blocks/nodesets/sidesets, use CSOEntityType, which is 2 greater than
01256             // group entity types
01257             tmp_result = get_entities( mem_types[i] + 2, id_buf + i, 1, entities, entities );
01258         if( MB_SUCCESS != tmp_result ) result = tmp_result;
01259     }
01260 
01261     return result;
01262 }
01263 
01264 ErrorCode Tqdcfr::get_entities( const unsigned int this_type,
01265                                 int* id_buf,
01266                                 const unsigned int id_buf_size,
01267                                 std::vector< EntityHandle >& entities,
01268                                 std::vector< EntityHandle >& excl_entities )
01269 {
01270     ErrorCode result = MB_FAILURE;
01271 
01272     if( this_type <= VERTEX )
01273         result = get_ref_entities( this_type, id_buf, id_buf_size, entities );
01274     else if( this_type >= HEX && this_type <= NODE )
01275         result = get_mesh_entities( this_type, id_buf, id_buf_size, entities, excl_entities );
01276 
01277     return result;
01278 }
01279 
01280 ErrorCode Tqdcfr::get_ref_entities( const unsigned int this_type,
01281                                     int* id_buf,
01282                                     const unsigned int id_buf_size,
01283                                     std::vector< EntityHandle >& entities )
01284 {
01285     for( unsigned int i = 0; i < id_buf_size; i++ )
01286         entities.push_back( ( gidSetMap[5 - this_type] )[id_buf[i]] );
01287 
01288     return MB_SUCCESS;
01289 }
01290 
01291 ErrorCode Tqdcfr::get_mesh_entities( const unsigned int this_type,
01292                                      int* id_buf,
01293                                      const unsigned int id_buf_size,
01294                                      std::vector< EntityHandle >& entities,
01295                                      std::vector< EntityHandle >& excl_entities )
01296 {
01297     ErrorCode result                      = MB_SUCCESS;
01298     std::vector< EntityHandle >* ent_list = NULL;
01299     EntityType this_ent_type              = MBVERTEX;
01300     const unsigned int arr_len            = sizeof( group_type_to_mb_type ) / sizeof( group_type_to_mb_type[0] );
01301     if( this_type > 1000 )
01302     {
01303         if( this_type - 1000 < arr_len )
01304         {
01305             this_ent_type = group_type_to_mb_type[this_type - 1000];
01306             ent_list      = &excl_entities;
01307         }
01308     }
01309     else
01310     {
01311         if( this_type < arr_len )
01312         {
01313             this_ent_type = group_type_to_mb_type[this_type];
01314             ent_list      = &entities;
01315         }
01316     }
01317     if( NULL == ent_list )
01318     {
01319         MB_SET_ERR( MB_FAILURE, "Entities list is NULL" );
01320     }
01321 
01322     // Get entities with this type, and get their cub id tags
01323     if( MBVERTEX == this_ent_type )
01324     {
01325         // Use either vertex offset or cubMOABVertexMap
01326         if( NULL == cubMOABVertexMap )
01327         {
01328             for( unsigned int i = 0; i < id_buf_size; i++ )
01329                 ent_list->push_back( (EntityHandle)( id_buf[i] + currVHandleOffset ) );
01330         }
01331         else
01332         {
01333             for( unsigned int i = 0; i < id_buf_size; i++ )
01334             {
01335                 assert( 0 != ( *cubMOABVertexMap )[id_buf[i]] );
01336                 ent_list->push_back( ( *cubMOABVertexMap )[id_buf[i]] );
01337             }
01338         }
01339     }
01340     else
01341     {
01342         Range tmp_ents;
01343         result = mdbImpl->get_entities_by_type( 0, this_ent_type, tmp_ents );
01344         if( MB_SUCCESS != result ) return result;
01345         if( tmp_ents.empty() && 0 != id_buf_size ) return MB_FAILURE;
01346 
01347         std::vector< int > cub_ids( tmp_ents.size() );
01348         result = mdbImpl->tag_get_data( globalIdTag, tmp_ents, &cub_ids[0] );
01349         if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) return result;
01350 
01351         // Now go through id list, finding each entity by id
01352         for( unsigned int i = 0; i < id_buf_size; i++ )
01353         {
01354             std::vector< int >::iterator vit = std::find( cub_ids.begin(), cub_ids.end(), id_buf[i] );
01355             if( vit != cub_ids.end() )
01356             {
01357                 EntityHandle this_ent = tmp_ents[vit - cub_ids.begin()];
01358                 if( mdbImpl->type_from_handle( this_ent ) != MBMAXTYPE ) ent_list->push_back( this_ent );
01359             }
01360             else
01361             {
01362                 std::cout << "Warning: didn't find " << CN::EntityTypeName( this_ent_type ) << " " << id_buf[i]
01363                           << std::endl;
01364             }
01365         }
01366     }
01367 
01368     return result;
01369 }
01370 
01371 ErrorCode Tqdcfr::read_nodes( const unsigned int gindex, Tqdcfr::ModelEntry* model, Tqdcfr::GeomHeader* entity )
01372 {
01373     if( entity->nodeCt == 0 )
01374     {
01375         if( debug ) std::cout << "(no nodes) ";
01376         return MB_SUCCESS;
01377     }
01378 
01379     // Get the ids & coords in separate calls to minimize memory usage
01380     // Position the file
01381     FSEEK( model->modelOffset + entity->nodeOffset );
01382     // Get node ids in uint_buf
01383     FREADI( entity->nodeCt );
01384 
01385     if( debug )
01386     {
01387         std::cout << "(";
01388         for( unsigned int i = 0; i < entity->nodeCt; i++ )
01389         {
01390             std::cout << uint_buf[i];
01391             if( i != entity->nodeCt - 1 ) std::cout << ", ";
01392         }
01393         std::cout << ")...";
01394     }
01395 
01396     // Get a space for reading nodal data directly into MB, and read that data
01397     EntityHandle vhandle = 0;
01398     std::vector< double* > arrays;
01399     readUtilIface->get_node_coords( 3, entity->nodeCt, uint_buf[0], vhandle, arrays,
01400                                     SequenceManager::DEFAULT_VERTEX_SEQUENCE_SIZE );
01401 
01402     // Get node x's in arrays[0]
01403     FREADDA( entity->nodeCt, arrays[0] );
01404     // Get node y's in arrays[1]
01405     FREADDA( entity->nodeCt, arrays[1] );
01406     // Get node z's in arrays[2]
01407     FREADDA( entity->nodeCt, arrays[2] );
01408 
01409     // Add these nodes into the entity's set
01410     Range dum_range( vhandle, vhandle + entity->nodeCt - 1 );
01411     ErrorCode result = mdbImpl->add_entities( entity->setHandle, dum_range );
01412     if( MB_SUCCESS != result ) return result;
01413 
01414     // Check for id contiguity; know that cid's will never be > 32bit, so
01415     // ids can be unsigned int
01416     unsigned int max_cid, min_cid;
01417     int contig;
01418     check_contiguous( entity->nodeCt, contig, min_cid, max_cid );
01419 
01420     // Compute the offset we get in this batch and compare to any previous one
01421     long vhandle_offset = vhandle - min_cid;
01422     if( -1 == currVHandleOffset ) currVHandleOffset = vhandle_offset;
01423 
01424     // In 2 situations we'll need to add/modify a cubit_id -> vhandle map:
01425     // case A: no map yet, and either this offset different from
01426     // previous or not contiguous
01427     if( !cubMOABVertexMap && ( currVHandleOffset != vhandle_offset || !contig ) )
01428     {
01429         // Get all vertices, removing ones in this batch
01430         Range vrange, tmp_range( dum_range );
01431         result = mdbImpl->get_entities_by_type( 0, MBVERTEX, vrange );RR;
01432         if( !beforeEnts.empty() ) tmp_range.merge( beforeEnts.subset_by_type( MBVERTEX ) );
01433         vrange = subtract( vrange, tmp_range );
01434         // Compute the max cid; map is indexed by cid, so size is max_cid + 1
01435 #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
01436 #define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
01437         // Sanity check that max vhandle is larger than offset
01438         long new_max = *vrange.rbegin() - currVHandleOffset;
01439         assert( new_max >= 0 && ( (long)*vrange.begin() ) - currVHandleOffset >= 0 );
01440         max_cid          = MAX( max_cid, ( (unsigned int)new_max ) );
01441         cubMOABVertexMap = new std::vector< EntityHandle >( max_cid + 1 );
01442         // Initialize to zero then put previous vertices into the map
01443         std::fill( cubMOABVertexMap->begin(), cubMOABVertexMap->end(), 0 );
01444         Range::iterator rit;
01445         for( rit = vrange.begin(); rit != vrange.end(); ++rit )
01446         {
01447             assert( ( (long)*rit ) - currVHandleOffset >= 0 && ( (long)*rit ) - currVHandleOffset <= max_cid );
01448             ( *cubMOABVertexMap )[*rit - currVHandleOffset] = *rit;
01449         }
01450     }
01451     // case B: there is a map and we need to resize it
01452     else if( cubMOABVertexMap && max_cid + 1 > cubMOABVertexMap->size() )
01453     {
01454         unsigned int old_size = cubMOABVertexMap->size();
01455         cubMOABVertexMap->resize( max_cid + 1 );
01456         std::fill( &( *cubMOABVertexMap )[old_size], &( *cubMOABVertexMap )[0] + cubMOABVertexMap->size(), 0 );
01457     }
01458 
01459     // OK, we have a map or don't need one
01460     if( NULL == cubMOABVertexMap )
01461     {
01462         // If we're not forward-contiguous (i.e. we're reverse or
01463         // out-of-order contiguous), re-order coordinates for handles
01464         // so that they are
01465         if( -1 == contig || -2 == contig )
01466         {
01467             // In case the arrays are large, do each coord separately
01468             std::vector< double > tmp_coords( entity->nodeCt );
01469             for( unsigned int j = 0; j < 3; j++ )
01470             {
01471                 // Permute the coords into new order
01472                 for( unsigned int i = 0; i < entity->nodeCt; i++ )
01473                 {
01474                     assert( uint_buf[i] >= min_cid && max_cid - uint_buf[i] < entity->nodeCt );
01475                     tmp_coords[uint_buf[i] - min_cid] = arrays[j][i];
01476                 }
01477                 // Copy the permuted to storage
01478                 std::copy( &tmp_coords[0], &tmp_coords[0] + entity->nodeCt, arrays[j] );
01479             }
01480             // Now re-order the ids; either way just go off min, max cid
01481             for( unsigned int i = 0; i < entity->nodeCt; i++ )
01482                 uint_buf[i] = min_cid + i;
01483         }
01484         else if( !contig )
01485             // Shouldn't get here, since in non-contiguous case map should be there
01486             assert( false );
01487     }
01488     else
01489     {
01490         // Put new vertices into the map
01491         // Now set the new values
01492         unsigned int* vit   = &uint_buf[0];
01493         Range::iterator rit = dum_range.begin();
01494         for( ; rit != dum_range.end(); vit++, ++rit )
01495         {
01496             assert( *vit < cubMOABVertexMap->size() );
01497             ( *cubMOABVertexMap )[*vit] = *rit;
01498         }
01499     }
01500 
01501     // No longer need to use uint_buf; convert in-place to ints, so we
01502     // can assign gid tag
01503     CONVERT_TO_INTS( entity->nodeCt );
01504     result = mdbImpl->tag_set_data( globalIdTag, dum_range, &int_buf[0] );
01505     if( MB_SUCCESS != result ) return result;
01506 
01507     // Set the dimension to at least zero (entity has at least nodes) on the geom tag
01508     int max_dim = 0;
01509     result      = mdbImpl->tag_set_data( geomTag, &( entity->setHandle ), 1, &max_dim );
01510     if( MB_SUCCESS != result ) return result;
01511     // Set the category tag just in case there're only vertices in this set
01512     result = mdbImpl->tag_set_data( categoryTag, &entity->setHandle, 1, &geom_categories[0] );
01513     if( MB_SUCCESS != result ) return result;
01514 
01515     // Get fixed node data and assign
01516     int md_index = model->nodeMD.get_md_entry( gindex, "FixedNodes" );
01517     if( -1 == md_index ) return MB_SUCCESS;
01518     MetaDataContainer::MetaDataEntry* md_entry = &( model->nodeMD.metadataEntries[md_index] );
01519 
01520     std::vector< int > fixed_flags( entity->nodeCt );
01521     std::fill( fixed_flags.begin(), fixed_flags.end(), 0 );
01522     if( md_entry->mdDataType != 3 ) return MB_FAILURE;
01523 
01524     for( std::vector< unsigned int >::iterator vit = md_entry->mdIntArrayValue.begin();
01525          vit != md_entry->mdIntArrayValue.end(); ++vit )
01526     {
01527 #ifndef NDEBUG
01528         EntityHandle fixed_v =
01529             ( cubMOABVertexMap ? ( *cubMOABVertexMap )[*vit] : (EntityHandle)currVHandleOffset + *vit );
01530         assert( fixed_v >= *dum_range.begin() && fixed_v <= *dum_range.rbegin() );
01531 #endif
01532         fixed_flags[*vit - *dum_range.begin()] = 1;
01533     }
01534 
01535     Tag fixedFlagTag;
01536     int dum_val = 0;
01537     result      = mdbImpl->tag_get_handle( "NodeFixed", 1, MB_TYPE_INTEGER, fixedFlagTag, MB_TAG_SPARSE | MB_TAG_CREAT,
01538                                            &dum_val );
01539     if( MB_SUCCESS != result ) return result;
01540     result = mdbImpl->tag_set_data( fixedFlagTag, dum_range, &fixed_flags[0] );
01541 
01542     return result;
01543 }
01544 
01545 ErrorCode Tqdcfr::read_elements( Tqdcfr::ModelEntry* model, Tqdcfr::GeomHeader* entity )
01546 {
01547     if( entity->elemTypeCt == 0 ) return MB_SUCCESS;
01548     const int in_order_map[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13,
01549                                  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 };
01550 
01551     // Get data in separate calls to minimize memory usage
01552     // Position the file
01553     FSEEK( model->modelOffset + entity->elemOffset );
01554 
01555     int int_type, nodes_per_elem, num_elem;
01556     int max_dim = -1;
01557     ErrorCode result;
01558     for( unsigned int i = 0; i < entity->elemTypeCt; i++ )
01559     {
01560         // For this elem type, get the type, nodes per elem, num elems
01561         FREADI( 3 );
01562         int_type       = uint_buf[0];
01563         nodes_per_elem = uint_buf[1];
01564         num_elem       = uint_buf[2];
01565 
01566         // Get MB element type from cub file's
01567         EntityType elem_type = mp_type_to_mb_type[int_type];
01568         max_dim              = ( max_dim < CN::Dimension( elem_type ) ? CN::Dimension( elem_type ) : max_dim );
01569 
01570         if( debug ) std::cout << "type " << CN::EntityTypeName( elem_type ) << ":";
01571 
01572         const int* node_order = cub_elem_order_map[elem_type][nodes_per_elem];
01573         if( !node_order ) node_order = in_order_map;
01574 
01575         // Get element ids
01576         FREADI( num_elem );
01577 
01578         // Check to see if ids are contiguous...
01579         int contig;
01580         unsigned int max_id, min_id;
01581         check_contiguous( num_elem, contig, min_id, max_id );
01582         if( 0 == contig && !printedElemWarning )
01583         {
01584             std::cout << "Element ids are not contiguous!" << std::endl;
01585             printedElemWarning = true;
01586         }
01587 
01588         // Get a space for reading connectivity data directly into MB
01589         EntityHandle *conn, start_handle;
01590 
01591         result = readUtilIface->get_element_connect( num_elem, nodes_per_elem, elem_type, int_buf[0], start_handle,
01592                                                      conn, SequenceManager::DEFAULT_ELEMENT_SEQUENCE_SIZE );
01593         if( MB_SUCCESS != result ) return result;
01594 
01595         Range dum_range( start_handle, start_handle + num_elem - 1 );
01596 
01597         long elem_offset;
01598         elem_offset = ( 1 == contig ? start_handle - int_buf[0] : int_buf[num_elem - 1] );
01599         if( -1 == currElementIdOffset[elem_type] ) currElementIdOffset[elem_type] = elem_offset;
01600 
01601         // Set the gids on elements
01602         CONVERT_TO_INTS( num_elem );
01603         result = mdbImpl->tag_set_data( globalIdTag, dum_range, &int_buf[0] );
01604         if( MB_SUCCESS != result ) return result;
01605 
01606         // Get the connectivity array
01607         unsigned int total_conn = num_elem * nodes_per_elem;
01608         if( major >= 14 ) FREADI( num_elem );  // We need to skip num_elem in advance, it looks like
01609         FREADI( total_conn );
01610 
01611         // Post-process connectivity into handles
01612         EntityHandle new_handle;
01613         int j = 0;
01614         for( int e = 0; e < num_elem; ++e )
01615         {
01616             for( int k = 0; k < nodes_per_elem; ++k, ++j )
01617             {
01618                 if( debug )
01619                 {
01620                     if( 0 == j ) std::cout << "Conn=";
01621                     std::cout << ", " << uint_buf[j];
01622                 }
01623                 if( NULL == cubMOABVertexMap )
01624                     new_handle = (EntityHandle)currVHandleOffset + uint_buf[j];
01625                 else
01626                 {
01627                     assert( uint_buf[j] < cubMOABVertexMap->size() && 0 != ( *cubMOABVertexMap )[uint_buf[j]] );
01628                     new_handle = ( *cubMOABVertexMap )[uint_buf[j]];
01629                 }
01630 #ifndef NDEBUG
01631                 EntityHandle dum_handle;
01632                 assert( MB_SUCCESS ==
01633                         mdbImpl->handle_from_id( MBVERTEX, mdbImpl->id_from_handle( new_handle ), dum_handle ) );
01634 #endif
01635                 conn[e * nodes_per_elem + node_order[k]] = new_handle;
01636             }
01637         }
01638 
01639         // Add these elements into the entity's set
01640         result = mdbImpl->add_entities( entity->setHandle, dum_range );
01641         if( MB_SUCCESS != result ) return result;
01642 
01643         // Notify MOAB of the new elements
01644         result = readUtilIface->update_adjacencies( start_handle, num_elem, nodes_per_elem, conn );
01645         if( MB_SUCCESS != result ) return result;
01646     }
01647 
01648     // Set the dimension on the geom tag
01649     result = mdbImpl->tag_set_data( geomTag, &entity->setHandle, 1, &max_dim );
01650     if( MB_SUCCESS != result ) return result;
01651     if( max_dim != -1 )
01652     {
01653         result = mdbImpl->tag_set_data( categoryTag, &entity->setHandle, 1, &geom_categories[max_dim] );
01654         if( MB_SUCCESS != result ) return result;
01655     }
01656 
01657     return MB_SUCCESS;
01658 }
01659 
01660 void Tqdcfr::check_contiguous( const unsigned int num_ents, int& contig, unsigned int& min_id, unsigned int& max_id )
01661 {
01662     unsigned int *id_it, curr_id, i;
01663 
01664     // Check in forward-contiguous direction
01665     id_it   = &uint_buf[0];
01666     curr_id = *id_it++ + 1;
01667     contig  = 1;
01668     min_id  = uint_buf[0];
01669     max_id  = uint_buf[0];
01670     for( i = 1; i < num_ents; id_it++, i++, curr_id++ )
01671     {
01672         if( *id_it != curr_id )
01673         {
01674             contig = 0;
01675         }
01676         min_id = MIN( min_id, uint_buf[i] );
01677         max_id = MAX( max_id, uint_buf[i] );
01678     }
01679 
01680     // If we got here and we're at the end of the loop, it's forward-contiguous
01681     if( 1 == contig ) return;
01682 
01683     // Check in reverse-contiguous direction
01684     contig  = -1;
01685     id_it   = &uint_buf[0];
01686     curr_id = *id_it++ - 1;
01687     for( i = 1; i < num_ents; id_it++, i++, curr_id-- )
01688     {
01689         if( *id_it != curr_id )
01690         {
01691             contig = 0;
01692             break;
01693         }
01694     }
01695 
01696     // If we got here and we're at the end of the loop, it's reverse-contiguous
01697     if( -1 == contig ) return;
01698 
01699     // One final check, for contiguous but out of order
01700     if( max_id - min_id + 1 == num_ents ) contig = -2;
01701 
01702     // Else it's not contiguous at all
01703     contig = 0;
01704 }
01705 
01706 void Tqdcfr::FEModelHeader::init( const unsigned int offset, Tqdcfr* instance )
01707 {
01708     instance->FSEEK( offset );
01709     instance->FREADI( 4 );
01710     feEndian       = instance->uint_buf[0];
01711     feSchema       = instance->uint_buf[1];
01712     feCompressFlag = instance->uint_buf[2];
01713     feLength       = instance->uint_buf[3];
01714     instance->FREADI( 3 );
01715     geomArray.init( instance->uint_buf );
01716     instance->FREADI( 2 );
01717     nodeArray.metaDataOffset    = instance->uint_buf[0];
01718     elementArray.metaDataOffset = instance->uint_buf[1];
01719     instance->FREADI( 3 );
01720     groupArray.init( instance->uint_buf );
01721     instance->FREADI( 3 );
01722     blockArray.init( instance->uint_buf );
01723     instance->FREADI( 3 );
01724     nodesetArray.init( instance->uint_buf );
01725     instance->FREADI( 3 );
01726     sidesetArray.init( instance->uint_buf );
01727     instance->FREADI( 1 );
01728 }
01729 
01730 ErrorCode Tqdcfr::read_file_header()
01731 {
01732     // Read file header
01733     FSEEK( 4 );
01734     // Read the first int from the file
01735     // If it is 0, it is littleEndian
01736     unsigned rval = fread( &fileTOC.fileEndian, sizeof( unsigned int ), 1, cubFile );
01737     IO_ASSERT( rval == 1 );
01738 #ifdef WORDS_BIGENDIAN
01739     if( fileTOC.fileEndian == 0 ) swapForEndianness = true;
01740 #else
01741     if( fileTOC.fileEndian != 0 ) swapForEndianness = true;
01742 #endif
01743     if( debug ) std::cout << " swapping ? " << swapForEndianness << "\n";
01744     FREADI( 5 );
01745     // fileTOC.fileEndian = uint_buf[0];
01746     fileTOC.fileSchema          = uint_buf[0];
01747     fileTOC.numModels           = uint_buf[1];
01748     fileTOC.modelTableOffset    = uint_buf[2];
01749     fileTOC.modelMetaDataOffset = uint_buf[3];
01750     fileTOC.activeFEModel       = uint_buf[4];
01751     if( debug ) fileTOC.print();
01752 
01753     return MB_SUCCESS;
01754 }
01755 
01756 ErrorCode Tqdcfr::read_model_entries()
01757 {
01758     // Read model entries
01759     FSEEK( fileTOC.modelTableOffset );
01760     FREADI( fileTOC.numModels * 6 );
01761     modelEntries.resize( fileTOC.numModels );
01762     if( modelEntries.empty() ) return MB_FAILURE;
01763     std::vector< unsigned int >::iterator int_it = uint_buf.begin();
01764     for( unsigned int i = 0; i < fileTOC.numModels; i++ )
01765     {
01766         modelEntries[i].modelHandle = *int_it++;
01767         modelEntries[i].modelOffset = *int_it++;
01768         modelEntries[i].modelLength = *int_it++;
01769         modelEntries[i].modelType   = *int_it++;
01770         modelEntries[i].modelOwner  = *int_it++;
01771         modelEntries[i].modelPad    = *int_it++;
01772         if( int_it == uint_buf.end() && i != fileTOC.numModels - 1 ) return MB_FAILURE;
01773         if( debug ) modelEntries[i].print();
01774     }
01775 
01776     return MB_SUCCESS;
01777 }
01778 
01779 int Tqdcfr::find_model( const unsigned int model_type )
01780 {
01781     for( unsigned int i = 0; i < fileTOC.numModels; i++ )
01782     {
01783         if( modelEntries[i].modelType == model_type ) return i;
01784     }
01785 
01786     return -1;
01787 }
01788 
01789 ErrorCode Tqdcfr::read_meta_data( const unsigned int metadata_offset, Tqdcfr::MetaDataContainer& mc )
01790 {
01791     // Read the metadata header
01792     FSEEK( metadata_offset );
01793     FREADI( 3 );
01794     mc.mdSchema     = uint_buf[0];
01795     mc.compressFlag = uint_buf[1];
01796 
01797     // Allocate space for the entries
01798     mc.metadataEntries.resize( uint_buf[2] );
01799 
01800     // Now read the metadata values
01801     for( unsigned int i = 0; i < mc.metadataEntries.size(); i++ )
01802     {
01803         FREADI( 2 );
01804         mc.metadataEntries[i].mdOwner    = uint_buf[0];
01805         mc.metadataEntries[i].mdDataType = uint_buf[1];
01806 
01807         // Read the name string
01808         read_md_string( mc.metadataEntries[i].mdName );
01809 
01810         if( mc.metadataEntries[i].mdDataType == 0 )
01811         {
01812             // integer
01813             FREADI( 1 );
01814             mc.metadataEntries[i].mdIntValue = uint_buf[0];
01815         }
01816         else if( mc.metadataEntries[i].mdDataType == 1 )
01817         {
01818             // string
01819             read_md_string( mc.metadataEntries[i].mdStringValue );
01820         }
01821         else if( mc.metadataEntries[i].mdDataType == 2 )
01822         {
01823             // double
01824             FREADD( 1 );
01825             mc.metadataEntries[i].mdDblValue = dbl_buf[0];
01826         }
01827         else if( mc.metadataEntries[i].mdDataType == 3 )
01828         {
01829             // int array
01830             FREADI( 1 );
01831             mc.metadataEntries[i].mdIntArrayValue.resize( uint_buf[0] );
01832             FREADI( mc.metadataEntries[i].mdIntArrayValue.size() );
01833             std::copy( uint_buf.begin(), uint_buf.begin() + mc.metadataEntries[i].mdIntArrayValue.size(),
01834                        mc.metadataEntries[i].mdIntArrayValue.begin() );
01835         }
01836         else if( mc.metadataEntries[i].mdDataType == 4 )
01837         {
01838             // double array
01839             FREADI( 1 );
01840             mc.metadataEntries[i].mdDblArrayValue.resize( uint_buf[0] );
01841             FREADD( mc.metadataEntries[i].mdDblArrayValue.size() );
01842             std::copy( dbl_buf.begin(), dbl_buf.begin() + mc.metadataEntries[i].mdDblArrayValue.size(),
01843                        mc.metadataEntries[i].mdDblArrayValue.begin() );
01844         }
01845         else
01846             return MB_FAILURE;
01847     }
01848     if( debug ) mc.print();
01849 
01850     return MB_SUCCESS;
01851 }
01852 
01853 ErrorCode Tqdcfr::read_md_string( std::string& name )
01854 {
01855     FREADI( 1 );
01856     int str_size = uint_buf[0];
01857     if( str_size > 0 )
01858     {
01859         FREADC( str_size );
01860         if( char_buf.size() <= (unsigned int)str_size ) char_buf.resize( str_size + 1 );
01861         char_buf[str_size] = '\0';
01862         name               = (char*)&char_buf[0];
01863         // Read pad if any
01864         int extra = str_size % sizeof( int );
01865         if( extra )
01866         {
01867             // Read extra chars to end of pad
01868             str_size = sizeof( int ) - extra;
01869             FREADC( str_size );
01870         }
01871     }
01872 
01873     return MB_SUCCESS;
01874 }
01875 
01876 ErrorCode Tqdcfr::GeomHeader::read_info_header( const unsigned int model_offset,
01877                                                 const Tqdcfr::FEModelHeader::ArrayInfo& info,
01878                                                 Tqdcfr* instance,
01879                                                 Tqdcfr::GeomHeader*& geom_headers )
01880 {
01881     geom_headers = new GeomHeader[info.numEntities];
01882     instance->FSEEK( model_offset + info.tableOffset );
01883     int dum_int;
01884     ErrorCode result;
01885 
01886     if( 0 == instance->categoryTag )
01887     {
01888         static const char val[CATEGORY_TAG_SIZE] = { 0 };
01889         result = instance->mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE,
01890                                                     instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
01891         if( MB_SUCCESS != result ) return result;
01892     }
01893 
01894     for( unsigned int i = 0; i < info.numEntities; i++ )
01895     {
01896         instance->FREADI( 8 );
01897         geom_headers[i].nodeCt     = instance->uint_buf[0];
01898         geom_headers[i].nodeOffset = instance->uint_buf[1];
01899         geom_headers[i].elemCt     = instance->uint_buf[2];
01900         geom_headers[i].elemOffset = instance->uint_buf[3];
01901         geom_headers[i].elemTypeCt = instance->uint_buf[4];
01902         geom_headers[i].elemLength = instance->uint_buf[5];
01903         geom_headers[i].geomID     = instance->uint_buf[6];
01904 
01905         // Don't represent in MOAB if no mesh
01906         if( geom_headers[i].nodeCt == 0 && geom_headers[i].elemCt == 0 ) continue;
01907 
01908         // Create an entity set for this entity
01909         result = instance->create_set( geom_headers[i].setHandle );
01910         if( MB_SUCCESS != result ) return result;
01911 
01912         // Set the dimension to -1; will have to reset later, after elements are read
01913         dum_int = -1;
01914         result  = instance->mdbImpl->tag_set_data( instance->geomTag, &( geom_headers[i].setHandle ), 1, &dum_int );
01915         if( MB_SUCCESS != result ) return result;
01916 
01917         // Set a unique id tag
01918         result = instance->mdbImpl->tag_set_data( instance->uniqueIdTag, &( geom_headers[i].setHandle ), 1,
01919                                                   &( geom_headers[i].geomID ) );
01920         if( MB_SUCCESS != result ) return result;
01921 
01922         // Put the set and uid into a map for later
01923         instance->uidSetMap[geom_headers[i].geomID] = geom_headers[i].setHandle;
01924     }
01925 
01926     // Now get the dimensions of elements for each geom entity
01927     for( unsigned int i = 0; i < info.numEntities; i++ )
01928     {
01929         if( geom_headers[i].elemTypeCt == 0 ) continue;
01930         instance->FSEEK( model_offset + geom_headers[i].elemOffset );
01931         for( unsigned int j = 0; j < geom_headers[i].elemTypeCt; j++ )
01932         {
01933             // For this elem type, get the type, nodes per elem, num elems
01934             instance->FREADI( 3 );
01935             int int_type           = instance->uint_buf[0];
01936             int nodes_per_elem     = instance->uint_buf[1];
01937             int num_elem           = instance->uint_buf[2];
01938             EntityType elem_type   = mp_type_to_mb_type[int_type];
01939             geom_headers[i].maxDim = std::max( geom_headers[i].maxDim, (int)CN::Dimension( elem_type ) );
01940             if( j < geom_headers[i].elemTypeCt - 1 )
01941             {
01942                 int num_skipped_ints = num_elem + num_elem * nodes_per_elem;
01943                 if( major >= 14 ) num_skipped_ints += num_elem;
01944                 instance->FREADI( num_skipped_ints );
01945             }
01946         }
01947     }
01948 
01949     return MB_SUCCESS;
01950 }
01951 
01952 ErrorCode Tqdcfr::GroupHeader::read_info_header( const unsigned int model_offset,
01953                                                  const Tqdcfr::FEModelHeader::ArrayInfo& info,
01954                                                  Tqdcfr* instance,
01955                                                  Tqdcfr::GroupHeader*& group_headers )
01956 {
01957     group_headers = new GroupHeader[info.numEntities];
01958     instance->FSEEK( model_offset + info.tableOffset );
01959     ErrorCode result;
01960 
01961     if( 0 == instance->categoryTag )
01962     {
01963         static const char val[CATEGORY_TAG_SIZE] = { 0 };
01964         result = instance->mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE,
01965                                                     instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
01966         if( MB_SUCCESS != result ) return result;
01967     }
01968 
01969     for( unsigned int i = 0; i < info.numEntities; i++ )
01970     {
01971         // Create an entity set for this entity
01972         result = instance->create_set( group_headers[i].setHandle );
01973         if( MB_SUCCESS != result ) return result;
01974         static const char group_category[CATEGORY_TAG_SIZE] = "Group\0";
01975 
01976         instance->FREADI( 6 );
01977         group_headers[i].grpID     = instance->uint_buf[0];
01978         group_headers[i].grpType   = instance->uint_buf[1];
01979         group_headers[i].memCt     = instance->uint_buf[2];
01980         group_headers[i].memOffset = instance->uint_buf[3];
01981         group_headers[i].memTypeCt = instance->uint_buf[4];
01982         group_headers[i].grpLength = instance->uint_buf[5];
01983 
01984         // Set the category tag to signify this is a group
01985         result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( group_headers[i].setHandle ), 1,
01986                                                   group_category );
01987         if( MB_SUCCESS != result ) return result;
01988 
01989         // Set a global id tag
01990         result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( group_headers[i].setHandle ), 1,
01991                                                   &( group_headers[i].grpID ) );
01992         if( MB_SUCCESS != result ) return result;
01993 
01994         instance->gidSetMap[5][group_headers[i].grpID] = group_headers[i].setHandle;
01995     }
01996 
01997     return MB_SUCCESS;
01998 }
01999 
02000 ErrorCode Tqdcfr::BlockHeader::read_info_header( const double data_version,
02001                                                  const unsigned int model_offset,
02002                                                  const Tqdcfr::FEModelHeader::ArrayInfo& info,
02003                                                  Tqdcfr* instance,
02004                                                  Tqdcfr::BlockHeader*& block_headers )
02005 {
02006     block_headers = new BlockHeader[info.numEntities];
02007     instance->FSEEK( model_offset + info.tableOffset );
02008     ErrorCode result;
02009 
02010     if( 0 == instance->categoryTag )
02011     {
02012         static const char val[CATEGORY_TAG_SIZE] = { 0 };
02013         result = instance->mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE,
02014                                                     instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
02015         if( MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result ) return result;
02016     }
02017 
02018     for( unsigned int i = 0; i < info.numEntities; i++ )
02019     {
02020         // Create an entity set for this entity
02021         result = instance->create_set( block_headers[i].setHandle );
02022         if( MB_SUCCESS != result ) return result;
02023         static const char material_category[CATEGORY_TAG_SIZE] = "Material Set\0";
02024 
02025         instance->FREADI( 12 );
02026         block_headers[i].blockID          = instance->uint_buf[0];
02027         block_headers[i].blockElemType    = instance->uint_buf[1];
02028         block_headers[i].memCt            = instance->uint_buf[2];
02029         block_headers[i].memOffset        = instance->uint_buf[3];
02030         block_headers[i].memTypeCt        = instance->uint_buf[4];
02031         block_headers[i].attribOrder      = instance->uint_buf[5];  // Attrib order
02032         block_headers[i].blockCol         = instance->uint_buf[6];
02033         block_headers[i].blockMixElemType = instance->uint_buf[7];  // Mixed elem type
02034         block_headers[i].blockPyrType     = instance->uint_buf[8];
02035         block_headers[i].blockMat         = instance->uint_buf[9];
02036         block_headers[i].blockLength      = instance->uint_buf[10];
02037         block_headers[i].blockDim         = instance->uint_buf[11];
02038 
02039         Tag bhTag_header;
02040         {
02041             std::vector< int > def_uint_zero( 3, 0 );
02042             result = instance->mdbImpl->tag_get_handle( BLOCK_HEADER, 3 * sizeof( unsigned int ), MB_TYPE_INTEGER,
02043                                                         bhTag_header, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_BYTES,
02044                                                         &def_uint_zero[0] );
02045             if( MB_SUCCESS != result ) return result;
02046             int block_header_data[] = { static_cast< int >( block_headers[i].blockCol ),
02047                                         static_cast< int >( block_headers[i].blockMat ),
02048                                         static_cast< int >( block_headers[i].blockDim ) };
02049             result =
02050                 instance->mdbImpl->tag_set_data( bhTag_header, &( block_headers[i].setHandle ), 1, block_header_data );
02051         }
02052 
02053         if( MB_SUCCESS != result ) return result;
02054 
02055         // Adjust element type for data version; older element types didn't include
02056         // 4 new trishell element types
02057         if( data_version <= 1.0 && block_headers[i].blockElemType >= 15 ) block_headers[i].blockElemType += 4;
02058 
02059         if( block_headers[i].blockElemType >= (unsigned)cub_elem_num_verts_len )
02060         {
02061             // Block element type unassigned, will have to infer from verts/element; make sure it's
02062             // the expected value of 52
02063             if( ( 14 == major && 2 < minor ) || 15 <= major )
02064             {
02065                 if( 55 != block_headers[i].blockElemType )
02066                     MB_SET_ERR( MB_FAILURE, "Invalid block element type: " << block_headers[i].blockElemType );
02067             }
02068             else
02069             {
02070                 if( 52 != block_headers[i].blockElemType )
02071                     MB_SET_ERR( MB_FAILURE, "Invalid block element type: " << block_headers[i].blockElemType );
02072             }
02073         }
02074 
02075         // Set the material set tag and id tag both to id
02076         result = instance->mdbImpl->tag_set_data( instance->blockTag, &( block_headers[i].setHandle ), 1,
02077                                                   &( block_headers[i].blockID ) );
02078         if( MB_SUCCESS != result ) return result;
02079         result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( block_headers[i].setHandle ), 1,
02080                                                   &( block_headers[i].blockID ) );
02081         if( MB_SUCCESS != result ) return result;
02082         result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( block_headers[i].setHandle ), 1,
02083                                                   material_category );
02084         if( MB_SUCCESS != result ) return result;
02085 
02086         // If this block is empty, continue
02087         if( !block_headers[i].memCt ) continue;
02088 
02089         // Check the number of vertices in the element type, and set the has mid nodes tag
02090         // accordingly; if element type wasn't set, they're unlikely to have mid nodes
02091         // 52 is for CUBIT versions below 14.1, 55 for CUBIT version 14.9 and above
02092         if( 52 != block_headers[i].blockElemType && 55 != block_headers[i].blockElemType )
02093         {
02094             int num_verts                    = cub_elem_num_verts[block_headers[i].blockElemType];
02095             block_headers[i].blockEntityType = block_type_to_mb_type[block_headers[i].blockElemType];
02096             if( ( block_headers[i].blockEntityType < MBMAXTYPE ) &&
02097                 ( num_verts != CN::VerticesPerEntity( block_headers[i].blockEntityType ) ) )
02098             {
02099                 // Not a linear element; try to find hasMidNodes values
02100                 for( int j = 0; j < 4; j++ )
02101                     block_headers[i].hasMidNodes[j] = 0;
02102                 if( 0 == instance->hasMidNodesTag )
02103                 {
02104                     result = instance->mdbImpl->tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER,
02105                                                                 instance->hasMidNodesTag, MB_TAG_SPARSE | MB_TAG_CREAT,
02106                                                                 block_headers[i].hasMidNodes );
02107                     if( MB_SUCCESS != result ) return result;
02108                 }
02109 
02110                 CN::HasMidNodes( block_headers[i].blockEntityType, num_verts, block_headers[i].hasMidNodes );
02111 
02112                 // Now set the tag on this set
02113                 result = instance->mdbImpl->tag_set_data( instance->hasMidNodesTag, &block_headers[i].setHandle, 1,
02114                                                           block_headers[i].hasMidNodes );
02115                 if( MB_SUCCESS != result ) return result;
02116             }
02117         }
02118     }
02119 
02120     return MB_SUCCESS;
02121 }
02122 
02123 ErrorCode Tqdcfr::NodesetHeader::read_info_header( const unsigned int model_offset,
02124                                                    const Tqdcfr::FEModelHeader::ArrayInfo& info,
02125                                                    Tqdcfr* instance,
02126                                                    Tqdcfr::NodesetHeader*& nodeset_headers )
02127 {
02128     nodeset_headers = new NodesetHeader[info.numEntities];
02129     instance->FSEEK( model_offset + info.tableOffset );
02130     ErrorCode result;
02131 
02132     if( 0 == instance->categoryTag )
02133     {
02134         static const char val[CATEGORY_TAG_SIZE] = { 0 };
02135         result = instance->mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE,
02136                                                     instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
02137         if( MB_SUCCESS != result ) return result;
02138     }
02139 
02140     for( unsigned int i = 0; i < info.numEntities; i++ )
02141     {
02142         // Create an entity set for this entity
02143         result = instance->create_set( nodeset_headers[i].setHandle );
02144         if( MB_SUCCESS != result ) return result;
02145         static const char dirichlet_category[CATEGORY_TAG_SIZE] = "Dirichlet Set\0";
02146 
02147         instance->FREADI( 8 );
02148         nodeset_headers[i].nsID      = instance->uint_buf[0];
02149         nodeset_headers[i].memCt     = instance->uint_buf[1];
02150         nodeset_headers[i].memOffset = instance->uint_buf[2];
02151         nodeset_headers[i].memTypeCt = instance->uint_buf[3];
02152         nodeset_headers[i].pointSym  = instance->uint_buf[4];  // Point sym
02153         nodeset_headers[i].nsCol     = instance->uint_buf[5];
02154         nodeset_headers[i].nsLength  = instance->uint_buf[6];
02155         // Pad
02156 
02157         // Set the dirichlet set tag and id tag both to id
02158         result = instance->mdbImpl->tag_set_data( instance->nsTag, &( nodeset_headers[i].setHandle ), 1,
02159                                                   &( nodeset_headers[i].nsID ) );
02160         if( MB_SUCCESS != result ) return result;
02161         result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( nodeset_headers[i].setHandle ), 1,
02162                                                   &( nodeset_headers[i].nsID ) );
02163         if( MB_SUCCESS != result ) return result;
02164         result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( nodeset_headers[i].setHandle ), 1,
02165                                                   dirichlet_category );
02166         if( MB_SUCCESS != result ) return result;
02167     }
02168 
02169     return MB_SUCCESS;
02170 }
02171 
02172 ErrorCode Tqdcfr::SidesetHeader::read_info_header( const unsigned int model_offset,
02173                                                    const Tqdcfr::FEModelHeader::ArrayInfo& info,
02174                                                    Tqdcfr* instance,
02175                                                    Tqdcfr::SidesetHeader*& sideset_headers )
02176 {
02177     sideset_headers = new SidesetHeader[info.numEntities];
02178     instance->FSEEK( model_offset + info.tableOffset );
02179     ErrorCode result;
02180 
02181     if( 0 == instance->categoryTag )
02182     {
02183         static const char val[CATEGORY_TAG_SIZE] = { 0 };
02184         result = instance->mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE,
02185                                                     instance->categoryTag, MB_TAG_SPARSE | MB_TAG_CREAT, val );
02186         if( MB_SUCCESS != result ) return result;
02187     }
02188 
02189     for( unsigned int i = 0; i < info.numEntities; i++ )
02190     {
02191         // Create an entity set for this entity
02192         result = instance->create_set( sideset_headers[i].setHandle );
02193         if( MB_SUCCESS != result ) return result;
02194         static const char neumann_category[CATEGORY_TAG_SIZE] = "Neumann Set\0";
02195 
02196         instance->FREADI( 8 );
02197         sideset_headers[i].ssID      = instance->uint_buf[0];
02198         sideset_headers[i].memCt     = instance->uint_buf[1];
02199         sideset_headers[i].memOffset = instance->uint_buf[2];
02200         sideset_headers[i].memTypeCt = instance->uint_buf[3];
02201         sideset_headers[i].numDF     = instance->uint_buf[4];  // Num dist factors
02202         sideset_headers[i].ssCol     = instance->uint_buf[5];
02203         sideset_headers[i].useShell  = instance->uint_buf[6];
02204         sideset_headers[i].ssLength  = instance->uint_buf[7];
02205 
02206         // Set the neumann set tag and id tag both to id
02207         result = instance->mdbImpl->tag_set_data( instance->ssTag, &( sideset_headers[i].setHandle ), 1,
02208                                                   &( sideset_headers[i].ssID ) );
02209         if( MB_SUCCESS != result ) return result;
02210         result = instance->mdbImpl->tag_set_data( instance->globalIdTag, &( sideset_headers[i].setHandle ), 1,
02211                                                   &( sideset_headers[i].ssID ) );
02212         if( MB_SUCCESS != result ) return result;
02213         result = instance->mdbImpl->tag_set_data( instance->categoryTag, &( sideset_headers[i].setHandle ), 1,
02214                                                   neumann_category );
02215         if( MB_SUCCESS != result ) return result;
02216     }
02217 
02218     return MB_SUCCESS;
02219 }
02220 
02221 void Tqdcfr::ModelEntry::print_geom_headers( const char* prefix, GeomHeader* header, const unsigned int num_headers )
02222 {
02223     if( !debug ) return;
02224     std::cout << prefix << std::endl;
02225     if( NULL != header )
02226     {
02227         for( unsigned int i = 0; i < num_headers; i++ )
02228         {
02229             std::cout << "Index " << i << std::endl;
02230             header[i].print();
02231         }
02232     }
02233 }
02234 
02235 void Tqdcfr::ModelEntry::print_group_headers( const char* prefix, GroupHeader* header, const unsigned int num_headers )
02236 {
02237     if( !debug ) return;
02238     std::cout << prefix << std::endl;
02239     if( NULL != header )
02240     {
02241         for( unsigned int i = 0; i < num_headers; i++ )
02242             header[i].print();
02243     }
02244 }
02245 
02246 void Tqdcfr::ModelEntry::print_block_headers( const char* prefix, BlockHeader* header, const unsigned int num_headers )
02247 {
02248     if( !debug ) return;
02249     std::cout << prefix << std::endl;
02250     if( NULL != header )
02251     {
02252         for( unsigned int i = 0; i < num_headers; i++ )
02253             header[i].print();
02254     }
02255 }
02256 
02257 void Tqdcfr::ModelEntry::print_nodeset_headers( const char* prefix,
02258                                                 NodesetHeader* header,
02259                                                 const unsigned int num_headers )
02260 {
02261     if( !debug ) return;
02262     std::cout << prefix << std::endl;
02263     if( NULL != header )
02264     {
02265         for( unsigned int i = 0; i < num_headers; i++ )
02266             header[i].print();
02267     }
02268 }
02269 
02270 void Tqdcfr::ModelEntry::print_sideset_headers( const char* prefix,
02271                                                 SidesetHeader* header,
02272                                                 const unsigned int num_headers )
02273 {
02274     if( !debug ) return;
02275     std::cout << prefix << std::endl;
02276     if( NULL != header )
02277     {
02278         for( unsigned int i = 0; i < num_headers; i++ )
02279             header[i].print();
02280     }
02281 }
02282 
02283 ErrorCode Tqdcfr::ModelEntry::read_header_info( Tqdcfr* instance, const double data_version )
02284 {
02285     feModelHeader.init( modelOffset, instance );
02286     int negone = -1;
02287     ErrorCode result;
02288     instance->globalIdTag = instance->mdbImpl->globalId_tag();
02289 
02290     if( feModelHeader.geomArray.numEntities > 0 )
02291     {
02292         result = instance->mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, instance->geomTag,
02293                                                     MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
02294         if( MB_SUCCESS != result ) return result;
02295 
02296         result = instance->mdbImpl->tag_get_handle( "UNIQUE_ID", 1, MB_TYPE_INTEGER, instance->uniqueIdTag,
02297                                                     MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
02298         if( MB_SUCCESS != result ) return result;
02299 
02300         result = Tqdcfr::GeomHeader::read_info_header( modelOffset, feModelHeader.geomArray, instance, feGeomH );
02301         print_geom_headers( "Geom headers:", feGeomH, feModelHeader.geomArray.numEntities );
02302         if( MB_SUCCESS != result ) return result;
02303     }
02304 
02305     if( feModelHeader.groupArray.numEntities > 0 )
02306     {
02307         result = Tqdcfr::GroupHeader::read_info_header( modelOffset, feModelHeader.groupArray, instance, feGroupH );
02308         print_group_headers( "Group headers:", feGroupH, feModelHeader.groupArray.numEntities );
02309         if( MB_SUCCESS != result ) return result;
02310     }
02311 
02312     if( feModelHeader.blockArray.numEntities > 0 )
02313     {
02314         result = instance->mdbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->blockTag,
02315                                                     MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
02316         if( MB_SUCCESS != result ) return result;
02317 
02318         result = Tqdcfr::BlockHeader::read_info_header( data_version, modelOffset, feModelHeader.blockArray, instance,
02319                                                         feBlockH );
02320         print_block_headers( "Block headers:", feBlockH, feModelHeader.blockArray.numEntities );
02321         if( MB_SUCCESS != result ) return result;
02322     }
02323     if( feModelHeader.nodesetArray.numEntities > 0 )
02324     {
02325         result = instance->mdbImpl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->nsTag,
02326                                                     MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
02327         if( MB_SUCCESS != result ) return result;
02328 
02329         result =
02330             Tqdcfr::NodesetHeader::read_info_header( modelOffset, feModelHeader.nodesetArray, instance, feNodeSetH );
02331         if( MB_SUCCESS != result ) return result;
02332         print_nodeset_headers( "Nodeset headers:", feNodeSetH, feModelHeader.nodesetArray.numEntities );
02333     }
02334     if( feModelHeader.sidesetArray.numEntities > 0 )
02335     {
02336         result = instance->mdbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, instance->ssTag,
02337                                                     MB_TAG_SPARSE | MB_TAG_CREAT, &negone );
02338         if( MB_SUCCESS != result ) return result;
02339 
02340         result =
02341             Tqdcfr::SidesetHeader::read_info_header( modelOffset, feModelHeader.sidesetArray, instance, feSideSetH );
02342         print_sideset_headers( "SideSet headers:", feSideSetH, feModelHeader.sidesetArray.numEntities );
02343     }
02344 
02345     return MB_SUCCESS;
02346 }
02347 
02348 ErrorCode Tqdcfr::ModelEntry::read_metadata_info( Tqdcfr* tqd )
02349 {
02350     if( debug ) std::cout << "Geom metadata:" << std::endl;
02351     tqd->read_meta_data( modelOffset + feModelHeader.geomArray.metaDataOffset, geomMD );
02352     if( debug ) std::cout << "Node metadata:" << std::endl;
02353     tqd->read_meta_data( modelOffset + feModelHeader.nodeArray.metaDataOffset, nodeMD );
02354     if( debug ) std::cout << "Elem metadata:" << std::endl;
02355     tqd->read_meta_data( modelOffset + feModelHeader.elementArray.metaDataOffset, elementMD );
02356     if( debug ) std::cout << "Group metadata:" << std::endl;
02357     tqd->read_meta_data( modelOffset + feModelHeader.groupArray.metaDataOffset, groupMD );
02358     if( debug ) std::cout << "Block metadata:" << std::endl;
02359     tqd->read_meta_data( modelOffset + feModelHeader.blockArray.metaDataOffset, blockMD );
02360     if( debug ) std::cout << "Nodeset metadata:" << std::endl;
02361     tqd->read_meta_data( modelOffset + feModelHeader.nodesetArray.metaDataOffset, nodesetMD );
02362     if( debug ) std::cout << "Sideset metadata:" << std::endl;
02363     tqd->read_meta_data( modelOffset + feModelHeader.sidesetArray.metaDataOffset, sidesetMD );
02364 
02365     return MB_SUCCESS;
02366 }
02367 
02368 ErrorCode Tqdcfr::read_acis_records( const char* sat_filename )
02369 {
02370     // Get the acis model location
02371     unsigned int acis_model_offset = 0, acis_model_length = 0, acis_model_handle = 1, acis_sat_type = 1;
02372     for( unsigned int i = 0; i < fileTOC.numModels; i++ )
02373     {
02374         if( modelEntries[i].modelHandle == acis_model_handle && modelEntries[i].modelType == acis_sat_type )
02375         {
02376             acis_model_offset = modelEntries[i].modelOffset;
02377             acis_model_length = modelEntries[i].modelLength;
02378             break;
02379         }
02380     }
02381 
02382     if( acis_model_length == 0 ) return MB_SUCCESS;
02383 
02384     std::vector< AcisRecord > records;
02385 
02386     acisDumpFile = NULL;
02387     if( sat_filename )
02388     {
02389         acisDumpFile = fopen( sat_filename, "w+" );
02390         if( NULL == acisDumpFile ) return MB_FAILURE;
02391     }
02392 
02393     // Position the file at the start of the acis model
02394     FSEEK( acis_model_offset );
02395 
02396     unsigned int bytes_left = acis_model_length;
02397 
02398     struct AcisRecord this_record;
02399     reset_record( this_record );
02400     char* ret;
02401 
02402     // Make the char buffer at least buf_size + 1 long, to fit null char
02403     const unsigned int buf_size = 1023;
02404 
02405     // CHECK_SIZE(char_buf, buf_size + 1);
02406     char_buf.resize( buf_size + 1 );
02407 
02408     while( 0 != bytes_left )
02409     {
02410         // Read the next buff characters, or bytes_left if smaller
02411         unsigned int next_buf = ( bytes_left > buf_size ? buf_size : bytes_left );
02412         FREADC( next_buf );
02413 
02414         if( NULL != acisDumpFile ) fwrite( &char_buf[0], sizeof( char ), next_buf, acisDumpFile );
02415 
02416         // Put null at end of string to stop searches
02417         char_buf.resize( next_buf + 1 );
02418         char_buf[next_buf]   = '\0';
02419         unsigned int buf_pos = 0;
02420 
02421         // Check for first read, and if so, get rid of the header
02422         if( bytes_left == acis_model_length )
02423         {
02424             // Look for 3 newlines
02425             ret = strchr( &( char_buf[0] ), '\n' );
02426             ret = strchr( ret + 1, '\n' );
02427             ret = strchr( ret + 1, '\n' );
02428             if( NULL == ret ) return MB_FAILURE;
02429             buf_pos += ret - &( char_buf[0] ) + 1;
02430         }
02431 
02432         bytes_left -= next_buf;
02433 
02434         // Now start grabbing records
02435         do
02436         {
02437             // Get next occurrence of '#' (record terminator)
02438             ret = strchr( &( char_buf[buf_pos] ), '#' );
02439             while( ret && (unsigned int)( ret + 1 - &char_buf[0] ) < bytes_left && *( ret + 1 ) != '\n' &&
02440                    *( ret + 1 ) != '\r' && *( ret + 1 ) != 0 )  // CR added for windows
02441                 ret = strchr( ret + 1, '#' );
02442             if( NULL != ret )
02443             {
02444                 // Grab the string (inclusive of the record terminator and the line feed) and
02445                 // complete the record
02446                 int num_chars = ret - &( char_buf[buf_pos] ) + 2;
02447                 if( *( ret + 1 ) == '\r' ) num_chars++;  // add more one character for Windows CR
02448                 this_record.att_string.append( &( char_buf[buf_pos] ), num_chars );
02449                 buf_pos += num_chars;
02450                 process_record( this_record );
02451 
02452                 // Put the record in the list...
02453                 records.push_back( this_record );
02454 
02455                 // And reset the record
02456                 reset_record( this_record );
02457             }
02458             else
02459             {
02460                 // Reached end of buffer; cache string then go get another; discard last character,
02461                 // which will be the null character
02462                 this_record.att_string.append( &( char_buf[buf_pos] ), next_buf - buf_pos );
02463                 buf_pos = next_buf;
02464             }
02465         } while( buf_pos < next_buf );
02466     }
02467 
02468     if( NULL != acisDumpFile )
02469         fwrite( "\n======================\nSorted acis records:\n======================\n", 1, 68, acisDumpFile );
02470 
02471     // Now interpret the records
02472     interpret_acis_records( records );
02473 
02474     if( NULL != acisDumpFile ) fclose( acisDumpFile );
02475 
02476     return MB_SUCCESS;
02477 }
02478 
02479 ErrorCode Tqdcfr::interpret_acis_records( std::vector< AcisRecord >& records )
02480 {
02481     // Make a tag for the vector holding unrecognized attributes
02482     void* default_val = NULL;
02483     ErrorCode result  = mdbImpl->tag_get_handle( "ATTRIB_VECTOR", sizeof( void* ), MB_TYPE_OPAQUE, attribVectorTag,
02484                                                  MB_TAG_CREAT | MB_TAG_SPARSE, &default_val );
02485     if( MB_SUCCESS != result ) return result;
02486 
02487     unsigned int current_record = 0;
02488 
02489 #define REC records[current_record]
02490 
02491     while( current_record != records.size() )
02492     {
02493         // If this record's been processed, or if it's an attribute, continue
02494         if( REC.processed || REC.rec_type == Tqdcfr::ATTRIB )
02495         {
02496             current_record++;
02497             continue;
02498         }
02499 
02500         if( REC.rec_type == Tqdcfr::UNKNOWN )
02501         {
02502             REC.processed = true;
02503             current_record++;
02504             continue;
02505         }
02506 
02507         // It's a known, non-attrib rec type; parse for any attribs
02508         parse_acis_attribs( current_record, records );
02509 
02510         REC.processed = true;
02511 
02512         current_record++;
02513     }
02514 
02515     return MB_SUCCESS;
02516 }
02517 
02518 ErrorCode Tqdcfr::parse_acis_attribs( const unsigned int entity_rec_num, std::vector< AcisRecord >& records )
02519 {
02520     unsigned int num_read;
02521     std::vector< std::string > attrib_vec;
02522     char temp_name[1024];
02523     char name_tag_val[NAME_TAG_SIZE];
02524     std::string name_tag;
02525     int id          = -1;
02526     int uid         = -1;
02527     int next_attrib = -1;
02528     ErrorCode result;
02529 
02530     int current_attrib = records[entity_rec_num].first_attrib;
02531     if( -1 == current_attrib ) return MB_SUCCESS;
02532 
02533     if( NULL != acisDumpFile )
02534     {
02535         fwrite( "-----------------------------------------------------------------------\n", 1, 72, acisDumpFile );
02536         fwrite( records[entity_rec_num].att_string.c_str(), sizeof( char ), records[entity_rec_num].att_string.length(),
02537                 acisDumpFile );
02538     }
02539 
02540     while( -1 != current_attrib )
02541     {
02542         if( records[current_attrib].rec_type != Tqdcfr::UNKNOWN &&
02543             ( records[current_attrib].att_next != next_attrib ||
02544               records[current_attrib].att_ent_num != (int)entity_rec_num ) )
02545             return MB_FAILURE;
02546 
02547         if( NULL != acisDumpFile )
02548             fwrite( records[current_attrib].att_string.c_str(), sizeof( char ),
02549                     records[current_attrib].att_string.length(), acisDumpFile );
02550 
02551         // Is the attrib one we already recognize?
02552         if( strncmp( records[current_attrib].att_string.c_str(), "ENTITY_NAME", 11 ) == 0 )
02553         {
02554             // Parse name
02555             int num_chars;
02556             num_read =
02557                 sscanf( records[current_attrib].att_string.c_str(), "ENTITY_NAME @%d %s", &num_chars, temp_name );
02558             if( num_read != 2 )
02559                 num_read =
02560                     sscanf( records[current_attrib].att_string.c_str(), "ENTITY_NAME %d %s", &num_chars, temp_name );
02561             if( num_read != 2 ) return MB_FAILURE;
02562 
02563             // Put the name on the entity
02564             name_tag = std::string( temp_name, num_chars );
02565         }
02566         else if( strncmp( records[current_attrib].att_string.c_str(), "ENTITY_ID", 9 ) == 0 )
02567         {
02568             // Parse id
02569             int bounding_uid, bounding_sense;
02570             num_read = sscanf( records[current_attrib].att_string.c_str(), "ENTITY_ID 0 3 %d %d %d", &id, &bounding_uid,
02571                                &bounding_sense );
02572             if( 3 != num_read )
02573             {
02574                 // Try reading updated entity_id format, which has coordinate triple embedded in it
02575                 // too
02576                 float dumx, dumy, dumz;
02577                 num_read = sscanf( records[current_attrib].att_string.c_str(), "ENTITY_ID 3 %f %f %f 3 %d %d %d", &dumx,
02578                                    &dumy, &dumz, &id, &bounding_uid, &bounding_sense );
02579                 num_read -= 3;
02580             }
02581 
02582             if( 3 != num_read )
02583                 std::cout << "Warning: bad ENTITY_ID attribute in .sat file, record number " << entity_rec_num
02584                           << ", record follows:" << std::endl
02585                           << records[current_attrib].att_string.c_str() << std::endl;
02586         }
02587         else if( strncmp( records[current_attrib].att_string.c_str(), "UNIQUE_ID", 9 ) == 0 )
02588         {
02589             // Parse uid
02590             if( major >= 14 )  // Change of format for cubit 14:
02591                 num_read = sscanf( records[current_attrib].att_string.c_str(), "UNIQUE_ID 0 1 %d", &uid );
02592             else
02593                 num_read = sscanf( records[current_attrib].att_string.c_str(), "UNIQUE_ID 1 0 1 %d", &uid );
02594             if( 1 != num_read ) return MB_FAILURE;
02595         }
02596         else if( strncmp( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 UNIQUE_ID", 29 ) == 0 )
02597         {
02598             // Parse uid
02599             int dum1, dum2, dum3, dum4;
02600             num_read = sscanf( records[current_attrib].att_string.c_str(),
02601                                "COMPOSITE_ATTRIB @9 UNIQUE_ID %d %d %d %d %d", &dum1, &dum2, &dum3, &dum4, &uid );
02602             if( 5 != num_read ) return MB_FAILURE;
02603         }
02604         else if( strncmp( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 ENTITY_ID", 29 ) == 0 )
02605         {
02606             // Parse id
02607             int dum1, dum2, dum3;
02608             num_read = sscanf( records[current_attrib].att_string.c_str(), "COMPOSITE_ATTRIB @9 ENTITY_ID %d %d %d %d",
02609                                &dum1, &dum2, &dum3, &id );
02610             if( 4 != num_read ) return MB_FAILURE;
02611         }
02612         else
02613         {
02614             attrib_vec.push_back( records[current_attrib].att_string );
02615         }
02616 
02617         records[current_attrib].processed = true;
02618         next_attrib                       = current_attrib;
02619         current_attrib                    = records[current_attrib].att_prev;
02620     }
02621 
02622     // At this point, there aren't entity sets for entity types which don't contain mesh
02623     // in this case, just return
02624     if( records[entity_rec_num].rec_type == aBODY || ( records[entity_rec_num].entity == 0 && uid == -1 ) )
02625     {
02626         return MB_SUCCESS;
02627         // Warning: couldn't resolve entity of type 1 because no uid was found.
02628         // ddriv: GeomTopoTool.cpp:172: ErrorCode GeomTopoTool::separate_by_dimension(const Range&,
02629         // Range*, void**): Assertion `false' failed. xxx
02630     }
02631 
02632     // Parsed the data; now put on mdb entities; first we need to find the entity
02633     if( records[entity_rec_num].entity == 0 )
02634     {
02635         records[entity_rec_num].entity = uidSetMap[uid];
02636     }
02637 
02638     if( 0 == records[entity_rec_num].entity ) return MB_SUCCESS;  // We do not have a MOAB entity for this, skip
02639 
02640     // assert(records[entity_rec_num].entity);
02641 
02642     // Set the id
02643     if( id != -1 )
02644     {
02645         result = mdbImpl->tag_set_data( globalIdTag, &( records[entity_rec_num].entity ), 1, &id );
02646         if( MB_SUCCESS != result ) return result;
02647 
02648         int ent_dim = -1;
02649         if( records[entity_rec_num].rec_type == aBODY )
02650             ent_dim = 4;
02651         else if( records[entity_rec_num].rec_type == LUMP )
02652             ent_dim = 3;
02653         else if( records[entity_rec_num].rec_type == FACE )
02654             ent_dim = 2;
02655         else if( records[entity_rec_num].rec_type == aEDGE )
02656             ent_dim = 1;
02657         else if( records[entity_rec_num].rec_type == aVERTEX )
02658             ent_dim = 0;
02659         if( -1 != ent_dim ) gidSetMap[ent_dim][id] = records[entity_rec_num].entity;
02660     }
02661 
02662     // Set the name
02663     if( !name_tag.empty() )
02664     {
02665         if( 0 == entityNameTag )
02666         {
02667             char dum_val[NAME_TAG_SIZE] = { 0 };
02668             result = mdbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, entityNameTag,
02669                                               MB_TAG_SPARSE | MB_TAG_CREAT, dum_val );
02670             if( MB_SUCCESS != result ) return result;
02671         }
02672 
02673         size_t len = name_tag.size();
02674         if( len >= NAME_TAG_SIZE ) len = NAME_TAG_SIZE - 1;  // Truncate a name that is too big
02675         memcpy( name_tag_val, name_tag.c_str(), len );
02676         memset( name_tag_val + len, '\0', NAME_TAG_SIZE - len );
02677         result = mdbImpl->tag_set_data( entityNameTag, &( records[entity_rec_num].entity ), 1, name_tag_val );
02678         if( MB_SUCCESS != result ) return result;
02679     }
02680 
02681     if( !attrib_vec.empty() )
02682     {
02683         // Put the attrib vector in a tag on the entity
02684         std::vector< std::string >* dum_vec;
02685         result = mdbImpl->tag_get_data( attribVectorTag, &( records[entity_rec_num].entity ), 1, &dum_vec );
02686         if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) return result;
02687         if( MB_TAG_NOT_FOUND == result || dum_vec == NULL )
02688         {
02689             // Put this list directly on the entity
02690             dum_vec = new std::vector< std::string >;
02691             dum_vec->swap( attrib_vec );
02692             result = mdbImpl->tag_set_data( attribVectorTag, &( records[entity_rec_num].entity ), 1, &dum_vec );
02693             if( MB_SUCCESS != result )
02694             {
02695                 delete dum_vec;
02696                 return result;
02697             }
02698         }
02699         else
02700         {
02701             // Copy this list over, and delete this list
02702             std::copy( attrib_vec.begin(), attrib_vec.end(), std::back_inserter( *dum_vec ) );
02703         }
02704     }
02705 
02706     return MB_SUCCESS;
02707 }
02708 
02709 ErrorCode Tqdcfr::reset_record( AcisRecord& this_record )
02710 {
02711     this_record.rec_type = Tqdcfr::UNKNOWN;
02712     this_record.att_string.clear();
02713     this_record.first_attrib = this_record.att_prev = this_record.att_next = this_record.att_ent_num = -1;
02714     this_record.processed                                                                            = false;
02715     this_record.entity                                                                               = 0;
02716 
02717     return MB_SUCCESS;
02718 }
02719 
02720 ErrorCode Tqdcfr::process_record( AcisRecord& this_record )
02721 {
02722     // Get the entity type
02723     const char* type_substr;
02724 
02725     // Try attribs first, since the others have some common processing between them
02726     if( ( type_substr = strstr( this_record.att_string.c_str(), "attrib" ) ) != NULL &&
02727         type_substr - this_record.att_string.c_str() < 20 )
02728     {
02729         this_record.rec_type = Tqdcfr::ATTRIB;
02730         bool simple_attrib   = false;
02731         bool generic_attrib  = false;
02732         if( ( type_substr = strstr( this_record.att_string.c_str(), "simple-snl-attrib" ) ) != NULL )
02733             simple_attrib = true;
02734         else if( ( type_substr = strstr( this_record.att_string.c_str(), "integer_attrib-name_attrib-gen-attrib" ) ) !=
02735                  NULL )
02736             generic_attrib = true;
02737         else
02738         {
02739             this_record.rec_type = Tqdcfr::UNKNOWN;
02740             return MB_SUCCESS;
02741         }
02742 
02743         // Find next space
02744         type_substr = strchr( type_substr, ' ' );
02745         if( NULL == type_substr ) return MB_FAILURE;
02746 
02747         // Read the numbers from there
02748         int num_converted = sscanf( type_substr, " $-1 -1 $%d $%d $%d -1", &( this_record.att_prev ),
02749                                     &( this_record.att_next ), &( this_record.att_ent_num ) );
02750         if( num_converted != 3 ) return MB_FAILURE;
02751 
02752         // Trim the string to the attribute, if it's a simple attrib
02753         if( simple_attrib )
02754         {
02755             type_substr = strstr( this_record.att_string.c_str(), "NEW_SIMPLE_ATTRIB" );
02756             if( NULL == type_substr ) return MB_FAILURE;
02757             type_substr = strstr( type_substr, "@" );
02758             if( NULL == type_substr ) return MB_FAILURE;
02759             type_substr = strstr( type_substr, " " ) + 1;
02760             // Copy the rest of the string to a dummy string
02761             std::string dum_str( type_substr );
02762             this_record.att_string = dum_str;
02763         }
02764         else if( generic_attrib )
02765         {
02766             type_substr = strstr( this_record.att_string.c_str(), "CUBIT_ID" );
02767             if( NULL == type_substr ) return MB_FAILURE;
02768             // Copy the rest of the string to a dummy string
02769             std::string dum_str( type_substr );
02770             this_record.att_string = dum_str;
02771         }
02772     }
02773     else
02774     {
02775         // Else it's a topological entity, I think
02776         if( ( type_substr = strstr( this_record.att_string.c_str(), "body" ) ) != NULL &&
02777             type_substr - this_record.att_string.c_str() < 20 )
02778         {
02779             this_record.rec_type = Tqdcfr::aBODY;
02780         }
02781         else if( ( type_substr = strstr( this_record.att_string.c_str(), "lump" ) ) != NULL &&
02782                  type_substr - this_record.att_string.c_str() < 20 )
02783         {
02784             this_record.rec_type = Tqdcfr::LUMP;
02785         }
02786         else if( ( type_substr = strstr( this_record.att_string.c_str(), "shell" ) ) != NULL &&
02787                  type_substr - this_record.att_string.c_str() < 20 )
02788         {
02789             // Don't care about shells
02790             this_record.rec_type = Tqdcfr::UNKNOWN;
02791         }
02792         else if( ( type_substr = strstr( this_record.att_string.c_str(), "surface" ) ) != NULL &&
02793                  type_substr - this_record.att_string.c_str() < 20 )
02794         {
02795             // Don't care about surfaces
02796             this_record.rec_type = Tqdcfr::UNKNOWN;
02797         }
02798         else if( ( type_substr = strstr( this_record.att_string.c_str(), "face" ) ) != NULL &&
02799                  type_substr - this_record.att_string.c_str() < 20 )
02800         {
02801             this_record.rec_type = Tqdcfr::FACE;
02802         }
02803         else if( ( type_substr = strstr( this_record.att_string.c_str(), "loop" ) ) != NULL &&
02804                  type_substr - this_record.att_string.c_str() < 20 )
02805         {
02806             // Don't care about loops
02807             this_record.rec_type = Tqdcfr::UNKNOWN;
02808         }
02809         else if( ( type_substr = strstr( this_record.att_string.c_str(), "coedge" ) ) != NULL &&
02810                  type_substr - this_record.att_string.c_str() < 20 )
02811         {
02812             // Don't care about coedges
02813             this_record.rec_type = Tqdcfr::UNKNOWN;
02814         }
02815         else if( ( type_substr = strstr( this_record.att_string.c_str(), "edge" ) ) != NULL &&
02816                  type_substr - this_record.att_string.c_str() < 20 )
02817         {
02818             this_record.rec_type = Tqdcfr::aEDGE;
02819         }
02820         else if( ( type_substr = strstr( this_record.att_string.c_str(), "vertex" ) ) != NULL &&
02821                  type_substr - this_record.att_string.c_str() < 20 )
02822         {
02823             this_record.rec_type = Tqdcfr::aVERTEX;
02824         }
02825         else
02826             this_record.rec_type = Tqdcfr::UNKNOWN;
02827 
02828         if( this_record.rec_type != Tqdcfr::UNKNOWN )
02829         {
02830             // Print a warning if it looks like there are sequence numbers
02831             if( type_substr != this_record.att_string.c_str() && !printedSeqWarning )
02832             {
02833                 std::cout << "Warning: acis file has sequence numbers!" << std::endl;
02834                 printedSeqWarning = true;
02835             }
02836 
02837             // Scan ahead to the next white space
02838             type_substr = strchr( type_substr, ' ' );
02839             if( NULL == type_substr ) return MB_FAILURE;
02840 
02841             // Get the id of the first attrib
02842             int num_converted = sscanf( type_substr, " $%d", &( this_record.first_attrib ) );
02843             if( num_converted != 1 ) return MB_FAILURE;
02844         }
02845     }
02846 
02847     return MB_SUCCESS;
02848 }
02849 
02850 Tqdcfr::FileTOC::FileTOC()
02851     : fileEndian( 0 ), fileSchema( 0 ), numModels( 0 ), modelTableOffset( 0 ), modelMetaDataOffset( 0 ),
02852       activeFEModel( 0 )
02853 {
02854 }
02855 
02856 void Tqdcfr::FileTOC::print()
02857 {
02858     std::cout << "FileTOC:End, Sch, #Mdl, TabOff, "
02859               << "MdlMDOff, actFEMdl = ";
02860     std::cout << fileEndian << ", " << fileSchema << ", " << numModels << ", " << modelTableOffset << ", "
02861               << modelMetaDataOffset << ", " << activeFEModel << std::endl;
02862 }
02863 
02864 Tqdcfr::FEModelHeader::ArrayInfo::ArrayInfo() : numEntities( 0 ), tableOffset( 0 ), metaDataOffset( 0 ) {}
02865 
02866 void Tqdcfr::FEModelHeader::ArrayInfo::print()
02867 {
02868     std::cout << "ArrayInfo:numEntities, tableOffset, metaDataOffset = " << numEntities << ", " << tableOffset << ", "
02869               << metaDataOffset << std::endl;
02870 }
02871 
02872 void Tqdcfr::FEModelHeader::ArrayInfo::init( const std::vector< unsigned int >& uint_buf_in )
02873 {
02874     numEntities    = uint_buf_in[0];
02875     tableOffset    = uint_buf_in[1];
02876     metaDataOffset = uint_buf_in[2];
02877 }
02878 
02879 void Tqdcfr::FEModelHeader::print()
02880 {
02881     std::cout << "FEModelHeader:feEndian, feSchema, feCompressFlag, feLength = " << feEndian << ", " << feSchema << ", "
02882               << feCompressFlag << ", " << feLength << std::endl;
02883     std::cout << "geomArray: ";
02884     geomArray.print();
02885     std::cout << "nodeArray: ";
02886     nodeArray.print();
02887     std::cout << "elementArray: ";
02888     elementArray.print();
02889     std::cout << "groupArray: ";
02890     groupArray.print();
02891     std::cout << "blockArray: ";
02892     blockArray.print();
02893     std::cout << "nodesetArray: ";
02894     nodesetArray.print();
02895     std::cout << "sidesetArray: ";
02896     sidesetArray.print();
02897 }
02898 
02899 Tqdcfr::GeomHeader::GeomHeader()
02900     : geomID( 0 ), nodeCt( 0 ), nodeOffset( 0 ), elemCt( 0 ), elemOffset( 0 ), elemTypeCt( 0 ), elemLength( 0 ),
02901       maxDim( 0 ), setHandle( 0 )
02902 {
02903 }
02904 
02905 void Tqdcfr::GeomHeader::print()
02906 {
02907     std::cout << "geomID = " << geomID << std::endl;
02908     std::cout << "nodeCt = " << nodeCt << std::endl;
02909     std::cout << "nodeOffset = " << nodeOffset << std::endl;
02910     std::cout << "elemCt = " << elemCt << std::endl;
02911     std::cout << "elemOffset = " << elemOffset << std::endl;
02912     std::cout << "elemTypeCt = " << elemTypeCt << std::endl;
02913     std::cout << "elemLength = " << elemLength << std::endl;
02914     std::cout << "setHandle = " << setHandle << std::endl;
02915 }
02916 
02917 Tqdcfr::GroupHeader::GroupHeader()
02918     : grpID( 0 ), grpType( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), grpLength( 0 ), setHandle( 0 )
02919 {
02920 }
02921 
02922 void Tqdcfr::GroupHeader::print()
02923 {
02924     std::cout << "grpID = " << grpID << std::endl;
02925     std::cout << "grpType = " << grpType << std::endl;
02926     std::cout << "memCt = " << memCt << std::endl;
02927     std::cout << "memOffset = " << memOffset << std::endl;
02928     std::cout << "memTypeCt = " << memTypeCt << std::endl;
02929     std::cout << "grpLength = " << grpLength << std::endl;
02930     std::cout << "setHandle = " << setHandle << std::endl;
02931 }
02932 
02933 Tqdcfr::BlockHeader::BlockHeader()
02934     : blockID( 0 ), blockElemType( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), attribOrder( 0 ), blockCol( 0 ),
02935       blockMixElemType( 0 ), blockPyrType( 0 ), blockMat( 0 ), blockLength( 0 ), blockDim( 0 ), setHandle( 0 ),
02936       blockEntityType( MBMAXTYPE )
02937 {
02938 }
02939 
02940 void Tqdcfr::BlockHeader::print()
02941 {
02942     std::cout << "blockID = " << blockID << std::endl;
02943     std::cout << "blockElemType = " << blockElemType << std::endl;
02944     std::cout << "memCt = " << memCt << std::endl;
02945     std::cout << "memOffset = " << memOffset << std::endl;
02946     std::cout << "memTypeCt = " << memTypeCt << std::endl;
02947     std::cout << "attribOrder = " << attribOrder << std::endl;
02948     std::cout << "blockCol = " << blockCol << std::endl;
02949     std::cout << "blockMixElemType = " << blockMixElemType << std::endl;
02950     std::cout << "blockPyrType = " << blockPyrType << std::endl;
02951     std::cout << "blockMat = " << blockMat << std::endl;
02952     std::cout << "blockLength = " << blockLength << std::endl;
02953     std::cout << "blockDim = " << blockDim << std::endl;
02954     std::cout << "setHandle = " << setHandle << std::endl;
02955     std::cout << "blockEntityType = " << blockEntityType << std::endl;
02956 }
02957 
02958 Tqdcfr::NodesetHeader::NodesetHeader()
02959     : nsID( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), pointSym( 0 ), nsCol( 0 ), nsLength( 0 ), setHandle( 0 )
02960 {
02961 }
02962 
02963 void Tqdcfr::NodesetHeader::print()
02964 {
02965     std::cout << "nsID = " << nsID << std::endl;
02966     std::cout << "memCt = " << memCt << std::endl;
02967     std::cout << "memOffset = " << memOffset << std::endl;
02968     std::cout << "memTypeCt = " << memTypeCt << std::endl;
02969     std::cout << "pointSym = " << pointSym << std::endl;
02970     std::cout << "nsCol = " << nsCol << std::endl;
02971     std::cout << "nsLength = " << nsLength << std::endl;
02972     std::cout << "setHandle = " << setHandle << std::endl;
02973 }
02974 
02975 Tqdcfr::SidesetHeader::SidesetHeader()
02976     : ssID( 0 ), memCt( 0 ), memOffset( 0 ), memTypeCt( 0 ), numDF( 0 ), ssCol( 0 ), useShell( 0 ), ssLength( 0 ),
02977       setHandle( 0 )
02978 {
02979 }
02980 
02981 void Tqdcfr::SidesetHeader::print()
02982 {
02983     std::cout << "ssID = " << ssID << std::endl;
02984     std::cout << "memCt = " << memCt << std::endl;
02985     std::cout << "memOffset = " << memOffset << std::endl;
02986     std::cout << "memTypeCt = " << memTypeCt << std::endl;
02987     std::cout << "numDF = " << numDF << std::endl;
02988     std::cout << "ssCol = " << ssCol << std::endl;
02989     std::cout << "useShell = " << useShell << std::endl;
02990     std::cout << "ssLength = " << ssLength << std::endl;
02991     std::cout << "setHandle = " << setHandle << std::endl;
02992 }
02993 
02994 Tqdcfr::MetaDataContainer::MetaDataEntry::MetaDataEntry()
02995     : mdOwner( 0 ), mdDataType( 0 ), mdIntValue( 0 ), mdName( "(uninit)" ), mdStringValue( "(uninit)" ), mdDblValue( 0 )
02996 {
02997 }
02998 
02999 void Tqdcfr::MetaDataContainer::MetaDataEntry::print()
03000 {
03001     std::cout << "MetaDataEntry:own, typ, name, I, D, S = " << mdOwner << ", " << mdDataType << ", " << mdName << ", "
03002               << mdIntValue << ", " << mdDblValue << ", " << mdStringValue;
03003     unsigned int i;
03004     if( mdIntArrayValue.size() )
03005     {
03006         std::cout << std::endl << "IArray = " << mdIntArrayValue[0];
03007         for( i = 1; i < mdIntArrayValue.size(); i++ )
03008             std::cout << ", " << mdIntArrayValue[i];
03009     }
03010     if( mdDblArrayValue.size() )
03011     {
03012         std::cout << std::endl << "DArray = " << mdDblArrayValue[0];
03013         for( i = 1; i < mdDblArrayValue.size(); i++ )
03014             std::cout << ", " << mdDblArrayValue[i];
03015     }
03016     std::cout << std::endl;
03017 }
03018 
03019 void Tqdcfr::MetaDataContainer::print()
03020 {
03021     std::cout << "MetaDataContainer:mdSchema, compressFlag, numDatums = " << mdSchema << ", " << compressFlag << ", "
03022               << metadataEntries.size() << std::endl;
03023 
03024     for( unsigned int i = 0; i < metadataEntries.size(); i++ )
03025         metadataEntries[i].print();
03026 }
03027 
03028 Tqdcfr::MetaDataContainer::MetaDataContainer() : mdSchema( 0 ), compressFlag( 0 ) {}
03029 
03030 int Tqdcfr::MetaDataContainer::get_md_entry( const unsigned int owner, const std::string& name )
03031 {
03032     for( unsigned int i = 0; i < metadataEntries.size(); i++ )
03033     {
03034         if( owner == metadataEntries[i].mdOwner && name == metadataEntries[i].mdName ) return i;
03035     }
03036 
03037     return -1;
03038 }
03039 
03040 Tqdcfr::ModelEntry::ModelEntry()
03041     : modelHandle( 0 ), modelOffset( 0 ), modelLength( 0 ), modelType( 0 ), modelOwner( 0 ), modelPad( 0 ),
03042       feGeomH( NULL ), feGroupH( NULL ), feBlockH( NULL ), feNodeSetH( NULL ), feSideSetH( NULL )
03043 {
03044 }
03045 
03046 Tqdcfr::ModelEntry::~ModelEntry()
03047 {
03048     delete[] feGeomH;
03049     delete[] feGroupH;
03050     delete[] feBlockH;
03051     delete[] feNodeSetH;
03052     delete[] feSideSetH;
03053 }
03054 
03055 void Tqdcfr::ModelEntry::print()
03056 {
03057     std::cout << "ModelEntry: Han, Of, Len, Tp, Own, Pd = " << modelHandle << ", " << modelOffset << ", " << modelLength
03058               << ", " << modelType << ", " << modelOwner << ", " << modelPad << std::endl;
03059 }
03060 
03061 ErrorCode Tqdcfr::create_set( EntityHandle& h, unsigned int flags )
03062 {
03063     return mdbImpl->create_meshset( flags, h );
03064 }
03065 
03066 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines