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