$extrastylesheet
#include <gmsh_io.h>

Public Member Functions | |
| GmshIO (MeshBase &mesh) | |
| GmshIO (const MeshBase &mesh) | |
| virtual void | read (const std::string &name) |
| virtual void | write (const std::string &name) |
| virtual void | write_nodal_data (const std::string &, const std::vector< Number > &, const std::vector< std::string > &) |
| bool & | binary () |
| virtual void | write_equation_systems (const std::string &, const EquationSystems &, const std::set< std::string > *system_names=NULL) |
| unsigned int & | ascii_precision () |
Protected Member Functions | |
| MeshBase & | mesh () |
| void | set_n_partitions (unsigned int n_parts) |
| void | skip_comment_lines (std::istream &in, const char comment_start) |
| const MeshBase & | mesh () const |
Protected Attributes | |
| std::vector< bool > | elems_of_dimension |
| const bool | _is_parallel_format |
Private Member Functions | |
| virtual void | read_mesh (std::istream &in) |
| virtual void | write_mesh (std::ostream &out) |
| void | write_post (const std::string &, const std::vector< Number > *=NULL, const std::vector< std::string > *=NULL) |
Private Attributes | |
| bool | _binary |
This class implements writing meshes in the Gmsh format. For a full description of the Gmsh format and to obtain the GMSH software see the Gmsh home page
| libMesh::GmshIO::GmshIO | ( | MeshBase & | mesh | ) | [explicit] |
Constructor. Takes a non-const Mesh reference which it will fill up with elements via the read() command.
Definition at line 311 of file gmsh_io.C.
: MeshInput<MeshBase> (mesh), MeshOutput<MeshBase> (mesh), _binary (false) { }
| libMesh::GmshIO::GmshIO | ( | const MeshBase & | mesh | ) | [explicit] |
Constructor. Takes a reference to a constant mesh object. This constructor will only allow us to write the mesh.
Definition at line 303 of file gmsh_io.C.
: MeshOutput<MeshBase>(mesh), _binary(false) { }
| unsigned int& libMesh::MeshOutput< MeshBase >::ascii_precision | ( | ) | [inherited] |
Return/set the precision to use when writing ASCII files.
By default we use numeric_limits<Real>::digits10 + 2, which should be enough to write out to ASCII and get the exact same Real back when reading in.
Referenced by libMesh::TecplotIO::write_ascii(), libMesh::GMVIO::write_ascii_new_impl(), and libMesh::GMVIO::write_ascii_old_impl().
| bool & libMesh::GmshIO::binary | ( | ) |
Flag indicating whether or not to write a binary file. While binary files may end up being smaller than equivalent ASCII files, they will almost certainly take longer to write. The reason for this is that the ostream::write() function which is used to write "binary" data to streams, only takes a pointer to char as its first argument. This means if you want to write anything other than a buffer of chars, you first have to use a strange memcpy hack to get the data into the desired format. See the templated to_binary_stream() function below.
Definition at line 320 of file gmsh_io.C.
References _binary.
Referenced by write_post().
{
return _binary;
}
| MeshBase & libMesh::MeshInput< MeshBase >::mesh | ( | ) | [protected, inherited] |
Returns the object as a writeable reference.
Referenced by libMesh::GMVIO::_read_materials(), libMesh::GMVIO::_read_nodes(), libMesh::GMVIO::_read_one_cell(), libMesh::AbaqusIO::assign_boundary_node_ids(), libMesh::AbaqusIO::assign_sideset_ids(), libMesh::AbaqusIO::assign_subdomain_ids(), libMesh::VTKIO::cells_to_vtk(), libMesh::ExodusII_IO::copy_elemental_solution(), libMesh::ExodusII_IO::copy_nodal_solution(), libMesh::GMVIO::copy_nodal_solution(), libMesh::TetGenIO::element_in(), libMesh::UNVIO::elements_in(), libMesh::UNVIO::elements_out(), libMesh::UNVIO::groups_in(), libMesh::TetGenIO::node_in(), libMesh::UNVIO::nodes_in(), libMesh::UNVIO::nodes_out(), libMesh::VTKIO::nodes_to_vtk(), libMesh::AbaqusIO::read(), libMesh::NameBasedIO::read(), libMesh::TetGenIO::read(), libMesh::Nemesis_IO::read(), libMesh::ExodusII_IO::read(), libMesh::GMVIO::read(), libMesh::CheckpointIO::read(), libMesh::XdrIO::read(), libMesh::VTKIO::read(), libMesh::LegacyXdrIO::read_ascii(), libMesh::CheckpointIO::read_bcs(), libMesh::CheckpointIO::read_connectivity(), libMesh::AbaqusIO::read_elements(), libMesh::UCDIO::read_implementation(), libMesh::UNVIO::read_implementation(), read_mesh(), libMesh::LegacyXdrIO::read_mesh(), libMesh::AbaqusIO::read_nodes(), libMesh::CheckpointIO::read_nodes(), libMesh::CheckpointIO::read_nodesets(), libMesh::XdrIO::read_serialized_bcs(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::OFFIO::read_stream(), libMesh::MatlabIO::read_stream(), libMesh::CheckpointIO::read_subdomain_names(), libMesh::NameBasedIO::write(), libMesh::TetGenIO::write(), libMesh::Nemesis_IO::write(), libMesh::ExodusII_IO::write(), libMesh::CheckpointIO::write(), libMesh::XdrIO::write(), libMesh::GMVIO::write_ascii_new_impl(), libMesh::GMVIO::write_ascii_old_impl(), libMesh::CheckpointIO::write_bcs(), libMesh::GMVIO::write_binary(), libMesh::CheckpointIO::write_connectivity(), libMesh::GMVIO::write_discontinuous_gmv(), libMesh::ExodusII_IO::write_element_data(), libMesh::UCDIO::write_implementation(), write_mesh(), libMesh::LegacyXdrIO::write_mesh(), libMesh::UCDIO::write_nodal_data(), libMesh::VTKIO::write_nodal_data(), libMesh::Nemesis_IO::write_nodal_data(), libMesh::NameBasedIO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data(), libMesh::ExodusII_IO::write_nodal_data_common(), libMesh::ExodusII_IO::write_nodal_data_discontinuous(), libMesh::CheckpointIO::write_nodes(), libMesh::CheckpointIO::write_nodesets(), libMesh::XdrIO::write_parallel(), write_post(), libMesh::XdrIO::write_serialized_bcs(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), libMesh::XdrIO::write_serialized_nodesets(), libMesh::XdrIO::write_serialized_subdomain_names(), libMesh::LegacyXdrIO::write_soln(), and libMesh::CheckpointIO::write_subdomain_names().
| const MeshBase & libMesh::MeshOutput< MeshBase >::mesh | ( | ) | const [protected, inherited] |
Returns the object as a read-only reference.
Referenced by libMesh::TecplotIO::elem_dimension(), libMesh::FroIO::write(), libMesh::DivaIO::write(), libMesh::TecplotIO::write(), libMesh::PostscriptIO::write(), libMesh::MEDITIO::write(), libMesh::EnsightIO::write(), libMesh::MEDITIO::write_ascii(), libMesh::TecplotIO::write_ascii(), libMesh::TecplotIO::write_binary(), libMesh::EnsightIO::write_geometry_ascii(), libMesh::TecplotIO::write_nodal_data(), libMesh::MEDITIO::write_nodal_data(), libMesh::EnsightIO::write_scalar_ascii(), libMesh::GnuPlotIO::write_solution(), libMesh::DivaIO::write_stream(), and libMesh::EnsightIO::write_vector_ascii().
| void libMesh::GmshIO::read | ( | const std::string & | name | ) | [virtual] |
Reads in a mesh in the Gmsh *.msh format from the ASCII file given by name.
The user is responsible for calling Mesh::prepare_for_use() after reading the mesh and before using it.
Implements libMesh::MeshInput< MeshBase >.
Definition at line 327 of file gmsh_io.C.
References read_mesh().
Referenced by libMesh::NameBasedIO::read().
| void libMesh::GmshIO::read_mesh | ( | std::istream & | in | ) | [private, virtual] |
Implementation of the read() function. This function is called by the public interface function and implements reading the file.
Definition at line 335 of file gmsh_io.C.
References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::add_elem(), libMesh::BoundaryInfo::add_node(), libMesh::MeshBase::add_point(), libMesh::BoundaryInfo::add_side(), libMesh::Elem::build(), libMesh::Elem::build_side(), libMesh::MeshBase::clear(), libMesh::MeshBase::delete_elem(), libMesh::Elem::dim(), end, libMesh::err, libMesh::MeshBase::get_boundary_info(), libMesh::libmesh_assert(), std::max(), libMesh::MeshInput< MeshBase >::mesh(), std::min(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::node(), libMesh::MeshBase::node_ptr(), libMesh::processor_id(), libMesh::Real, libMesh::MeshBase::reserve_elem(), libMesh::MeshBase::reserve_nodes(), libMesh::DofObject::set_id(), libMesh::MeshBase::set_mesh_dimension(), libMesh::Elem::set_node(), side, libMesh::Elem::subdomain_id(), and libMesh::x.
Referenced by read().
{
// This is a serial-only process for now;
// the Mesh should be read on processor 0 and
// broadcast later
libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
libmesh_assert(in.good());
// initialize the map with element types
init_eletypes();
// clear any data in the mesh
MeshBase& mesh = MeshInput<MeshBase>::mesh();
mesh.clear();
// some variables
int format=0, size=0;
Real version = 1.0;
// map to hold the node numbers for translation
// note the the nodes can be non-consecutive
std::map<unsigned int, unsigned int> nodetrans;
// For reading the file line by line
std::string s;
while (true)
{
// Try to read something. This may set EOF!
std::getline(in, s);
if (in)
{
// Process s...
if (s.find("$MeshFormat") == static_cast<std::string::size_type>(0))
{
in >> version >> format >> size;
if ((version != 2.0) && (version != 2.1) && (version != 2.2))
{
// Some notes on gmsh mesh versions:
//
// Mesh version 2.0 goes back as far as I know. It's not explicitly
// mentioned here: http://www.geuz.org/gmsh/doc/VERSIONS.txt
//
// As of gmsh-2.4.0:
// bumped mesh version format to 2.1 (small change in the $PhysicalNames
// section, where the group dimension is now required);
// [Since we don't even parse the PhysicalNames section at the time
// of this writing, I don't think this change affects us.]
//
// Mesh version 2.2 tested by Manav Bhatia; no other
// libMesh code changes were required for support
libmesh_error_msg("Error: Unknown msh file version " << version);
}
if (format)
libmesh_error_msg("Error: Unknown data format for mesh in Gmsh reader.");
}
// read the node block
else if (s.find("$NOD") == static_cast<std::string::size_type>(0) ||
s.find("$NOE") == static_cast<std::string::size_type>(0) ||
s.find("$Nodes") == static_cast<std::string::size_type>(0))
{
unsigned int num_nodes = 0;
in >> num_nodes;
mesh.reserve_nodes (num_nodes);
// read in the nodal coordinates and form points.
Real x, y, z;
unsigned int id;
// add the nodal coordinates to the mesh
for (unsigned int i=0; i<num_nodes; ++i)
{
in >> id >> x >> y >> z;
mesh.add_point (Point(x, y, z), i);
nodetrans[id] = i;
}
// read the $ENDNOD delimiter
std::getline(in, s);
}
// Read the element block
else if (s.find("$ELM") == static_cast<std::string::size_type>(0) ||
s.find("$Elements") == static_cast<std::string::size_type>(0))
{
// For reading the number of elements and the node ids from the stream
unsigned int
num_elem = 0,
node_id = 0;
// read how many elements are there, and reserve space in the mesh
in >> num_elem;
mesh.reserve_elem (num_elem);
// As of version 2.2, the format for each element line is:
// elm-number elm-type number-of-tags < tag > ... node-number-list
// From the Gmsh docs:
// * the first tag is the number of the
// physical entity to which the element belongs
// * the second is the number of the elementary geometrical
// entity to which the element belongs
// * the third is the number of mesh partitions to which the element
// belongs
// * The rest of the tags are the partition ids (negative
// partition ids indicate ghost cells). A zero tag is
// equivalent to no tag. Gmsh and most codes using the
// MSH 2 format require at least the first two tags
// (physical and elementary tags).
// Keep track of all the element dimensions seen
std::vector<unsigned> elem_dimensions_seen(3);
// read the elements
for (unsigned int iel=0; iel<num_elem; ++iel)
{
unsigned int
id, type,
physical=1, elementary=1,
nnodes=0, ntags;
// Note: tag has to be an int because it could be negative,
// see above.
int tag;
if (version <= 1.0)
in >> id >> type >> physical >> elementary >> nnodes;
else
{
in >> id >> type >> ntags;
if (ntags > 2)
libmesh_do_once(libMesh::err << "Warning, ntags=" << ntags << ", but we currently only support reading 2 flags." << std::endl;);
for (unsigned int j = 0; j < ntags; j++)
{
in >> tag;
if (j == 0)
physical = tag;
else if (j == 1)
elementary = tag;
}
}
// Consult the import element table to determine which element to build
std::map<unsigned int, elementDefinition>::iterator eletypes_it = eletypes_imp.find(type);
// Make sure we actually found something
if (eletypes_it == eletypes_imp.end())
libmesh_error_msg("Element type " << type << " not found!");
// Get a reference to the elementDefinition
const elementDefinition& eletype = eletypes_it->second;
// If we read nnodes, make sure it matches the number in eletype.nnodes
if (nnodes != 0 && nnodes != eletype.nnodes)
libmesh_error_msg("nnodes = " << nnodes << " and eletype.nnodes = " << eletype.nnodes << " do not match.");
// Assign the value from the eletype object.
nnodes = eletype.nnodes;
// Don't add 0-dimensional "point" elements to the
// Mesh. They should *always* be treated as boundary
// "nodeset" data.
if (eletype.dim > 0)
{
// Record this element dimension as being "seen".
// We will treat all elements with dimension <
// max(dimension) as specifying boundary conditions,
// but we won't know what max_elem_dimension_seen is
// until we read the entire file.
elem_dimensions_seen[eletype.dim-1] = 1;
// Add the element to the mesh
{
Elem* elem = Elem::build(eletype.type).release();
elem->set_id(iel);
elem = mesh.add_elem(elem);
// Make sure that the libmesh element we added has nnodes nodes.
if (elem->n_nodes() != nnodes)
libmesh_error_msg("Number of nodes for element " \
<< id \
<< " of type " << eletypes_imp[type].type \
<< " (Gmsh type " << type \
<< ") does not match Libmesh definition. " \
<< "I expected " << elem->n_nodes() \
<< " nodes, but got " << nnodes);
// Add node pointers to the elements.
// If there is a node translation table, use it.
if (eletype.nodes.size() > 0)
for (unsigned int i=0; i<nnodes; i++)
{
in >> node_id;
elem->set_node(eletype.nodes[i]) = mesh.node_ptr(nodetrans[node_id]);
}
else
{
for (unsigned int i=0; i<nnodes; i++)
{
in >> node_id;
elem->set_node(i) = mesh.node_ptr(nodetrans[node_id]);
}
}
// Finally, set the subdomain ID to physical. If this is a lower-dimension element, this ID will
// eventually go into the Mesh's BoundaryInfo object.
elem->subdomain_id() = static_cast<subdomain_id_type>(physical);
}
}
// Handle 0-dimensional elements (points) by adding
// them to the BoundaryInfo object with
// boundary_id == physical.
else
{
// This seems like it should always be the same
// number as the 'id' we already read in on this
// line. At least it was in the example gmsh
// file I had...
in >> node_id;
mesh.get_boundary_info().add_node
(nodetrans[node_id],
static_cast<boundary_id_type>(physical));
}
} // element loop
// read the $ENDELM delimiter
std::getline(in, s);
// Record the max and min element dimension seen while reading the file.
unsigned char
max_elem_dimension_seen=1,
min_elem_dimension_seen=3;
for (unsigned char i=0; i<elem_dimensions_seen.size(); ++i)
if (elem_dimensions_seen[i])
{
// Debugging
// libMesh::out << "Seen elements of dimension " << i+1 << std::endl;
max_elem_dimension_seen =
std::max(max_elem_dimension_seen, cast_int<unsigned char>(i+1));
min_elem_dimension_seen =
std::min(min_elem_dimension_seen, cast_int<unsigned char>(i+1));
}
// Debugging:
// libMesh::out << "max_elem_dimension_seen=" << max_elem_dimension_seen << std::endl;
// libMesh::out << "min_elem_dimension_seen=" << min_elem_dimension_seen << std::endl;
// If the difference between the max and min element dimension seen is larger than
// 1, (e.g. the file has 1D and 3D elements only) we don't handle this case.
if (max_elem_dimension_seen - min_elem_dimension_seen > 1)
libmesh_error_msg("Cannot handle meshes with dimension mismatch greater than 1.");
// How many different element dimensions did we see while reading from file?
unsigned n_dims_seen = std::accumulate(elem_dimensions_seen.begin(),
elem_dimensions_seen.end(),
static_cast<unsigned>(0),
std::plus<unsigned>());
// Have not yet tested a case where 1, 2, and 3D elements are all in the same Mesh,
// though it should theoretically be possible to handle.
if (n_dims_seen == 3)
libmesh_error_msg("Reading meshes with 1, 2, and 3D elements not currently supported.");
// Set mesh_dimension based on the largest element dimension seen.
mesh.set_mesh_dimension(max_elem_dimension_seen);
if (n_dims_seen > 1)
{
// map from (node ids) -> elem of lower dimensional elements that can provide boundary conditions
typedef std::map<std::vector<dof_id_type>, Elem*> provide_container_t;
provide_container_t provide_bcs;
// 1st loop over active elements - get info about lower-dimensional elements.
{
MeshBase::element_iterator it = mesh.active_elements_begin();
const MeshBase::element_iterator end = mesh.active_elements_end();
for ( ; it != end; ++it)
{
Elem* elem = *it;
if (elem->dim() < max_elem_dimension_seen)
{
// Debugging status
// libMesh::out << "Processing Elem " << elem->id() << " as a boundary element." << std::endl;
// To be pushed into the provide_bcs data structure
std::vector<dof_id_type> node_ids(elem->n_nodes());
// To be consistent with the previous GmshIO behavior, add all the lower-dimensional elements' nodes to
// the Mesh's BoundaryInfo object with the lower-dimensional element's subdomain ID.
for (unsigned n=0; n<elem->n_nodes(); n++)
{
mesh.get_boundary_info().add_node
(elem->node(n), elem->subdomain_id());
// And save for our local data structure
node_ids[n] = elem->node(n);
}
// Sort before putting into the map
std::sort(node_ids.begin(), node_ids.end());
provide_bcs[node_ids] = elem;
}
}
} // end 1st loop over active elements
// Debugging: What did we put in the provide_bcs data structure?
// {
// provide_container_t::iterator provide_it = provide_bcs.begin();
// provide_container_t::iterator provide_end = provide_bcs.end();
// for ( ; provide_it != provide_end; ++provide_it)
// {
// std::vector<dof_id_type> node_list = (*provide_it).first;
// Elem* elem = (*provide_it).second;
//
// libMesh::out << "Elem " << elem->id() << " provides BCs for the face: ";
// for (unsigned i=0; i<node_list.size(); ++i)
// libMesh::out << node_list[i] << " ";
// libMesh::out << std::endl;
// }
// }
// 2nd loop over active elements - use lower dimensional element data to set BCs for higher dimensional elements
{
MeshBase::element_iterator it = mesh.active_elements_begin();
const MeshBase::element_iterator end = mesh.active_elements_end();
for ( ; it != end; ++it)
{
Elem* elem = *it;
if (elem->dim() == max_elem_dimension_seen)
{
// This is a max-dimension element that
// may require BCs. For each of its
// sides, including internal sides, we'll
// see if a lower-dimensional element
// provides boundary information for it.
// Note that we have not yet called
// find_neighbors(), so we can't use
// elem->neighbor(sn) in this algorithm...
for (unsigned short sn=0;
sn<elem->n_sides(); sn++)
{
UniquePtr<Elem> side (elem->build_side(sn));
// Build up a node_ids vector, which is the key
std::vector<dof_id_type> node_ids(side->n_nodes());
for (unsigned n=0; n<side->n_nodes(); n++)
node_ids[n] = side->node(n);
// Sort the vector before using it as a key
std::sort(node_ids.begin(), node_ids.end());
// Look for this key in the provide_bcs map
provide_container_t::iterator iter = provide_bcs.find(node_ids);
if (iter != provide_bcs.end())
{
Elem* lower_dim_elem = (*iter).second;
// libMesh::out << "Elem "
// << lower_dim_elem->id()
// << " provides BCs for side "
// << sn
// << " of Elem "
// << elem->id()
// << std::endl;
// Add boundary information based on the lower-dimensional element's subdomain id.
mesh.get_boundary_info().add_side(elem,
sn,
cast_int<boundary_id_type>(lower_dim_elem->subdomain_id()));
}
}
}
}
} // end 2nd loop over active elements
// 3rd loop over active elements - Remove the lower-dimensional elements
{
MeshBase::element_iterator it = mesh.active_elements_begin();
const MeshBase::element_iterator end = mesh.active_elements_end();
for ( ; it != end; ++it)
{
Elem* elem = *it;
if (elem->dim() < max_elem_dimension_seen)
mesh.delete_elem(elem);
}
} // end 3rd loop over active elements
} // end if (n_dims_seen > 1)
} // if $ELM
continue;
} // if (in)
// If !in, check to see if EOF was set. If so, break out
// of while loop.
if (in.eof())
break;
// If !in and !in.eof(), stream is in a bad state!
libmesh_error_msg("Stream is bad! Perhaps the file does not exist?");
} // while true
}
| void libMesh::MeshInput< MeshBase >::set_n_partitions | ( | unsigned int | n_parts | ) | [inline, protected, inherited] |
Sets the number of partitions in the mesh. Typically this gets done by the partitioner, but some parallel file formats begin "pre-partitioned".
Definition at line 94 of file mesh_input.h.
References libMesh::MeshInput< MT >::mesh().
Referenced by libMesh::Nemesis_IO::read(), and libMesh::XdrIO::read().
{ this->mesh().set_n_partitions() = n_parts; }
| void libMesh::MeshInput< MeshBase >::skip_comment_lines | ( | std::istream & | in, |
| const char | comment_start | ||
| ) | [protected, inherited] |
Reads input from in, skipping all the lines that start with the character comment_start.
Referenced by libMesh::TetGenIO::read(), and libMesh::UCDIO::read_implementation().
| void libMesh::GmshIO::write | ( | const std::string & | name | ) | [virtual] |
This method implements writing a mesh to a specified file in the Gmsh *.msh format.
Implements libMesh::MeshOutput< MeshBase >.
Definition at line 756 of file gmsh_io.C.
References libMesh::processor_id(), and write_mesh().
Referenced by libMesh::NameBasedIO::write().
{
if (MeshOutput<MeshBase>::mesh().processor_id() == 0)
{
// Open the output file stream
std::ofstream out_stream (name.c_str());
// Make sure it opened correctly
if (!out_stream.good())
libmesh_file_error(name.c_str());
this->write_mesh (out_stream);
}
}
| virtual void libMesh::MeshOutput< MeshBase >::write_equation_systems | ( | const std::string & | , |
| const EquationSystems & | , | ||
| const std::set< std::string > * | system_names = NULL |
||
| ) | [virtual, inherited] |
This method implements writing a mesh with data to a specified file where the data is taken from the EquationSystems object.
Reimplemented in libMesh::NameBasedIO.
Referenced by libMesh::Nemesis_IO::write_timestep(), and libMesh::ExodusII_IO::write_timestep().
| void libMesh::GmshIO::write_mesh | ( | std::ostream & | out | ) | [private, virtual] |
This method implements writing a mesh to a specified file. This will write an ASCII *.msh file.
Definition at line 788 of file gmsh_io.C.
References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), end, libMesh::DofObject::id(), libMesh::libmesh_assert(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::n_active_elem(), libMesh::MeshBase::n_nodes(), libMesh::Elem::n_nodes(), libMesh::Elem::node(), libMesh::MeshBase::node(), libMesh::DofObject::processor_id(), libMesh::Real, libMesh::Elem::subdomain_id(), and libMesh::Elem::type().
Referenced by write().
{
// Be sure that the stream is valid.
libmesh_assert (out_stream.good());
// initialize the map with element types
init_eletypes();
// Get a const reference to the mesh
const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
// Note: we are using version 2.0 of the gmsh output format.
// Write the file header.
out_stream << "$MeshFormat\n";
out_stream << "2.0 0 " << sizeof(Real) << '\n';
out_stream << "$EndMeshFormat\n";
// write the nodes in (n x y z) format
out_stream << "$Nodes\n";
out_stream << mesh.n_nodes() << '\n';
for (unsigned int v=0; v<mesh.n_nodes(); v++)
out_stream << mesh.node(v).id()+1 << " "
<< mesh.node(v)(0) << " "
<< mesh.node(v)(1) << " "
<< mesh.node(v)(2) << '\n';
out_stream << "$EndNodes\n";
{
// write the connectivity
out_stream << "$Elements\n";
out_stream << mesh.n_active_elem() << '\n';
MeshBase::const_element_iterator it = mesh.active_elements_begin();
const MeshBase::const_element_iterator end = mesh.active_elements_end();
// loop over the elements
for ( ; it != end; ++it)
{
const Elem* elem = *it;
// Make sure we have a valid entry for
// the current element type.
libmesh_assert (eletypes_exp.count(elem->type()));
// consult the export element table
const elementDefinition& eletype = eletypes_exp[elem->type()];
// The element mapper better not require any more nodes
// than are present in the current element!
libmesh_assert_less_equal (eletype.nodes.size(), elem->n_nodes());
// elements ids are 1 based in Gmsh
out_stream << elem->id()+1 << " ";
// element type
out_stream << eletype.exptype;
// write the number of tags and
// tag1 (physical entity), tag2 (geometric entity), and tag3 (partition entity)
out_stream << " 3 "
<< static_cast<unsigned int>(elem->subdomain_id())
<< " 1 "
<< (elem->processor_id()+1) << " ";
// if there is a node translation table, use it
if (eletype.nodes.size() > 0)
for (unsigned int i=0; i < elem->n_nodes(); i++)
out_stream << elem->node(eletype.nodes[i])+1 << " "; // gmsh is 1-based
// otherwise keep the same node order
else
for (unsigned int i=0; i < elem->n_nodes(); i++)
out_stream << elem->node(i)+1 << " "; // gmsh is 1-based
out_stream << "\n";
} // element loop
out_stream << "$EndElements\n";
}
}
| void libMesh::GmshIO::write_nodal_data | ( | const std::string & | fname, |
| const std::vector< Number > & | soln, | ||
| const std::vector< std::string > & | names | ||
| ) | [virtual] |
This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are provided.
Reimplemented from libMesh::MeshOutput< MeshBase >.
Definition at line 773 of file gmsh_io.C.
References libMesh::processor_id(), libMesh::START_LOG(), and write_post().
Referenced by libMesh::NameBasedIO::write_nodal_data().
{
START_LOG("write_nodal_data()", "GmshIO");
//this->_binary = true;
if (MeshOutput<MeshBase>::mesh().processor_id() == 0)
this->write_post (fname, &soln, &names);
STOP_LOG("write_nodal_data()", "GmshIO");
}
| void libMesh::GmshIO::write_post | ( | const std::string & | fname, |
| const std::vector< Number > * | v = NULL, |
||
| const std::vector< std::string > * | solution_names = NULL |
||
| ) | [private] |
This method implements writing a mesh with nodal data to a specified file where the nodal data and variable names are optionally provided. This will write an ASCII or binary *.pos file, depending on the binary flag.
Definition at line 870 of file gmsh_io.C.
References libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), binary(), libMesh::EDGE2, libMesh::EDGE3, libMesh::EDGE4, end, libMesh::err, libMesh::HEX20, libMesh::HEX27, libMesh::HEX8, libMesh::libmesh_real(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::n_nodes(), n_vars, libMesh::Elem::n_vertices(), libMesh::Elem::node(), libMesh::out, libMesh::Elem::point(), libMesh::PRISM15, libMesh::PRISM18, libMesh::PRISM6, libMesh::processor_id(), libMesh::PYRAMID5, libMesh::QUAD4, libMesh::QUAD8, libMesh::QUAD9, libMesh::TET10, libMesh::TET4, libMesh::TRI3, and libMesh::TRI6.
Referenced by write_nodal_data().
{
// Should only do this on processor 0!
libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
// Create an output stream
std::ofstream out_stream(fname.c_str());
// Make sure it opened correctly
if (!out_stream.good())
libmesh_file_error(fname.c_str());
// initialize the map with element types
init_eletypes();
// create a character buffer
char buf[80];
// Get a constant reference to the mesh.
const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
// write the data
if ((solution_names != NULL) && (v != NULL))
{
const unsigned int n_vars =
cast_int<unsigned int>(solution_names->size());
if (!(v->size() == mesh.n_nodes()*n_vars))
libMesh::err << "ERROR: v->size()=" << v->size()
<< ", mesh.n_nodes()=" << mesh.n_nodes()
<< ", n_vars=" << n_vars
<< ", mesh.n_nodes()*n_vars=" << mesh.n_nodes()*n_vars
<< "\n";
libmesh_assert_equal_to (v->size(), mesh.n_nodes()*n_vars);
// write the header
out_stream << "$PostFormat\n";
if (this->binary())
out_stream << "1.2 1 " << sizeof(double) << "\n";
else
out_stream << "1.2 0 " << sizeof(double) << "\n";
out_stream << "$EndPostFormat\n";
// Loop over the elements to see how much of each type there are
unsigned int n_points=0, n_lines=0, n_triangles=0, n_quadrangles=0,
n_tetrahedra=0, n_hexahedra=0, n_prisms=0, n_pyramids=0;
unsigned int n_scalar=0, n_vector=0, n_tensor=0;
unsigned int nb_text2d=0, nb_text2d_chars=0, nb_text3d=0, nb_text3d_chars=0;
{
MeshBase::const_element_iterator it = mesh.active_elements_begin();
const MeshBase::const_element_iterator end = mesh.active_elements_end();
for ( ; it != end; ++it)
{
const ElemType elemtype = (*it)->type();
switch (elemtype)
{
case EDGE2:
case EDGE3:
case EDGE4:
{
n_lines += 1;
break;
}
case TRI3:
case TRI6:
{
n_triangles += 1;
break;
}
case QUAD4:
case QUAD8:
case QUAD9:
{
n_quadrangles += 1;
break;
}
case TET4:
case TET10:
{
n_tetrahedra += 1;
break;
}
case HEX8:
case HEX20:
case HEX27:
{
n_hexahedra += 1;
break;
}
case PRISM6:
case PRISM15:
case PRISM18:
{
n_prisms += 1;
break;
}
case PYRAMID5:
{
n_pyramids += 1;
break;
}
default:
libmesh_error_msg("ERROR: Nonexistent element type " << (*it)->type());
}
}
}
// create a view for each variable
for (unsigned int ivar=0; ivar < n_vars; ivar++)
{
std::string varname = (*solution_names)[ivar];
// at the moment, we just write out scalar quantities
// later this should be made configurable through
// options to the writer class
n_scalar = 1;
// write the variable as a view, and the number of time steps
out_stream << "$View\n" << varname << " " << 1 << "\n";
// write how many of each geometry type are written
out_stream << n_points * n_scalar << " "
<< n_points * n_vector << " "
<< n_points * n_tensor << " "
<< n_lines * n_scalar << " "
<< n_lines * n_vector << " "
<< n_lines * n_tensor << " "
<< n_triangles * n_scalar << " "
<< n_triangles * n_vector << " "
<< n_triangles * n_tensor << " "
<< n_quadrangles * n_scalar << " "
<< n_quadrangles * n_vector << " "
<< n_quadrangles * n_tensor << " "
<< n_tetrahedra * n_scalar << " "
<< n_tetrahedra * n_vector << " "
<< n_tetrahedra * n_tensor << " "
<< n_hexahedra * n_scalar << " "
<< n_hexahedra * n_vector << " "
<< n_hexahedra * n_tensor << " "
<< n_prisms * n_scalar << " "
<< n_prisms * n_vector << " "
<< n_prisms * n_tensor << " "
<< n_pyramids * n_scalar << " "
<< n_pyramids * n_vector << " "
<< n_pyramids * n_tensor << " "
<< nb_text2d << " "
<< nb_text2d_chars << " "
<< nb_text3d << " "
<< nb_text3d_chars << "\n";
// if binary, write a marker to identify the endianness of the file
if (this->binary())
{
const int one = 1;
std::memcpy(buf, &one, sizeof(int));
out_stream.write(buf, sizeof(int));
}
// the time steps (there is just 1 at the moment)
if (this->binary())
{
double one = 1;
std::memcpy(buf, &one, sizeof(double));
out_stream.write(buf, sizeof(double));
}
else
out_stream << "1\n";
// Loop over the elements and write out the data
MeshBase::const_element_iterator it = mesh.active_elements_begin();
const MeshBase::const_element_iterator end = mesh.active_elements_end();
for ( ; it != end; ++it)
{
const Elem* elem = *it;
// this is quite crappy, but I did not invent that file format!
for (unsigned int d=0; d<3; d++) // loop over the dimensions
{
for (unsigned int n=0; n < elem->n_vertices(); n++) // loop over vertices
{
const Point& vertex = elem->point(n);
if (this->binary())
{
double tmp = vertex(d);
std::memcpy(buf, &tmp, sizeof(double));
out_stream.write(reinterpret_cast<char *>(buf), sizeof(double));
}
else
out_stream << vertex(d) << " ";
}
if (!this->binary())
out_stream << "\n";
}
// now finally write out the data
for (unsigned int i=0; i < elem->n_vertices(); i++) // loop over vertices
if (this->binary())
{
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
libMesh::out << "WARNING: Gmsh::write_post does not fully support "
<< "complex numbers. Will only write the real part of "
<< "variable " << varname << std::endl;
#endif
double tmp = libmesh_real((*v)[elem->node(i)*n_vars + ivar]);
std::memcpy(buf, &tmp, sizeof(double));
out_stream.write(reinterpret_cast<char *>(buf), sizeof(double));
}
else
{
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
libMesh::out << "WARNING: Gmsh::write_post does not fully support "
<< "complex numbers. Will only write the real part of "
<< "variable " << varname << std::endl;
#endif
out_stream << libmesh_real((*v)[elem->node(i)*n_vars + ivar]) << "\n";
}
}
if (this->binary())
out_stream << "\n";
out_stream << "$EndView\n";
} // end variable loop (writing the views)
}
}
bool libMesh::GmshIO::_binary [private] |
const bool libMesh::MeshOutput< MeshBase >::_is_parallel_format [protected, inherited] |
Flag specifying whether this format is parallel-capable. If this is false (default) I/O is only permitted when the mesh has been serialized.
Definition at line 126 of file mesh_output.h.
Referenced by libMesh::FroIO::write(), libMesh::DivaIO::write(), libMesh::PostscriptIO::write(), and libMesh::EnsightIO::write().
std::vector<bool> libMesh::MeshInput< MeshBase >::elems_of_dimension [protected, inherited] |
A vector of bools describing what dimension elements have been encountered when reading a mesh.
Definition at line 100 of file mesh_input.h.
Referenced by libMesh::GMVIO::_read_one_cell(), libMesh::UNVIO::elements_in(), libMesh::UNVIO::max_elem_dimension_seen(), libMesh::AbaqusIO::max_elem_dimension_seen(), libMesh::AbaqusIO::read(), libMesh::Nemesis_IO::read(), libMesh::ExodusII_IO::read(), libMesh::GMVIO::read(), libMesh::VTKIO::read(), libMesh::AbaqusIO::read_elements(), libMesh::UCDIO::read_implementation(), libMesh::UNVIO::read_implementation(), libMesh::LegacyXdrIO::read_mesh(), and libMesh::XdrIO::read_serialized_connectivity().