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