MOAB: Mesh Oriented datABase  (version 5.4.0)
ReadCGNS.cpp
Go to the documentation of this file.
00001 /**
00002  * \class ReadCGNS
00003  * \brief Template for writing a new reader in MOAB
00004  *
00005  */
00006 
00007 #include "ReadCGNS.hpp"
00008 #include "Internals.hpp"
00009 #include "moab/Interface.hpp"
00010 #include "moab/ReadUtilIface.hpp"
00011 #include "moab/Range.hpp"
00012 #include "moab/FileOptions.hpp"
00013 #include "MBTagConventions.hpp"
00014 #include "MBParallelConventions.h"
00015 #include "moab/CN.hpp"
00016 
00017 #include <cstdio>
00018 #include <cassert>
00019 #include <cerrno>
00020 #include <map>
00021 #include <set>
00022 
00023 #include <iostream>
00024 #include <cmath>
00025 
00026 namespace moab
00027 {
00028 
00029 ReaderIface* ReadCGNS::factory( Interface* iface )
00030 {
00031     return new ReadCGNS( iface );
00032 }
00033 
00034 ReadCGNS::ReadCGNS( Interface* impl ) : fileName( NULL ), mesh_dim( 0 ), mbImpl( impl ), globalId( 0 ), boundary( 0 )
00035 {
00036     mbImpl->query_interface( readMeshIface );
00037 }
00038 
00039 ReadCGNS::~ReadCGNS()
00040 {
00041     if( readMeshIface )
00042     {
00043         mbImpl->release_interface( readMeshIface );
00044         readMeshIface = 0;
00045     }
00046 }
00047 
00048 ErrorCode ReadCGNS::read_tag_values( const char* /* file_name */,
00049                                      const char* /* tag_name */,
00050                                      const FileOptions& /* opts */,
00051                                      std::vector< int >& /* tag_values_out */,
00052                                      const SubsetList* /* subset_list */ )
00053 {
00054     return MB_NOT_IMPLEMENTED;
00055 }
00056 
00057 ErrorCode ReadCGNS::load_file( const char* filename,
00058                                const EntityHandle* /*file_set*/,
00059                                const FileOptions& opts,
00060                                const ReaderIface::SubsetList* subset_list,
00061                                const Tag* file_id_tag )
00062 {
00063     int num_material_sets        = 0;
00064     const int* material_set_list = 0;
00065 
00066     if( subset_list )
00067     {
00068         if( subset_list->tag_list_length > 1 && !strcmp( subset_list->tag_list[0].tag_name, MATERIAL_SET_TAG_NAME ) )
00069         {
00070             MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "CGNS supports subset read only by material ID" );
00071         }
00072         material_set_list = subset_list->tag_list[0].tag_values;
00073         num_material_sets = subset_list->tag_list[0].num_tag_values;
00074     }
00075 
00076     ErrorCode result;
00077 
00078     geomSets.clear();
00079     globalId = mbImpl->globalId_tag();
00080 
00081     // Create set for more convenient check for material set ids
00082     std::set< int > blocks;
00083     for( const int* mat_set_end = material_set_list + num_material_sets; material_set_list != mat_set_end;
00084          ++material_set_list )
00085         blocks.insert( *material_set_list );
00086 
00087     // Map of ID->handle for nodes
00088     std::map< long, EntityHandle > node_id_map;
00089 
00090     // Save filename to member variable so we don't need to pass as an argument
00091     // to called functions
00092     fileName = filename;
00093 
00094     // Process options; see src/FileOptions.hpp for API for FileOptions class, and
00095     // doc/metadata_info.doc for a description of various options used by some of the readers in
00096     // MOAB
00097     result = process_options( opts );MB_CHK_SET_ERR( result, fileName << ": problem reading options" );
00098 
00099     // Open file
00100     int filePtr = 0;
00101 
00102     cg_open( filename, CG_MODE_READ, &filePtr );
00103 
00104     if( filePtr <= 0 )
00105     {
00106         MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, fileName << ": fopen returned error" );
00107     }
00108 
00109     // Read number of verts, elements, sets
00110     long num_verts = 0, num_elems = 0, num_sets = 0;
00111     int num_bases = 0, num_zones = 0, num_sections = 0;
00112 
00113     char zoneName[128];
00114     cgsize_t size[3];
00115 
00116     mesh_dim = 3;  // Default to 3D
00117 
00118     // Read number of bases;
00119     cg_nbases( filePtr, &num_bases );
00120 
00121     if( num_bases > 1 )
00122     {
00123         MB_SET_ERR( MB_NOT_IMPLEMENTED, fileName << ": support for number of bases > 1 not implemented" );
00124     }
00125 
00126     for( int indexBase = 1; indexBase <= num_bases; ++indexBase )
00127     {
00128         // Get the number of zones/blocks in current base.
00129         cg_nzones( filePtr, indexBase, &num_zones );
00130 
00131         if( num_zones > 1 )
00132         {
00133             MB_SET_ERR( MB_NOT_IMPLEMENTED, fileName << ": support for number of zones > 1 not implemented" );
00134         }
00135 
00136         for( int indexZone = 1; indexZone <= num_zones; ++indexZone )
00137         {
00138             // Get zone name and size.
00139             cg_zone_read( filePtr, indexBase, indexZone, zoneName, size );
00140 
00141             // Read number of sections/Parts in current zone.
00142             cg_nsections( filePtr, indexBase, indexZone, &num_sections );
00143 
00144             num_verts = size[0];
00145             num_elems = size[1];
00146             num_sets  = num_sections;
00147 
00148             std::cout << "\nnumber of nodes = " << num_verts;
00149             std::cout << "\nnumber of elems = " << num_elems;
00150             std::cout << "\nnumber of parts = " << num_sets << std::endl;
00151 
00152             // //////////////////////////////////
00153             // Read Nodes
00154 
00155             // Allocate nodes; these are allocated in one shot, get contiguous handles starting with
00156             // start_handle, and the reader is passed back double*'s pointing to MOAB's native
00157             // storage for vertex coordinates for those verts
00158             std::vector< double* > coord_arrays;
00159             EntityHandle handle = 0;
00160             result              = readMeshIface->get_node_coords( 3, num_verts, MB_START_ID, handle, coord_arrays );MB_CHK_SET_ERR( result, fileName << ": Trouble reading vertices" );
00161 
00162             // Fill in vertex coordinate arrays
00163             cgsize_t beginPos = 1, endPos = num_verts;
00164 
00165             // Read nodes coordinates.
00166             cg_coord_read( filePtr, indexBase, indexZone, "CoordinateX", RealDouble, &beginPos, &endPos,
00167                            coord_arrays[0] );
00168             cg_coord_read( filePtr, indexBase, indexZone, "CoordinateY", RealDouble, &beginPos, &endPos,
00169                            coord_arrays[1] );
00170             cg_coord_read( filePtr, indexBase, indexZone, "CoordinateZ", RealDouble, &beginPos, &endPos,
00171                            coord_arrays[2] );
00172 
00173             // CGNS seems to always include the Z component, even if the mesh is 2D.
00174             // Check if Z is zero and determine mesh dimension.
00175             // Also create the node_id_map data.
00176             double sumZcoord = 0.0;
00177             double eps       = 1.0e-12;
00178             for( long i = 0; i < num_verts; ++i, ++handle )
00179             {
00180                 int index = i + 1;
00181 
00182                 node_id_map.insert( std::pair< long, EntityHandle >( index, handle ) ).second;
00183 
00184                 sumZcoord += *( coord_arrays[2] + i );
00185             }
00186             if( std::abs( sumZcoord ) <= eps ) mesh_dim = 2;
00187 
00188             // Create reverse map from handle to id
00189             std::vector< int > ids( num_verts );
00190             std::vector< int >::iterator id_iter = ids.begin();
00191             std::vector< EntityHandle > handles( num_verts );
00192             std::vector< EntityHandle >::iterator h_iter = handles.begin();
00193             for( std::map< long, EntityHandle >::iterator i = node_id_map.begin(); i != node_id_map.end();
00194                  ++i, ++id_iter, ++h_iter )
00195             {
00196                 *id_iter = i->first;
00197                 *h_iter  = i->second;
00198             }
00199             // Store IDs in tags
00200             result = mbImpl->tag_set_data( globalId, &handles[0], num_verts, &ids[0] );
00201             if( MB_SUCCESS != result ) return result;
00202             if( file_id_tag )
00203             {
00204                 result = mbImpl->tag_set_data( *file_id_tag, &handles[0], num_verts, &ids[0] );
00205                 if( MB_SUCCESS != result ) return result;
00206             }
00207             ids.clear();
00208             handles.clear();
00209 
00210             // //////////////////////////////////
00211             // Read elements data
00212 
00213             EntityType ent_type;
00214 
00215             long section_offset = 0;
00216 
00217             // Define which mesh parts are volume families.
00218             // Mesh parts with volumeID[X] = 0 are boundary parts.
00219             std::vector< int > volumeID( num_sections, 0 );
00220 
00221             for( int section = 0; section < num_sections; ++section )
00222             {
00223                 ElementType_t elemsType;
00224                 int iparent_flag, nbndry;
00225                 char sectionName[128];
00226                 int verts_per_elem;
00227 
00228                 int cgSection = section + 1;
00229 
00230                 cg_section_read( filePtr, indexBase, indexZone, cgSection, sectionName, &elemsType, &beginPos, &endPos,
00231                                  &nbndry, &iparent_flag );
00232 
00233                 size_t section_size = endPos - beginPos + 1;
00234 
00235                 // Read element description in current section
00236 
00237                 switch( elemsType )
00238                 {
00239                     case BAR_2:
00240                         ent_type       = MBEDGE;
00241                         verts_per_elem = 2;
00242                         break;
00243                     case TRI_3:
00244                         ent_type       = MBTRI;
00245                         verts_per_elem = 3;
00246                         if( mesh_dim == 2 ) volumeID[section] = 1;
00247                         break;
00248                     case QUAD_4:
00249                         ent_type       = MBQUAD;
00250                         verts_per_elem = 4;
00251                         if( mesh_dim == 2 ) volumeID[section] = 1;
00252                         break;
00253                     case TETRA_4:
00254                         ent_type       = MBTET;
00255                         verts_per_elem = 4;
00256                         if( mesh_dim == 3 ) volumeID[section] = 1;
00257                         break;
00258                     case PYRA_5:
00259                         ent_type       = MBPYRAMID;
00260                         verts_per_elem = 5;
00261                         if( mesh_dim == 3 ) volumeID[section] = 1;
00262                         break;
00263                     case PENTA_6:
00264                         ent_type       = MBPRISM;
00265                         verts_per_elem = 6;
00266                         if( mesh_dim == 3 ) volumeID[section] = 1;
00267                         break;
00268                     case HEXA_8:
00269                         ent_type       = MBHEX;
00270                         verts_per_elem = 8;
00271                         if( mesh_dim == 3 ) volumeID[section] = 1;
00272                         break;
00273                     case MIXED:
00274                         ent_type       = MBMAXTYPE;
00275                         verts_per_elem = 0;
00276                         break;
00277                     default:
00278                         MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
00279                 }
00280 
00281                 if( elemsType == TETRA_4 || elemsType == PYRA_5 || elemsType == PENTA_6 || elemsType == HEXA_8 ||
00282                     elemsType == TRI_3 || elemsType == QUAD_4 || ( ( elemsType == BAR_2 ) && mesh_dim == 2 ) )
00283                 {
00284                     // Read connectivity into conn_array directly
00285 
00286                     cgsize_t iparentdata;
00287                     cgsize_t connDataSize;
00288 
00289                     // Get number of entries on the connectivity list for this section
00290                     cg_ElementDataSize( filePtr, indexBase, indexZone, cgSection, &connDataSize );
00291 
00292                     // Need a temporary vector to later cast to conn_array.
00293                     std::vector< cgsize_t > elemNodes( connDataSize );
00294 
00295                     cg_elements_read( filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata );
00296 
00297                     // //////////////////////////////////
00298                     // Create elements, sets and tags
00299 
00300                     create_elements( sectionName, file_id_tag, ent_type, verts_per_elem, section_offset, section_size,
00301                                      elemNodes );
00302                 }  // Homogeneous mesh type
00303                 else if( elemsType == MIXED )
00304                 {
00305                     // We must first sort all elements connectivities into continuous vectors
00306 
00307                     cgsize_t connDataSize;
00308                     cgsize_t iparentdata;
00309 
00310                     cg_ElementDataSize( filePtr, indexBase, indexZone, cgSection, &connDataSize );
00311 
00312                     std::vector< cgsize_t > elemNodes( connDataSize );
00313 
00314                     cg_elements_read( filePtr, indexBase, indexZone, cgSection, &elemNodes[0], &iparentdata );
00315 
00316                     std::vector< cgsize_t > elemsConn_EDGE;
00317                     std::vector< cgsize_t > elemsConn_TRI, elemsConn_QUAD;
00318                     std::vector< cgsize_t > elemsConn_TET, elemsConn_PYRA, elemsConn_PRISM, elemsConn_HEX;
00319                     cgsize_t count_EDGE, count_TRI, count_QUAD;
00320                     cgsize_t count_TET, count_PYRA, count_PRISM, count_HEX;
00321 
00322                     // First, get elements count for current section
00323 
00324                     count_EDGE = count_TRI = count_QUAD = 0;
00325                     count_TET = count_PYRA = count_PRISM = count_HEX = 0;
00326 
00327                     int connIndex = 0;
00328                     for( int i = beginPos; i <= endPos; i++ )
00329                     {
00330                         elemsType = ElementType_t( elemNodes[connIndex] );
00331 
00332                         // Get current cell node count.
00333                         cg_npe( elemsType, &verts_per_elem );
00334 
00335                         switch( elemsType )
00336                         {
00337                             case BAR_2:
00338                                 count_EDGE += 1;
00339                                 break;
00340                             case TRI_3:
00341                                 count_TRI += 1;
00342                                 break;
00343                             case QUAD_4:
00344                                 count_QUAD += 1;
00345                                 break;
00346                             case TETRA_4:
00347                                 count_TET += 1;
00348                                 break;
00349                             case PYRA_5:
00350                                 count_PYRA += 1;
00351                                 break;
00352                             case PENTA_6:
00353                                 count_PRISM += 1;
00354                                 break;
00355                             case HEXA_8:
00356                                 count_HEX += 1;
00357                                 break;
00358                             default:
00359                                 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
00360                         }
00361 
00362                         connIndex += ( verts_per_elem + 1 );  // Add one to skip next element descriptor
00363                     }
00364 
00365                     if( count_EDGE > 0 ) elemsConn_EDGE.resize( count_EDGE * 2 );
00366                     if( count_TRI > 0 ) elemsConn_TRI.resize( count_TRI * 3 );
00367                     if( count_QUAD > 0 ) elemsConn_QUAD.resize( count_QUAD * 4 );
00368                     if( count_TET > 0 ) elemsConn_TET.resize( count_TET * 4 );
00369                     if( count_PYRA > 0 ) elemsConn_PYRA.resize( count_PYRA * 5 );
00370                     if( count_PRISM > 0 ) elemsConn_PRISM.resize( count_PRISM * 6 );
00371                     if( count_HEX > 0 ) elemsConn_HEX.resize( count_HEX * 8 );
00372 
00373                     // Grab mixed section elements connectivity
00374 
00375                     int idx_edge, idx_tri, idx_quad;
00376                     int idx_tet, idx_pyra, idx_prism, idx_hex;
00377                     idx_edge = idx_tri = idx_quad = 0;
00378                     idx_tet = idx_pyra = idx_prism = idx_hex = 0;
00379 
00380                     connIndex = 0;
00381                     for( int i = beginPos; i <= endPos; i++ )
00382                     {
00383                         elemsType = ElementType_t( elemNodes[connIndex] );
00384 
00385                         // Get current cell node count.
00386                         cg_npe( elemsType, &verts_per_elem );
00387 
00388                         switch( elemsType )
00389                         {
00390                             case BAR_2:
00391                                 for( int j = 0; j < 2; ++j )
00392                                     elemsConn_EDGE[idx_edge + j] = elemNodes[connIndex + j + 1];
00393                                 idx_edge += 2;
00394                                 break;
00395                             case TRI_3:
00396                                 for( int j = 0; j < 3; ++j )
00397                                     elemsConn_TRI[idx_tri + j] = elemNodes[connIndex + j + 1];
00398                                 idx_tri += 3;
00399                                 break;
00400                             case QUAD_4:
00401                                 for( int j = 0; j < 4; ++j )
00402                                     elemsConn_QUAD[idx_quad + j] = elemNodes[connIndex + j + 1];
00403                                 idx_quad += 4;
00404                                 break;
00405                             case TETRA_4:
00406                                 for( int j = 0; j < 4; ++j )
00407                                     elemsConn_TET[idx_tet + j] = elemNodes[connIndex + j + 1];
00408                                 idx_tet += 4;
00409                                 break;
00410                             case PYRA_5:
00411                                 for( int j = 0; j < 5; ++j )
00412                                     elemsConn_PYRA[idx_pyra + j] = elemNodes[connIndex + j + 1];
00413                                 idx_pyra += 5;
00414                                 break;
00415                             case PENTA_6:
00416                                 for( int j = 0; j < 6; ++j )
00417                                     elemsConn_PRISM[idx_prism + j] = elemNodes[connIndex + j + 1];
00418                                 idx_prism += 6;
00419                                 break;
00420                             case HEXA_8:
00421                                 for( int j = 0; j < 8; ++j )
00422                                     elemsConn_HEX[idx_hex + j] = elemNodes[connIndex + j + 1];
00423                                 idx_hex += 8;
00424                                 break;
00425                             default:
00426                                 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, fileName << ": Trouble determining element type" );
00427                         }
00428 
00429                         connIndex += ( verts_per_elem + 1 );  // Add one to skip next element descriptor
00430                     }
00431 
00432                     // //////////////////////////////////
00433                     // Create elements, sets and tags
00434 
00435                     if( count_EDGE > 0 )
00436                         create_elements( sectionName, file_id_tag, MBEDGE, 2, section_offset, count_EDGE,
00437                                          elemsConn_EDGE );
00438 
00439                     if( count_TRI > 0 )
00440                         create_elements( sectionName, file_id_tag, MBTRI, 3, section_offset, count_TRI, elemsConn_TRI );
00441 
00442                     if( count_QUAD > 0 )
00443                         create_elements( sectionName, file_id_tag, MBQUAD, 4, section_offset, count_QUAD,
00444                                          elemsConn_QUAD );
00445 
00446                     if( count_TET > 0 )
00447                         create_elements( sectionName, file_id_tag, MBTET, 4, section_offset, count_TET, elemsConn_TET );
00448 
00449                     if( count_PYRA > 0 )
00450                         create_elements( sectionName, file_id_tag, MBPYRAMID, 5, section_offset, count_PYRA,
00451                                          elemsConn_PYRA );
00452 
00453                     if( count_PRISM > 0 )
00454                         create_elements( sectionName, file_id_tag, MBPRISM, 6, section_offset, count_PRISM,
00455                                          elemsConn_PRISM );
00456 
00457                     if( count_HEX > 0 )
00458                         create_elements( sectionName, file_id_tag, MBHEX, 8, section_offset, count_HEX, elemsConn_HEX );
00459                 }  // Mixed mesh type
00460             }      // num_sections
00461 
00462             cg_close( filePtr );
00463 
00464             return result;
00465         }  // indexZone for
00466     }      // indexBase for
00467 
00468     return MB_SUCCESS;
00469 }
00470 
00471 ErrorCode ReadCGNS::create_elements( char* sectionName,
00472                                      const Tag* file_id_tag,
00473                                      const EntityType& ent_type,
00474                                      const int& verts_per_elem,
00475                                      long& section_offset,
00476                                      int elems_count,
00477                                      const std::vector< cgsize_t >& elemsConn )
00478 {
00479     ErrorCode result;
00480 
00481     // Create the element sequence; passes back a pointer to the internal storage for connectivity
00482     // and the starting entity handle
00483     EntityHandle* conn_array;
00484     EntityHandle handle = 0;
00485 
00486     result = readMeshIface->get_element_connect( elems_count, verts_per_elem, ent_type, 1, handle, conn_array );MB_CHK_SET_ERR( result, fileName << ": Trouble reading elements" );
00487 
00488     if( sizeof( EntityHandle ) == sizeof( cgsize_t ) )
00489     {
00490         memcpy( conn_array, &elemsConn[0], elemsConn.size() * sizeof( EntityHandle ) );
00491     }
00492     else
00493     {  // if CGNS is compiled without 64bit enabled
00494         std::vector< EntityHandle > elemsConnTwin( elemsConn.size(), 0 );
00495         for( int i = 0; i < elemsConn.size(); i++ )
00496         {
00497             elemsConnTwin[i] = static_cast< EntityHandle >( elemsConn[i] );
00498         }
00499         memcpy( conn_array, &elemsConnTwin[0], elemsConnTwin.size() * sizeof( EntityHandle ) );
00500     }
00501 
00502     // Notify MOAB of the new elements
00503     result = readMeshIface->update_adjacencies( handle, elems_count, verts_per_elem, conn_array );
00504     if( MB_SUCCESS != result ) return result;
00505 
00506     // //////////////////////////////////
00507     // Create sets and tags
00508 
00509     Range elements( handle, handle + elems_count - 1 );
00510 
00511     // Store element IDs
00512 
00513     std::vector< int > id_list( elems_count );
00514 
00515     // Add 1 to offset id to 1-based numbering
00516     for( cgsize_t i = 0; i < elems_count; ++i )
00517         id_list[i] = i + 1 + section_offset;
00518     section_offset += elems_count;
00519 
00520     create_sets( sectionName, file_id_tag, ent_type, elements, id_list, 0 );
00521 
00522     return MB_SUCCESS;
00523 }
00524 
00525 ErrorCode ReadCGNS::create_sets( char* sectionName,
00526                                  const Tag* file_id_tag,
00527                                  EntityType /*element_type*/,
00528                                  const Range& elements,
00529                                  const std::vector< int >& set_ids,
00530                                  int /*set_type*/ )
00531 {
00532     ErrorCode result;
00533 
00534     result = mbImpl->tag_set_data( globalId, elements, &set_ids[0] );
00535     if( MB_SUCCESS != result ) return result;
00536 
00537     if( file_id_tag )
00538     {
00539         result = mbImpl->tag_set_data( *file_id_tag, elements, &set_ids[0] );
00540         if( MB_SUCCESS != result ) return result;
00541     }
00542 
00543     EntityHandle set_handle;
00544 
00545     Tag tag_handle;
00546 
00547     const char* setName = sectionName;
00548 
00549     mbImpl->tag_get_handle( setName, 1, MB_TYPE_INTEGER, tag_handle, MB_TAG_SPARSE | MB_TAG_CREAT );
00550 
00551     // Create set
00552     result = mbImpl->create_meshset( MESHSET_SET, set_handle );MB_CHK_SET_ERR( result, fileName << ": Trouble creating set" );
00553 
00554     //// Add dummy values to current set
00555     // std::vector<int> tags(set_ids.size(), 1);
00556     // result = mbImpl->tag_set_data(tag_handle, elements, &tags[0]);
00557     // if (MB_SUCCESS != result) return result;
00558 
00559     // Add them to the set
00560     result = mbImpl->add_entities( set_handle, elements );MB_CHK_SET_ERR( result, fileName << ": Trouble putting entities in set" );
00561 
00562     return MB_SUCCESS;
00563 }
00564 
00565 ErrorCode ReadCGNS::process_options( const FileOptions& opts )
00566 {
00567     // Mark all options seen, to avoid compile warning on unused variable
00568     opts.mark_all_seen();
00569 
00570     return MB_SUCCESS;
00571 }
00572 
00573 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines