![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
Gmsh (http://www.geuz.org/gmsh) file reader. More...
#include <ReadGmsh.hpp>
Public Member Functions | |
ErrorCode | load_file (const char *file_name, const EntityHandle *file_set, const FileOptions &opts, const SubsetList *subset_list=0, const Tag *file_id_tag=0) |
Load mesh from a file. | |
ErrorCode | read_tag_values (const char *file_name, const char *tag_name, const FileOptions &opts, std::vector< int > &tag_values_out, const SubsetList *subset_list=0) |
Read tag values from a file. | |
ReadGmsh (Interface *impl=NULL) | |
Constructor. | |
virtual | ~ReadGmsh () |
Destructor. | |
Static Public Member Functions | |
static ReaderIface * | factory (Interface *) |
factory method | |
Private Member Functions | |
ErrorCode | create_elements (const GmshElemType &type, const std::vector< int > &elem_ids, const std::vector< int > &matl_ids, const std::vector< int > &geom_ids, const std::vector< int > &prtn_ids, const std::vector< EntityHandle > &connectivity, const Tag *file_id_tag) |
Create an element sequence. | |
ErrorCode | create_sets (EntityType element_type, const Range &elements, const std::vector< int > &set_ids, int set_type) |
Add elements to sets as dictated by grouping ID in file. | |
ErrorCode | create_geometric_topology () |
NOT IMPLEMENTED Reconstruct parent-child relations for geometry sets from mesh connectivity. | |
Private Attributes | |
ReadUtilIface * | readMeshIface |
Interface * | mdbImpl |
interface instance | |
Tag | globalId |
Range | geomSets |
Gmsh (http://www.geuz.org/gmsh) file reader.
Definition at line 33 of file ReadGmsh.hpp.
ReadGmsh::ReadGmsh | ( | Interface * | impl = NULL | ) |
Constructor.
Definition at line 49 of file ReadGmsh.cpp.
References mdbImpl, moab::Interface::query_interface(), and readMeshIface.
Referenced by factory().
: mdbImpl( impl ), globalId( 0 )
{
mdbImpl->query_interface( readMeshIface );
}
ReadGmsh::~ReadGmsh | ( | ) | [virtual] |
Destructor.
Definition at line 54 of file ReadGmsh.cpp.
References mdbImpl, readMeshIface, and moab::Interface::release_interface().
{
if( readMeshIface )
{
mdbImpl->release_interface( readMeshIface );
readMeshIface = 0;
}
}
ErrorCode ReadGmsh::create_elements | ( | const GmshElemType & | type, |
const std::vector< int > & | elem_ids, | ||
const std::vector< int > & | matl_ids, | ||
const std::vector< int > & | geom_ids, | ||
const std::vector< int > & | prtn_ids, | ||
const std::vector< EntityHandle > & | connectivity, | ||
const Tag * | file_id_tag | ||
) | [private] |
Create an element sequence.
Definition at line 325 of file ReadGmsh.cpp.
References create_sets(), ErrorCode, moab::ReadUtilIface::get_element_connect(), globalId, moab::Range::insert(), MB_START_ID, MB_SUCCESS, moab::GmshElemType::mb_type, MBVERTEX, mdbImpl, moab::GmshElemType::node_order, moab::GmshElemType::num_nodes, readMeshIface, moab::Interface::tag_set_data(), and moab::ReadUtilIface::update_adjacencies().
Referenced by load_file().
{
ErrorCode result;
// Make sure input is consistent
const unsigned long num_elem = elem_ids.size();
const int node_per_elem = type.num_nodes;
if( matl_ids.size() != num_elem || geom_ids.size() != num_elem || prtn_ids.size() != num_elem ||
connectivity.size() != num_elem * node_per_elem )
return MB_FAILURE;
// Create the element sequence
// for points, simply gather the connectivities and create the materials
if( type.mb_type == MBVERTEX )
{
Range elements;
elements.insert< std::vector< EntityHandle > >( connectivity.begin(), connectivity.end() );
result = create_sets( type.mb_type, elements, matl_ids, 0 );
if( MB_SUCCESS != result ) return result;
return MB_SUCCESS;
}
EntityHandle handle = 0;
EntityHandle* conn_array;
result =
readMeshIface->get_element_connect( num_elem, node_per_elem, type.mb_type, MB_START_ID, handle, conn_array );
if( MB_SUCCESS != result ) return result;
// Copy passed element connectivity into entity sequence data.
if( type.node_order )
{
for( unsigned long i = 0; i < num_elem; ++i )
for( int j = 0; j < node_per_elem; ++j )
conn_array[i * node_per_elem + type.node_order[j]] = connectivity[i * node_per_elem + j];
}
else
{
memcpy( conn_array, &connectivity[0], connectivity.size() * sizeof( EntityHandle ) );
}
// Notify MOAB of the new elements
result = readMeshIface->update_adjacencies( handle, num_elem, node_per_elem, conn_array );
if( MB_SUCCESS != result ) return result;
// Store element IDs
Range elements( handle, handle + num_elem - 1 );
result = mdbImpl->tag_set_data( globalId, elements, &elem_ids[0] );
if( MB_SUCCESS != result ) return result;
if( file_id_tag )
{
result = mdbImpl->tag_set_data( *file_id_tag, elements, &elem_ids[0] );
if( MB_SUCCESS != result ) return result;
}
// Add elements to material sets
result = create_sets( type.mb_type, elements, matl_ids, 0 );
if( MB_SUCCESS != result ) return result;
// Add elements to geometric sets
result = create_sets( type.mb_type, elements, geom_ids, 1 );
if( MB_SUCCESS != result ) return result;
// Add elements to parallel partitions
result = create_sets( type.mb_type, elements, prtn_ids, 2 );
if( MB_SUCCESS != result ) return result;
return MB_SUCCESS;
}
ErrorCode ReadGmsh::create_geometric_topology | ( | ) | [private] |
NOT IMPLEMENTED Reconstruct parent-child relations for geometry sets from mesh connectivity.
Definition at line 516 of file ReadGmsh.cpp.
References moab::Range::clear(), moab::Range::empty(), geomSets, and MB_SUCCESS.
Referenced by load_file().
{
if( geomSets.empty() ) return MB_SUCCESS;
// Not implemented yet
geomSets.clear();
return MB_SUCCESS;
}
ErrorCode ReadGmsh::create_sets | ( | EntityType | element_type, |
const Range & | elements, | ||
const std::vector< int > & | set_ids, | ||
int | set_type | ||
) | [private] |
Add elements to sets as dictated by grouping ID in file.
Definition at line 399 of file ReadGmsh.cpp.
References moab::Interface::add_entities(), moab::Range::begin(), moab::Interface::create_meshset(), dim, moab::CN::Dimension(), moab::Range::empty(), moab::Range::end(), entities, ErrorCode, GEOM_DIMENSION_TAG_NAME, geomSets, moab::Interface::get_entities_by_type_and_tag(), globalId, moab::Range::insert(), moab::intersect(), MATERIAL_SET_TAG_NAME, MB_ENTITY_NOT_FOUND, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, mdbImpl, MESHSET_SET, PARALLEL_PARTITION_TAG_NAME, moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), and moab::Interface::tag_set_data().
Referenced by create_elements().
{
ErrorCode result;
// Get a unique list of set IDs
std::set< int > ids;
for( std::vector< int >::const_iterator i = set_ids.begin(); i != set_ids.end(); ++i )
ids.insert( *i );
// No Sets?
if( ids.empty() || ( ids.size() == 1 && *ids.begin() == 0 ) ) return MB_SUCCESS; // no sets (all ids are zero)
// Get/create tag handles
int num_tags;
Tag tag_handles[2];
int tag_val;
const void* tag_values[2] = { &tag_val, NULL };
switch( set_type )
{
default:
return MB_FAILURE;
case 0:
case 2: {
const char* name = set_type ? PARALLEL_PARTITION_TAG_NAME : MATERIAL_SET_TAG_NAME;
result = mdbImpl->tag_get_handle( name, 1, MB_TYPE_INTEGER, tag_handles[0], MB_TAG_SPARSE | MB_TAG_CREAT );
if( MB_SUCCESS != result ) return result;
num_tags = 1;
break;
}
case 1: {
result = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, tag_handles[1],
MB_TAG_SPARSE | MB_TAG_CREAT );
if( MB_SUCCESS != result ) return result;
tag_values[1] = NULL;
tag_handles[0] = globalId;
num_tags = 2;
break;
}
} // switch
// For each unique set ID...
for( std::set< int >::iterator i = ids.begin(); i != ids.end(); ++i )
{
// Skip "null" set ID
if( *i == 0 ) continue;
// Get all entities with the current set ID
Range entities, sets;
std::vector< int >::const_iterator j = set_ids.begin();
for( Range::iterator k = elements.begin(); k != elements.end(); ++j, ++k )
if( *i == *j ) entities.insert( *k );
// Get set by ID
// Cppcheck warning (false positive): variable tag_val is assigned a value that is never
// used
tag_val = *i;
result = mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, tag_handles, tag_values, num_tags, sets );
if( MB_SUCCESS != result && MB_ENTITY_NOT_FOUND != result ) return result;
// Don't use existing geometry sets (from some other file)
if( 1 == set_type ) // Geometry
sets = intersect( sets, geomSets );
// Get set handle
EntityHandle set;
// If no sets with ID, create one
if( sets.empty() )
{
result = mdbImpl->create_meshset( MESHSET_SET, set );
if( MB_SUCCESS != result ) return result;
result = mdbImpl->tag_set_data( tag_handles[0], &set, 1, &*i );
if( MB_SUCCESS != result ) return result;
if( 1 == set_type )
{ // Geometry
int dim = CN::Dimension( type );
result = mdbImpl->tag_set_data( tag_handles[1], &set, 1, &dim );
if( MB_SUCCESS != result ) return result;
geomSets.insert( set );
}
}
else
{
set = *sets.begin();
if( 1 == set_type )
{ // Geometry
int dim = CN::Dimension( type );
// Get dimension of set
int dim2;
result = mdbImpl->tag_get_data( tag_handles[1], &set, 1, &dim2 );
if( MB_SUCCESS != result ) return result;
// If we're putting geometry of a higher dimension into the
// set, increase the dimension of the set.
if( dim > dim2 )
{
result = mdbImpl->tag_set_data( tag_handles[1], &set, 1, &dim );
if( MB_SUCCESS != result ) return result;
}
}
}
// Put the mesh entities into the set
result = mdbImpl->add_entities( set, entities );
if( MB_SUCCESS != result ) return result;
} // for (ids)
return MB_SUCCESS;
}
ReaderIface * ReadGmsh::factory | ( | Interface * | iface | ) | [static] |
factory method
Definition at line 44 of file ReadGmsh.cpp.
References ReadGmsh().
Referenced by moab::ReaderWriterSet::ReaderWriterSet().
{
return new ReadGmsh( iface );
}
ErrorCode ReadGmsh::load_file | ( | const char * | file_name, |
const EntityHandle * | file_set, | ||
const FileOptions & | opts, | ||
const SubsetList * | subset_list = 0 , |
||
const Tag * | file_id_tag = 0 |
||
) | [virtual] |
Load mesh from a file.
Method all readers must provide to import a mesh.
file_name | The file to read. |
file_set | Optional pointer to entity set representing file. If this is not NULL, reader may optionally tag the pointed-to set with format-specific meta-data. |
subset_list | An optional struct pointer specifying the tags identifying entity sets to be read. |
file_id_tag | If specified, reader should store for each entity it reads, a unique integer ID for this tag. |
Implements moab::ReaderIface.
Definition at line 72 of file ReadGmsh.cpp.
References moab::Range::clear(), create_elements(), create_geometric_topology(), ErrorCode, geomSets, moab::FileTokenizer::get_doubles(), moab::FileTokenizer::get_integers(), moab::FileTokenizer::get_long_ints(), moab::FileTokenizer::get_newline(), moab::ReadUtilIface::get_node_coords(), moab::FileTokenizer::get_string(), globalId, moab::Interface::globalId_tag(), moab::GmshUtil::gmshElemTypes, moab::FileTokenizer::line_number(), moab::FileTokenizer::match_token(), MATERIAL_SET_TAG_NAME, MB_FILE_DOES_NOT_EXIST, MB_FILE_WRITE_ERROR, MB_SET_ERR, MB_START_ID, MB_SUCCESS, MB_UNSUPPORTED_OPERATION, MBMAXTYPE, mdbImpl, moab::GmshElemType::num_nodes, moab::ReaderIface::IDTag::num_tag_values, moab::GmshUtil::numGmshElemType, readMeshIface, moab::ReaderIface::SubsetList::tag_list, moab::ReaderIface::SubsetList::tag_list_length, moab::ReaderIface::IDTag::tag_name, moab::Interface::tag_set_data(), and moab::ReaderIface::IDTag::tag_values.
{
int num_material_sets = 0;
const int* material_set_list = 0;
if( subset_list )
{
if( subset_list->tag_list_length > 1 && !strcmp( subset_list->tag_list[0].tag_name, MATERIAL_SET_TAG_NAME ) )
{
MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "GMsh supports subset read only by material ID" );
}
material_set_list = subset_list->tag_list[0].tag_values;
num_material_sets = subset_list->tag_list[0].num_tag_values;
}
geomSets.clear();
globalId = mdbImpl->globalId_tag();
// Create set for more convenient check for material set ids
std::set< int > blocks;
for( const int* mat_set_end = material_set_list + num_material_sets; material_set_list != mat_set_end;
++material_set_list )
blocks.insert( *material_set_list );
// Map of ID->handle for nodes
std::map< long, EntityHandle > node_id_map;
int data_size = 8;
// Open file and hand off pointer to tokenizer
FILE* file_ptr = fopen( filename, "r" );
if( !file_ptr )
{
MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, filename << ": " << strerror( errno ) );
}
FileTokenizer tokens( file_ptr, readMeshIface );
// Determine file format version
const char* const start_tokens[] = { "$NOD", "$MeshFormat", 0 };
int format_version = tokens.match_token( start_tokens );
if( !format_version ) return MB_FILE_DOES_NOT_EXIST;
// If version 2.0, read additional header info
if( 2 == format_version )
{
double version;
if( !tokens.get_doubles( 1, &version ) ) return MB_FILE_WRITE_ERROR;
if( version != 2.0 && version != 2.1 && version != 2.2 )
{
MB_SET_ERR( MB_FILE_DOES_NOT_EXIST, filename << ": unknown format version: " << version );
return MB_FILE_DOES_NOT_EXIST;
}
int file_format;
if( !tokens.get_integers( 1, &file_format ) || !tokens.get_integers( 1, &data_size ) ||
!tokens.match_token( "$EndMeshFormat" ) )
return MB_FILE_WRITE_ERROR;
// If physical entities in the gmsh file -> discard this
const char* const phys_tokens[] = { "$Nodes", "$PhysicalNames", 0 };
int hasPhys = tokens.match_token( phys_tokens );
if( hasPhys == 2 )
{
long num_phys;
if( !tokens.get_long_ints( 1, &num_phys ) ) return MB_FILE_WRITE_ERROR;
for( long loop_phys = 0; loop_phys < num_phys; loop_phys++ )
{
long physDim;
long physGroupNum;
// char const * physName;
if( !tokens.get_long_ints( 1, &physDim ) ) return MB_FILE_WRITE_ERROR;
if( !tokens.get_long_ints( 1, &physGroupNum ) ) return MB_FILE_WRITE_ERROR;
const char* ptc = tokens.get_string();
if( !ptc ) return MB_FILE_WRITE_ERROR;
// try to get to the end of the line, without reporting errors
// really, we need to skip this
while( !tokens.get_newline( false ) )
ptc = tokens.get_string();
}
if( !tokens.match_token( "$EndPhysicalNames" ) || !tokens.match_token( "$Nodes" ) )
return MB_FILE_WRITE_ERROR;
}
}
// Read number of nodes
long num_nodes;
if( !tokens.get_long_ints( 1, &num_nodes ) ) return MB_FILE_WRITE_ERROR;
// Allocate nodes
std::vector< double* > coord_arrays;
EntityHandle handle = 0;
ErrorCode result = readMeshIface->get_node_coords( 3, num_nodes, MB_START_ID, handle, coord_arrays );
if( MB_SUCCESS != result ) return result;
// Read nodes
double *x = coord_arrays[0], *y = coord_arrays[1], *z = coord_arrays[2];
for( long i = 0; i < num_nodes; ++i, ++handle )
{
long id;
if( !tokens.get_long_ints( 1, &id ) || !tokens.get_doubles( 1, x++ ) || !tokens.get_doubles( 1, y++ ) ||
!tokens.get_doubles( 1, z++ ) )
return MB_FILE_WRITE_ERROR;
if( !node_id_map.insert( std::pair< long, EntityHandle >( id, handle ) ).second )
{
MB_SET_ERR( MB_FILE_WRITE_ERROR, "Duplicate node ID at line " << tokens.line_number() );
}
}
// Create reverse map from handle to id
std::vector< int > ids( num_nodes );
std::vector< int >::iterator id_iter = ids.begin();
std::vector< EntityHandle > handles( num_nodes );
std::vector< EntityHandle >::iterator h_iter = handles.begin();
for( std::map< long, EntityHandle >::iterator i = node_id_map.begin(); i != node_id_map.end();
++i, ++id_iter, ++h_iter )
{
*id_iter = i->first;
*h_iter = i->second;
}
// Store IDs in tags
result = mdbImpl->tag_set_data( globalId, &handles[0], num_nodes, &ids[0] );
if( MB_SUCCESS != result ) return result;
if( file_id_tag )
{
result = mdbImpl->tag_set_data( *file_id_tag, &handles[0], num_nodes, &ids[0] );
if( MB_SUCCESS != result ) return result;
}
ids.clear();
handles.clear();
// Get tokens signifying end of node data and start of elements
if( !tokens.match_token( format_version == 1 ? "$ENDNOD" : "$EndNodes" ) ||
!tokens.match_token( format_version == 1 ? "$ELM" : "$Elements" ) )
return MB_FILE_WRITE_ERROR;
// Get element count
long num_elem;
if( !tokens.get_long_ints( 1, &num_elem ) ) return MB_FILE_WRITE_ERROR;
// Lists of data accumulated for elements
std::vector< EntityHandle > connectivity;
std::vector< int > mat_set_list, geom_set_list, part_set_list, id_list;
// Temporary, per-element data
std::vector< int > int_data( 5 ), tag_data( 2 );
std::vector< long > tmp_conn;
int curr_elem_type = -1;
for( long i = 0; i < num_elem; ++i )
{
// Read element description
// File format 1.0
if( 1 == format_version )
{
if( !tokens.get_integers( 5, &int_data[0] ) ) return MB_FILE_WRITE_ERROR;
tag_data[0] = int_data[2];
tag_data[1] = int_data[3];
if( (unsigned)tag_data[1] < GmshUtil::numGmshElemType &&
GmshUtil::gmshElemTypes[tag_data[1]].num_nodes != (unsigned)int_data[4] )
{
MB_SET_ERR( MB_FILE_WRITE_ERROR,
"Invalid node count for element type at line " << tokens.line_number() );
}
}
// File format 2.0
else
{
if( !tokens.get_integers( 3, &int_data[0] ) ) return MB_FILE_WRITE_ERROR;
tag_data.resize( int_data[2] );
if( !tokens.get_integers( tag_data.size(), &tag_data[0] ) ) return MB_FILE_WRITE_ERROR;
}
// If a list of material sets was specified in the
// argument list, skip any elements for which the
// material set is not specified or is not in the
// passed list.
if( !blocks.empty() && ( tag_data.empty() || blocks.find( tag_data[0] ) != blocks.end() ) ) continue;
// If the next element is not the same type as the last one,
// create a sequence for the block of elements we've read
// to this point (all of the same type), and clear accumulated
// data.
if( int_data[1] != curr_elem_type )
{
if( !id_list.empty() )
{ // First iteration
result = create_elements( GmshUtil::gmshElemTypes[curr_elem_type], id_list, mat_set_list, geom_set_list,
part_set_list, connectivity, file_id_tag );
if( MB_SUCCESS != result ) return result;
}
id_list.clear();
mat_set_list.clear();
geom_set_list.clear();
part_set_list.clear();
connectivity.clear();
curr_elem_type = int_data[1];
if( (unsigned)curr_elem_type >= GmshUtil::numGmshElemType ||
GmshUtil::gmshElemTypes[curr_elem_type].mb_type == MBMAXTYPE )
{
MB_SET_ERR( MB_FILE_WRITE_ERROR,
"Unsupported element type " << curr_elem_type << " at line " << tokens.line_number() );
}
tmp_conn.resize( GmshUtil::gmshElemTypes[curr_elem_type].num_nodes );
}
// Store data from element description
id_list.push_back( int_data[0] );
if( tag_data.size() > 3 )
part_set_list.push_back( tag_data[3] ); // it must be new format for gmsh, >= 2.5
// it could have negative partition ids, for ghost elements
else if( tag_data.size() > 2 )
part_set_list.push_back( tag_data[2] ); // old format, partition id saved in 3rd tag field
else
part_set_list.push_back( 0 );
geom_set_list.push_back( tag_data.size() > 1 ? tag_data[1] : 0 );
mat_set_list.push_back( tag_data.size() > 0 ? tag_data[0] : 0 );
// Get element connectivity
if( !tokens.get_long_ints( tmp_conn.size(), &tmp_conn[0] ) ) return MB_FILE_WRITE_ERROR;
// Convert connectivity from IDs to handles
for( unsigned j = 0; j < tmp_conn.size(); ++j )
{
std::map< long, EntityHandle >::iterator k = node_id_map.find( tmp_conn[j] );
if( k == node_id_map.end() )
{
MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid node ID at line " << tokens.line_number() );
}
connectivity.push_back( k->second );
}
} // for (num_nodes)
// Create entity sequence for last element(s).
if( !id_list.empty() )
{
result = create_elements( GmshUtil::gmshElemTypes[curr_elem_type], id_list, mat_set_list, geom_set_list,
part_set_list, connectivity, file_id_tag );
if( MB_SUCCESS != result ) return result;
}
// Construct parent-child relations for geometric sets.
// Note: At the time this comment was written, the following
// function was not implemented.
result = create_geometric_topology();
geomSets.clear();
return result;
}
ErrorCode ReadGmsh::read_tag_values | ( | const char * | file_name, |
const char * | tag_name, | ||
const FileOptions & | opts, | ||
std::vector< int > & | tag_values_out, | ||
const SubsetList * | subset_list = 0 |
||
) | [virtual] |
Read tag values from a file.
Read the list if all integer tag values from the file for a tag that is a single integer value per entity.
file_name | The file to read. |
tag_name | The tag for which to read values |
tag_values_out | Output: The list of tag values. |
subset_list | An array of tag name and value sets specifying the subset of the file to read. If multiple tags are specified, the sets that match all tags (intersection) should be read. |
subset_list_length | The length of the 'subset_list' array. |
Implements moab::ReaderIface.
Definition at line 63 of file ReadGmsh.cpp.
References MB_NOT_IMPLEMENTED.
{
return MB_NOT_IMPLEMENTED;
}
Range moab::ReadGmsh::geomSets [private] |
Definition at line 80 of file ReadGmsh.hpp.
Referenced by create_geometric_topology(), create_sets(), and load_file().
Tag moab::ReadGmsh::globalId [private] |
Definition at line 79 of file ReadGmsh.hpp.
Referenced by create_elements(), create_sets(), and load_file().
Interface* moab::ReadGmsh::mdbImpl [private] |
interface instance
Definition at line 77 of file ReadGmsh.hpp.
Referenced by create_elements(), create_sets(), load_file(), ReadGmsh(), and ~ReadGmsh().
ReadUtilIface* moab::ReadGmsh::readMeshIface [private] |
Definition at line 74 of file ReadGmsh.hpp.
Referenced by create_elements(), load_file(), ReadGmsh(), and ~ReadGmsh().