![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
Export Gmsh files. More...
#include <WriteGmsh.hpp>
Public Member Functions | |
WriteGmsh (Interface *impl) | |
Constructor. | |
virtual | ~WriteGmsh () |
Destructor. | |
ErrorCode | write_file (const char *file_name, const bool overwrite, const FileOptions &opts, const EntityHandle *output_list, const int num_sets, const std::vector< std::string > &qa_list, const Tag *tag_list=NULL, int num_tags=0, int export_dimension=3) |
writes out a file | |
Static Public Member Functions | |
static WriterIface * | factory (Interface *) |
factory method | |
Private Attributes | |
Interface * | mbImpl |
interface instance | |
WriteUtilIface * | mWriteIface |
Export Gmsh files.
Known limitations:
Definition at line 40 of file WriteGmsh.hpp.
moab::WriteGmsh::WriteGmsh | ( | Interface * | impl | ) |
Constructor.
Definition at line 25 of file WriteGmsh.cpp.
References mWriteIface, and moab::Interface::query_interface().
Referenced by factory().
: mbImpl( impl )
{
impl->query_interface( mWriteIface );
}
moab::WriteGmsh::~WriteGmsh | ( | ) | [virtual] |
Destructor.
Definition at line 30 of file WriteGmsh.cpp.
References mbImpl, mWriteIface, and moab::Interface::release_interface().
{
mbImpl->release_interface( mWriteIface );
}
WriterIface * moab::WriteGmsh::factory | ( | Interface * | iface | ) | [static] |
factory method
Definition at line 20 of file WriteGmsh.cpp.
References WriteGmsh().
Referenced by moab::ReaderWriterSet::ReaderWriterSet().
{
return new WriteGmsh( iface );
}
ErrorCode moab::WriteGmsh::write_file | ( | const char * | file_name, |
const bool | overwrite, | ||
const FileOptions & | opts, | ||
const EntityHandle * | output_list, | ||
const int | num_sets, | ||
const std::vector< std::string > & | qa_list, | ||
const Tag * | tag_list = NULL , |
||
int | num_tags = 0 , |
||
int | export_dimension = 3 |
||
) | [virtual] |
writes out a file
Writes out a file.
Implements moab::WriterIface.
Definition at line 51 of file WriteGmsh.cpp.
References moab::Range::begin(), moab::WriteUtilIface::check_doesnt_exist(), moab::ElemInfo::count, moab::DEFAULT_PRECISION, moab::Range::empty(), moab::Range::end(), moab::CN::EntityTypeName(), ErrorCode, GEOM_DIMENSION_TAG_NAME, moab::Interface::get_adjacencies(), moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::Interface::get_entities_by_dimension(), moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type_and_tag(), moab::GmshUtil::get_gmsh_type(), moab::FileOptions::get_int_option(), moab::Interface::globalId_tag(), moab::GmshUtil::gmshElemTypes, moab::ElemInfo::id, moab::Interface::id_from_handle(), moab::Range::insert(), moab::intersect(), MATERIAL_SET_TAG_NAME, MB_ENTITY_NOT_FOUND, MB_FILE_DOES_NOT_EXIST, MB_FILE_WRITE_ERROR, MB_SET_ERR, MB_SUCCESS, MB_TYPE_INTEGER, MBENTITYSET, mbImpl, moab::Range::merge(), mWriteIface, moab::GmshElemType::node_order, PARALLEL_PARTITION_TAG_NAME, moab::Range::rbegin(), moab::Range::rend(), moab::Range::size(), moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::ElemInfo::type, and moab::Interface::type_from_handle().
{
ErrorCode rval;
Tag global_id = 0, block_tag = 0, geom_tag = 0, prtn_tag = 0;
if( !overwrite )
{
rval = mWriteIface->check_doesnt_exist( file_name );
if( MB_SUCCESS != rval ) return rval;
}
// Get tags
global_id = mbImpl->globalId_tag();
mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, block_tag );
if( global_id ) mbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );
mbImpl->tag_get_handle( PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, prtn_tag );
// Define arrays to hold entity sets of interest
Range sets[3];
Tag set_tags[] = { block_tag, geom_tag, prtn_tag };
Tag set_ids[] = { block_tag, 0 /*global_id*/, prtn_tag };
// Get entities to write
Range elements, nodes;
if( !output_list )
{
rval = mbImpl->get_entities_by_dimension( 0, 0, nodes, false );
if( MB_SUCCESS != rval ) return rval;
for( int d = 1; d <= 3; ++d )
{
Range tmp_range;
rval = mbImpl->get_entities_by_dimension( 0, d, tmp_range, false );
if( MB_SUCCESS != rval ) return rval;
elements.merge( tmp_range );
}
for( int s = 0; s < 3; ++s )
{
if( set_tags[s] )
{
rval = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, set_tags + s, 0, 1, sets[s] );
if( MB_SUCCESS != rval ) return rval;
}
}
}
else
{
for( int i = 0; i < num_sets; ++i )
{
EntityHandle set = output_list[i];
for( int d = 1; d < 3; ++d )
{
Range tmp_range, tmp_nodes;
rval = mbImpl->get_entities_by_dimension( set, d, tmp_range, true );
if( rval != MB_SUCCESS ) return rval;
elements.merge( tmp_range );
rval = mbImpl->get_adjacencies( tmp_range, set, false, tmp_nodes );
if( rval != MB_SUCCESS ) return rval;
nodes.merge( tmp_nodes );
}
for( int s = 0; s < 3; ++s )
{
if( set_tags[s] )
{
Range tmp_range;
rval = mbImpl->get_entities_by_type_and_tag( set, MBENTITYSET, set_tags + s, 0, 1, tmp_range );
if( MB_SUCCESS != rval ) return rval;
sets[s].merge( tmp_range );
int junk;
rval = mbImpl->tag_get_data( set_tags[s], &set, 1, &junk );
if( MB_SUCCESS == rval ) sets[s].insert( set );
}
}
}
}
if( elements.empty() )
{
MB_SET_ERR( MB_ENTITY_NOT_FOUND, "Nothing to write" );
}
// Get global IDs for all elements.
// First try to get from tag. If tag is not defined or not set
// for all elements, use handle value instead.
std::vector< int > global_id_array( elements.size() );
std::vector< int >::iterator id_iter;
if( !global_id || MB_SUCCESS != mbImpl->tag_get_data( global_id, elements, &global_id_array[0] ) )
{
id_iter = global_id_array.begin();
for( Range::iterator i = elements.begin(); i != elements.end(); ++i, ++id_iter )
*id_iter = mbImpl->id_from_handle( *i );
}
// Figure out the maximum ID value so we know where to start allocating
// new IDs when we encounter ID conflicts.
int max_id = 0;
for( id_iter = global_id_array.begin(); id_iter != global_id_array.end(); ++id_iter )
if( *id_iter > max_id ) max_id = *id_iter;
// Initialize ElemInfo struct for each element
std::map< EntityHandle, ElemInfo > elem_sets; // Per-element info
std::set< int > elem_global_ids; // Temporary for finding duplicate IDs
id_iter = global_id_array.begin();
// Iterate backwards to give highest-dimension entities first dibs for
// a conflicting ID.
for( Range::reverse_iterator i = elements.rbegin(); i != elements.rend(); ++i )
{
int id = *id_iter;
++id_iter;
if( !elem_global_ids.insert( id ).second ) id = ++max_id;
ElemInfo& ei = elem_sets[*i];
ei.count = 0;
ei.id = id;
EntityType type = mbImpl->type_from_handle( *i );
int num_vtx;
const EntityHandle* conn;
rval = mbImpl->get_connectivity( *i, conn, num_vtx );
if( MB_SUCCESS != rval ) return rval;
ei.type = GmshUtil::get_gmsh_type( type, num_vtx );
if( ei.type < 0 )
{
MB_SET_ERR( MB_FILE_WRITE_ERROR, "Gmem file format does not support element of type "
<< CN::EntityTypeName( type ) << " with " << num_vtx << " vertices" );
}
}
// Don't need these any more, free memory.
elem_global_ids.clear();
global_id_array.clear();
// For each material set, geometry set, or partition; store
// the ID of the set on each element.
for( int s = 0; s < 3; ++s )
{
if( !set_tags[s] ) continue;
for( Range::iterator i = sets[s].begin(); i != sets[s].end(); ++i )
{
int id;
if( set_ids[s] )
{
rval = mbImpl->tag_get_data( set_ids[s], &*i, 1, &id );
if( MB_SUCCESS != rval ) return rval;
}
else
id = mbImpl->id_from_handle( *i );
Range elems;
rval = mbImpl->get_entities_by_handle( *i, elems );
if( MB_SUCCESS != rval ) return rval;
elems = intersect( elems, elements );
for( Range::iterator j = elems.begin(); j != elems.end(); ++j )
elem_sets[*j].set( s, id );
}
}
// Create file
std::ofstream out( file_name );
if( !out ) return MB_FILE_DOES_NOT_EXIST;
// Write header
out << "$MeshFormat" << std::endl;
out << "2.0 0 " << sizeof( double ) << std::endl;
out << "$EndMeshFormat" << std::endl;
// Set precision for node coordinates
int precision;
if( MB_SUCCESS != options.get_int_option( "PRECISION", precision ) ) precision = DEFAULT_PRECISION;
const int old_precision = out.precision();
out.precision( precision );
// Write nodes
out << "$Nodes" << std::endl;
out << nodes.size() << std::endl;
std::vector< double > coords( 3 * nodes.size() );
rval = mbImpl->get_coords( nodes, &coords[0] );
if( MB_SUCCESS != rval ) return rval;
std::vector< double >::iterator c = coords.begin();
for( Range::iterator i = nodes.begin(); i != nodes.end(); ++i )
{
out << mbImpl->id_from_handle( *i );
out << " " << *c;
++c;
out << " " << *c;
++c;
out << " " << *c;
++c;
out << std::endl;
}
out << "$EndNodes" << std::endl;
coords.clear();
// Restore stream state
out.precision( old_precision );
// Write elements
out << "$Elements" << std::endl;
out << elem_sets.size() << std::endl;
for( std::map< EntityHandle, ElemInfo >::iterator i = elem_sets.begin(); i != elem_sets.end(); ++i )
{
int num_vtx;
const EntityHandle* conn;
rval = mbImpl->get_connectivity( i->first, conn, num_vtx );
if( MB_SUCCESS != rval ) return rval;
out << i->second.id << ' ' << i->second.type << ' ' << i->second.count;
for( int j = 0; j < i->second.count; ++j )
out << ' ' << i->second.sets[j];
const int* order = GmshUtil::gmshElemTypes[i->second.type].node_order;
// Need to re-order vertices
if( order )
{
for( int j = 0; j < num_vtx; ++j )
out << ' ' << mbImpl->id_from_handle( conn[order[j]] );
}
else
{
for( int j = 0; j < num_vtx; ++j )
out << ' ' << mbImpl->id_from_handle( conn[j] );
}
out << std::endl;
}
out << "$EndElements" << std::endl;
// Done
return MB_SUCCESS;
}
Interface* moab::WriteGmsh::mbImpl [private] |
interface instance
Definition at line 66 of file WriteGmsh.hpp.
Referenced by write_file(), and ~WriteGmsh().
WriteUtilIface* moab::WriteGmsh::mWriteIface [private] |
Definition at line 67 of file WriteGmsh.hpp.
Referenced by write_file(), WriteGmsh(), and ~WriteGmsh().