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