$extrastylesheet
#include <abaqus_io.h>

Public Member Functions | |
| AbaqusIO (MeshBase &mesh) | |
| virtual | ~AbaqusIO () |
| virtual void | read (const std::string &name) |
Public Attributes | |
| bool | build_sidesets_from_nodesets |
Protected Member Functions | |
| MeshBase & | mesh () |
| void | set_n_partitions (unsigned int n_parts) |
| void | skip_comment_lines (std::istream &in, const char comment_start) |
Protected Attributes | |
| std::vector< bool > | elems_of_dimension |
Private Types | |
| typedef std::map< std::string, std::vector< dof_id_type > > | container_t |
| typedef std::map< std::string, std::vector< std::pair < dof_id_type, unsigned > > > | sideset_container_t |
Private Member Functions | |
| void | read_nodes (std::string nset_name) |
| void | read_elements (std::string upper, std::string elset_name) |
| std::string | parse_label (std::string line, std::string label_name) |
| void | read_ids (std::string set_name, container_t &container) |
| void | assign_subdomain_ids () |
| void | read_sideset (std::string sideset_name, sideset_container_t &container) |
| void | assign_boundary_node_ids () |
| void | assign_sideset_ids () |
| void | process_and_discard_comments () |
| unsigned char | max_elem_dimension_seen () |
Private Attributes | |
| container_t | _nodeset_ids |
| container_t | _elemset_ids |
| sideset_container_t | _sideset_ids |
| std::ifstream | _in |
| std::set< ElemType > | _elem_types |
| std::map< dof_id_type, dof_id_type > | _abaqus_to_libmesh_elem_mapping |
| std::map< dof_id_type, dof_id_type > | _abaqus_to_libmesh_node_mapping |
| bool | _already_seen_part |
The AbaqusIO class is a preliminary implementation for reading Abaqus mesh files in ASCII format.
Definition at line 38 of file abaqus_io.h.
typedef std::map<std::string, std::vector<dof_id_type> > libMesh::AbaqusIO::container_t [private] |
The type of data structure used to store Node and Elemset IDs.
Definition at line 68 of file abaqus_io.h.
typedef std::map<std::string, std::vector<std::pair<dof_id_type, unsigned> > > libMesh::AbaqusIO::sideset_container_t [private] |
Type of the data structure for storing the (elem ID, side) pairs defining sidesets. These come from the *Surface sections of the input file.
Definition at line 75 of file abaqus_io.h.
| libMesh::AbaqusIO::AbaqusIO | ( | MeshBase & | mesh | ) | [explicit] |
Constructor. Takes a writeable reference to a mesh object.
Definition at line 187 of file abaqus_io.C.
: MeshInput<MeshBase> (mesh_in), build_sidesets_from_nodesets(false), _already_seen_part(false) { }
| libMesh::AbaqusIO::~AbaqusIO | ( | ) | [virtual] |
| void libMesh::AbaqusIO::assign_boundary_node_ids | ( | ) | [private] |
This function assigns boundary IDs to node sets based on the alphabetical order in which the sets are labelled in the Abaqus file. We choose the alphabetical ordering simply because Abaqus does not provide a numerical one within the file.
Definition at line 847 of file abaqus_io.C.
References _abaqus_to_libmesh_node_mapping, _nodeset_ids, libMesh::BoundaryInfo::add_node(), libMesh::MeshBase::get_boundary_info(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::node_ptr(), and libMesh::BoundaryInfo::nodeset_name().
Referenced by read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// Iterate over the container of nodesets
container_t::iterator it = _nodeset_ids.begin();
for (unsigned short current_id=0; it != _nodeset_ids.end(); ++it, ++current_id)
{
// Associate current_id with the name we determined earlier
the_mesh.get_boundary_info().nodeset_name(current_id) = it->first;
// Get a reference to the current vector of nodeset ID values
std::vector<dof_id_type>& nodeset_ids = it->second;
for (std::size_t i=0; i<nodeset_ids.size(); ++i)
{
// Map the Abaqus global node ID to the libmesh node ID
dof_id_type libmesh_global_node_id = _abaqus_to_libmesh_node_mapping[nodeset_ids[i]];
// Get node pointer from the mesh
Node* node = the_mesh.node_ptr(libmesh_global_node_id);
if (node == NULL)
libmesh_error_msg("Error! Mesh returned NULL node pointer!");
// Add this node with the current_id (which is determined by the
// alphabetical ordering of the map) to the BoundaryInfo object
the_mesh.get_boundary_info().add_node(node, current_id);
}
}
}
| void libMesh::AbaqusIO::assign_sideset_ids | ( | ) | [private] |
Called at the end of the read() function, assigns any sideset IDs found when reading the file to the BoundaryInfo object.
Definition at line 883 of file abaqus_io.C.
References _abaqus_to_libmesh_elem_mapping, _elemset_ids, _sideset_ids, libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::BoundaryInfo::add_side(), libMesh::Elem::build_side(), libMesh::Elem::dim(), libMesh::MeshBase::elem(), end, libMesh::Utility::enum_to_string(), libMesh::MeshBase::get_boundary_info(), max_elem_dimension_seen(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::node(), side, libMesh::BoundaryInfo::sideset_name(), and libMesh::Elem::type().
Referenced by read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// initialize the eletypes map (eletypes is a file-global variable)
init_eletypes();
// Iterate over the container of sidesets
{
sideset_container_t::iterator it = _sideset_ids.begin();
for (unsigned short current_id=0; it != _sideset_ids.end(); ++it, ++current_id)
{
// Associate current_id with the name we determined earlier
the_mesh.get_boundary_info().sideset_name(current_id) = it->first;
// Get a reference to the current vector of nodeset ID values
std::vector<std::pair<dof_id_type,unsigned> >& sideset_ids = it->second;
for (std::size_t i=0; i<sideset_ids.size(); ++i)
{
// sideset_ids is a vector of pairs (elem id, side id). Pull them out
// now to make the code below more readable.
dof_id_type abaqus_elem_id = sideset_ids[i].first;
unsigned abaqus_side_number = sideset_ids[i].second;
// Map the Abaqus element ID to LibMesh numbering
dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[ abaqus_elem_id ];
// Get pointer to that element
Elem* elem = the_mesh.elem(libmesh_elem_id);
// Check that the pointer returned from the Mesh is non-NULL
if (elem == NULL)
libmesh_error_msg("Mesh returned NULL pointer for Elem " << libmesh_elem_id);
// Grab a reference to the element definition for this element type
const ElementDefinition& eledef = eletypes[elem->type()];
// If the element definition was not found, the call above would have
// created one with an uninitialized struct. Check for that here...
if (eledef.abaqus_zero_based_side_id_to_libmesh_side_id.size() == 0)
libmesh_error_msg("No Abaqus->LibMesh mapping information for ElemType " \
<< Utility::enum_to_string(elem->type()) \
<< "!");
// Add this node with the current_id (which is determined by the
// alphabetical ordering of the map). Side numbers in Abaqus are 1-based,
// so we subtract 1 here before passing the abaqus side number to the
// mapping array
the_mesh.get_boundary_info().add_side
(elem,
eledef.abaqus_zero_based_side_id_to_libmesh_side_id[abaqus_side_number-1],
current_id);
}
}
}
// Some elsets (if they contain lower-dimensional elements) also
// define sidesets. So loop over them and build a searchable data
// structure we can use to assign sidesets.
{
unsigned char max_dim = this->max_elem_dimension_seen();
// multimap from "vector-of-lower-dimensional-element-node-ids" to subdomain ID which should be applied.
// We use a multimap because the lower-dimensional elements can belong to more than 1 sideset.
typedef std::multimap<std::vector<dof_id_type>, unsigned> provide_bcs_t;
provide_bcs_t provide_bcs;
// The elemset_id counter assigns a logical numbering to the _elemset_ids keys
container_t::iterator it = _elemset_ids.begin();
for (unsigned short elemset_id=0; it != _elemset_ids.end(); ++it, ++elemset_id)
{
// Grab a reference to the vector of IDs
std::vector<dof_id_type>& id_vector = it->second;
// Loop over this vector
for (std::size_t i=0; i<id_vector.size(); ++i)
{
// Map the id_vector[i]'th element ID (Abaqus numbering) to LibMesh numbering
dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[ id_vector[i] ];
// Get pointer to that element
Elem* elem = the_mesh.elem(libmesh_elem_id);
if (elem == NULL)
libmesh_error_msg("Mesh returned NULL pointer for Elem " << libmesh_elem_id);
// If the element dimension is equal to the maximum
// dimension seen, we can break out of this for loop --
// this elset does not contain sideset information.
if (elem->dim() == max_dim)
break;
// We can only handle elements that are *exactly*
// one dimension lower than the max element
// dimension. Not sure if "edge" BCs in 3D
// actually make sense/are required...
if (elem->dim()+1 != max_dim)
libmesh_error_msg("ERROR: Expected boundary element of dimension " << max_dim-1 << " but got " << elem->dim());
// To be pushed into the provide_bcs data container
std::vector<dof_id_type> elem_node_ids(elem->n_nodes());
// Save node IDs in a local vector which will be used as a key for the map.
for (unsigned n=0; n<elem->n_nodes(); n++)
elem_node_ids[n] = elem->node(n);
// Sort before putting into the map
std::sort(elem_node_ids.begin(), elem_node_ids.end());
// Insert the (key, id) pair into the multimap
provide_bcs.insert(std::make_pair(elem_node_ids, elemset_id));
// Associate the name of this sideset with the ID we've
// chosen. It's not necessary to do this for every
// element in the set, but it's convenient to do it here
// since we have all the necessary information...
the_mesh.get_boundary_info().sideset_name(elemset_id) = it->first;
}
}
// Loop over elements and try to assign boundary information
{
MeshBase::element_iterator e_it = the_mesh.active_elements_begin();
const MeshBase::element_iterator end = the_mesh.active_elements_end();
for ( ; e_it != end; ++e_it)
{
Elem* elem = *e_it;
if (elem->dim() == max_dim)
{
// 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 multimap
std::pair<provide_bcs_t::const_iterator, provide_bcs_t::const_iterator>
range = provide_bcs.equal_range (node_ids);
// Add boundary information for each side in the range.
for (provide_bcs_t::const_iterator s_it = range.first;
s_it != range.second; ++s_it)
the_mesh.get_boundary_info().add_side
(elem, sn, cast_int<unsigned short>(s_it->second));
}
}
}
}
}
}
| void libMesh::AbaqusIO::assign_subdomain_ids | ( | ) | [private] |
This function is called after all the elements have been read and assigns element subdomain IDs.
The IDs are simply chosen in the order in which the elset labels are stored in the map (roughly alphabetically). To make this easy on people who are planning to use Exodus output, we'll assign different geometric elements to different (but related) subdomains, i.e. assuming there are E elemsets:
Elemset 0, Geometric Type 0: ID 0 Elemset 0, Geometric Type 1: ID 0+E ... Elemset 0, Geometric Type N: ID 0+N*E -------------------------------------- Elemset 1, Geometric Type 0: ID 1 Elemset 1, Geometric Type 1: ID 1+E ... Elemset 1, Geometric Type N: ID 1+N*E etc.
Definition at line 775 of file abaqus_io.C.
References _abaqus_to_libmesh_elem_mapping, _elem_types, _elemset_ids, libMesh::Elem::dim(), libMesh::MeshBase::elem(), libMesh::Utility::enum_to_string(), max_elem_dimension_seen(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::Elem::subdomain_id(), libMesh::MeshBase::subdomain_name(), and libMesh::Elem::type().
Referenced by read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// The number of elemsets we've found while reading
std::size_t n_elemsets = _elemset_ids.size();
// Fill in a temporary map with (ElemType, index) pairs based on the _elem_types set. This
// will allow us to easily look up this index in the loop below.
std::map<ElemType, unsigned> elem_types_map;
{
unsigned ctr=0;
for (std::set<ElemType>::iterator it=_elem_types.begin(); it!=_elem_types.end(); ++it)
elem_types_map[*it] = ctr++;
}
// Loop over each Elemset and assign subdomain IDs to Mesh elements
{
// The maximum element dimension seen while reading the Mesh
unsigned char max_dim = this->max_elem_dimension_seen();
// The elemset_id counter assigns a logical numbering to the _elemset_ids keys
container_t::iterator it = _elemset_ids.begin();
for (unsigned elemset_id=0; it != _elemset_ids.end(); ++it, ++elemset_id)
{
// Grab a reference to the vector of IDs
std::vector<dof_id_type>& id_vector = it->second;
// Loop over this vector
for (std::size_t i=0; i<id_vector.size(); ++i)
{
// Map the id_vector[i]'th element ID (Abaqus numbering) to LibMesh numbering
dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[ id_vector[i] ];
// Get pointer to that element
Elem* elem = the_mesh.elem(libmesh_elem_id);
if (elem == NULL)
libmesh_error_msg("Mesh returned NULL pointer for Elem " << libmesh_elem_id);
// We won't assign subdomain ids to lower-dimensional
// elements, as they are assumed to represent boundary
// conditions. Since lower-dimensional elements can
// appear in multiple sidesets, it doesn't make sense to
// assign them a single subdomain id... only the last one
// assigned would actually "stick".
if (elem->dim() < max_dim)
break;
// Compute the proper subdomain ID, based on the formula in the
// documentation for this function.
subdomain_id_type computed_id = cast_int<subdomain_id_type>
(elemset_id + (elem_types_map[elem->type()] * n_elemsets));
// Assign this ID to the element in question
elem->subdomain_id() = computed_id;
// We will also assign a unique name to the computed_id,
// which is created by appending the geometric element
// name to the elset name provided by the user in the
// Abaqus file.
std::string computed_name = it->first + "_" + Utility::enum_to_string(elem->type());
the_mesh.subdomain_name(computed_id) = computed_name;
}
}
}
}
| unsigned char libMesh::AbaqusIO::max_elem_dimension_seen | ( | ) | [private] |
Returns the maximum geometric element dimension encountered while reading the Mesh. Only valid after the elements have been read in and the elems_of_dimension array has been populated.
Definition at line 1095 of file abaqus_io.C.
References libMesh::MeshInput< MeshBase >::elems_of_dimension.
Referenced by assign_sideset_ids(), assign_subdomain_ids(), and read().
{
unsigned char max_dim = 0;
unsigned char elem_dimensions_size = cast_int<unsigned char>
(elems_of_dimension.size());
// The elems_of_dimension array is 1-based in the UNV reader
for (unsigned char i=1; i<elem_dimensions_size; ++i)
if (elems_of_dimension[i])
max_dim = i;
return max_dim;
}
| 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(), assign_boundary_node_ids(), assign_sideset_ids(), 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(), 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(), read_elements(), libMesh::UCDIO::read_implementation(), libMesh::UNVIO::read_implementation(), libMesh::GmshIO::read_mesh(), libMesh::LegacyXdrIO::read_mesh(), 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(), libMesh::GmshIO::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(), libMesh::GmshIO::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().
| std::string libMesh::AbaqusIO::parse_label | ( | std::string | line, |
| std::string | label_name | ||
| ) | [private] |
This function parses a label of the form foo=bar from a comma-delimited line of the form ..., foo=bar, ... The input to the function in this case would be foo, the output would be bar
Definition at line 652 of file abaqus_io.C.
References end.
Referenced by read().
{
// Handle files which have weird line endings from e.g. windows.
// You can check what kind of line endings you have with 'cat -vet'.
// For example, some files may have two kinds of line endings like:
//
// 4997,^I496,^I532,^I487,^I948^M$
//
// and we don't want to deal with this when extracting a label, so
// just remove all the space characters, which should include all
// kinds of remaining newlines. (I don't think Abaqus allows
// whitespace in label names.)
line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end());
// Do all string comparisons in upper-case
std::string
upper_line(line),
upper_label_name(label_name);
std::transform(upper_line.begin(), upper_line.end(), upper_line.begin(), ::toupper);
std::transform(upper_label_name.begin(), upper_label_name.end(), upper_label_name.begin(), ::toupper);
// Get index of start of "label="
size_t label_index = upper_line.find(upper_label_name + "=");
if (label_index != std::string::npos)
{
// Location of the first comma following "label="
size_t comma_index = upper_line.find(",", label_index);
// Construct iterators from which to build the sub-string.
// Note: The +1 while initializing beg is to skip past the "=" which follows the label name
std::string::iterator
beg = line.begin() + label_name.size() + 1 + label_index,
end = (comma_index == std::string::npos) ? line.end() : line.begin() + comma_index;
return std::string(beg, end);
}
// The label index was not found, return the empty string
return std::string("");
}
| void libMesh::AbaqusIO::process_and_discard_comments | ( | ) | [private] |
Any of the various sections can start with some number of lines of comments, which start with "**". This function discards any lines of comments that it finds from the stream, leaving trailing data intact.
Definition at line 1052 of file abaqus_io.C.
References _in.
Referenced by read().
{
std::string dummy;
while (true)
{
// We assume we are at the beginning of a line that may be
// comments or may be data. We need to only discard the line if
// it begins with **, but we must avoid calling std::getline()
// since there's no way to put that back.
if (_in.peek() == '*')
{
// The first character was a star, so actually read it from the stream.
_in.get();
// Peek at the next character...
if (_in.peek() == '*')
{
// OK, second character was star also, by definition this
// line must be a comment! Read the rest of the line and discard!
std::getline(_in, dummy);
}
else
{
// The second character was _not_ a star, so put back the first star
// we pulled out so that the line can be parsed correctly by somebody
// else!
_in.unget();
// Finally, break out of the while loop, we are done parsing comments
break;
}
}
else
{
// First character was not *, so this line must be data! Break out of the
// while loop!
break;
}
}
}
| void libMesh::AbaqusIO::read | ( | const std::string & | name | ) | [virtual] |
This method implements reading a mesh from a specified file.
Implements libMesh::MeshInput< MeshBase >.
Definition at line 204 of file abaqus_io.C.
References _already_seen_part, _elemset_ids, _in, _nodeset_ids, _sideset_ids, assign_boundary_node_ids(), assign_sideset_ids(), assign_subdomain_ids(), libMesh::BoundaryInfo::build_side_list_from_node_list(), build_sidesets_from_nodesets, libMesh::MeshBase::clear(), libMesh::MeshBase::delete_elem(), libMesh::Elem::dim(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::MeshInput< MeshBase >::elems_of_dimension, libMesh::MeshBase::get_boundary_info(), libMesh::libmesh_assert(), max_elem_dimension_seen(), libMesh::MeshInput< MeshBase >::mesh(), parse_label(), process_and_discard_comments(), read_elements(), read_ids(), read_nodes(), read_sideset(), and libMesh::MeshBase::set_mesh_dimension().
Referenced by libMesh::NameBasedIO::read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// Clear any existing mesh data
the_mesh.clear();
// Open stream for reading
_in.open(fname.c_str());
libmesh_assert(_in.good());
// Initialize the elems_of_dimension array. We will use this in a
// "1-based" manner so that elems_of_dimension[d]==true means
// elements of dimension d have been seen.
elems_of_dimension.resize(4, false);
// Read file line-by-line... this is based on a set of different
// test input files. I have not looked at the full input file
// specs for Abaqus.
std::string s;
while (true)
{
// Try to read something. This may set EOF!
std::getline(_in, s);
if (_in)
{
// Process s...
//
// There are many sections in Abaqus files, we read some
// but others are just ignored... Some sections may occur
// more than once. For example for a hybrid grid, you
// will have multiple *Element sections...
// Some Abaqus files use all upper-case for section names,
// so we will just convert s to uppercase
std::string upper(s);
std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
// 0.) Look for the "*Part" section
if (upper.find("*PART") == static_cast<std::string::size_type>(0))
{
if (_already_seen_part)
libmesh_error_msg("We currently don't support reading Abaqus files with multiple PART sections");
_already_seen_part = true;
}
// 1.) Look for the "*Nodes" section
if (upper.find("*NODE") == static_cast<std::string::size_type>(0))
{
// Some sections that begin with *NODE are actually
// "*NODE OUTPUT" sections which we want to skip. I
// have only seen this with a single space, but it would
// probably be more robust to remove whitespace before
// making this check.
if (upper.find("*NODE OUTPUT") == static_cast<std::string::size_type>(0))
continue;
// Some *Node sections also specify an Nset name on the same line.
// Look for one here.
std::string nset_name = this->parse_label(s, "nset");
// Process any lines of comments that may be present
this->process_and_discard_comments();
// Read a block of nodes
this->read_nodes(nset_name);
}
// 2.) Look for the "*Element" section
else if (upper.find("*ELEMENT,") == static_cast<std::string::size_type>(0))
{
// Some sections that begin with *ELEMENT are actually
// "*ELEMENT OUTPUT" sections which we want to skip. I
// have only seen this with a single space, but it would
// probably be more robust to remove whitespace before
// making this check.
if (upper.find("*ELEMENT OUTPUT") == static_cast<std::string::size_type>(0))
continue;
// Some *Element sections also specify an Elset name on the same line.
// Look for one here.
std::string elset_name = this->parse_label(s, "elset");
// Process any lines of comments that may be present
this->process_and_discard_comments();
// Read a block of elements
this->read_elements(upper, elset_name);
}
// 3.) Look for a Nodeset section
else if (upper.find("*NSET") == static_cast<std::string::size_type>(0))
{
std::string nset_name = this->parse_label(s, "nset");
// I haven't seen an unnamed nset yet, but let's detect it
// just in case...
if (nset_name == "")
libmesh_error_msg("Unnamed nset encountered!");
// Process any lines of comments that may be present
this->process_and_discard_comments();
// Read the IDs, storing them in _nodeset_ids
this->read_ids(nset_name, _nodeset_ids);
} // *Nodeset
// 4.) Look for an Elset section
else if (upper.find("*ELSET") == static_cast<std::string::size_type>(0))
{
std::string elset_name = this->parse_label(s, "elset");
// I haven't seen an unnamed elset yet, but let's detect it
// just in case...
if (elset_name == "")
libmesh_error_msg("Unnamed elset encountered!");
// Process any lines of comments that may be present
this->process_and_discard_comments();
// Read the IDs, storing them in _elemset_ids
this->read_ids(elset_name, _elemset_ids);
} // *Elset
// 5.) Look for a Surface section. Need to be a little
// careful, since there are also "surface interaction"
// sections we don't want to read here.
else if (upper.find("*SURFACE,") == static_cast<std::string::size_type>(0))
{
// Get the name from the Name=Foo label. This will be the map key.
std::string sideset_name = this->parse_label(s, "name");
// Process any lines of comments that may be present
this->process_and_discard_comments();
// Read the sideset IDs
this->read_sideset(sideset_name, _sideset_ids);
}
continue;
} // if (_in)
// If !file, 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: " << fname << " does not exist?");
} // while
// Set the Mesh dimension based on the highest dimension element seen.
the_mesh.set_mesh_dimension(this->max_elem_dimension_seen());
// Set element IDs based on the element sets.
this->assign_subdomain_ids();
// Assign nodeset values to the BoundaryInfo object
this->assign_boundary_node_ids();
// Assign sideset values in the BoundaryInfo object
this->assign_sideset_ids();
// Abaqus files only contain nodesets by default. To be useful in
// applying most types of BCs in libmesh, we will definitely need
// sidesets. So we can call the new BoundaryInfo function which
// generates sidesets from nodesets.
if (build_sidesets_from_nodesets)
the_mesh.get_boundary_info().build_side_list_from_node_list();
// Delete lower-dimensional elements from the Mesh. We assume these
// were only used for setting BCs, and aren't part of the actual
// Mesh.
{
unsigned char max_dim = this->max_elem_dimension_seen();
MeshBase::element_iterator el = the_mesh.elements_begin();
const MeshBase::element_iterator end_el = the_mesh.elements_end();
for (; el != end_el; ++el)
{
Elem* elem = *el;
if (elem->dim() < max_dim)
the_mesh.delete_elem(elem);
}
}
}
| void libMesh::AbaqusIO::read_elements | ( | std::string | upper, |
| std::string | elset_name | ||
| ) | [private] |
This function parses a block of elements in the Abaqus file. You must pass it an upper-cased version of the string declaring this section, which is typically something like: *ELEMENT, TYPE=CPS3 so that it can determine the type of elements to read.
Definition at line 481 of file abaqus_io.C.
References _abaqus_to_libmesh_elem_mapping, _abaqus_to_libmesh_node_mapping, _elem_types, _elemset_ids, _in, libMesh::MeshBase::add_elem(), libMesh::Elem::build(), libMesh::EDGE2, libMesh::MeshInput< MeshBase >::elems_of_dimension, libMesh::Utility::enum_to_string(), libMesh::HEX20, libMesh::HEX8, libMesh::DofObject::id(), libMesh::INVALID_ELEM, libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::node_ptr(), libMesh::PRISM15, libMesh::PRISM6, libMesh::QUAD4, libMesh::Elem::set_node(), libMesh::TET10, libMesh::TET4, and libMesh::TRI3.
Referenced by read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// initialize the eletypes map (eletypes is a file-global variable)
init_eletypes();
ElemType elem_type = INVALID_ELEM;
unsigned n_nodes_per_elem = 0;
// Within s, we should have "type=XXXX"
if (upper.find("T3D2") != std::string::npos)
{
elem_type = EDGE2;
n_nodes_per_elem = 2;
elems_of_dimension[1] = true;
}
else if (upper.find("CPE4") != std::string::npos ||
upper.find("CPS4") != std::string::npos)
{
elem_type = QUAD4;
n_nodes_per_elem = 4;
elems_of_dimension[2] = true;
}
else if (upper.find("CPS3") != std::string::npos ||
upper.find("S3R") != std::string::npos)
{
elem_type = TRI3;
n_nodes_per_elem = 3;
elems_of_dimension[2] = true;
}
else if (upper.find("C3D8") != std::string::npos)
{
elem_type = HEX8;
n_nodes_per_elem = 8;
elems_of_dimension[3] = true;
}
else if (upper.find("C3D4") != std::string::npos)
{
elem_type = TET4;
n_nodes_per_elem = 4;
elems_of_dimension[3] = true;
}
else if (upper.find("C3D20") != std::string::npos)
{
elem_type = HEX20;
n_nodes_per_elem = 20;
elems_of_dimension[3] = true;
}
else if (upper.find("C3D6") != std::string::npos)
{
elem_type = PRISM6;
n_nodes_per_elem = 6;
elems_of_dimension[3] = true;
}
else if (upper.find("C3D15") != std::string::npos)
{
elem_type = PRISM15;
n_nodes_per_elem = 15;
elems_of_dimension[3] = true;
}
else if (upper.find("C3D10") != std::string::npos)
{
elem_type = TET10;
n_nodes_per_elem = 10;
elems_of_dimension[3] = true;
}
else
libmesh_error_msg("Unrecognized element type: " << upper);
// Insert the elem type we detected into the set of all elem types for this mesh
_elem_types.insert(elem_type);
// Grab a reference to the element definition for this element type
const ElementDefinition& eledef = eletypes[elem_type];
// If the element definition was not found, the call above would have
// created one with an uninitialized struct. Check for that here...
if (eledef.abaqus_zero_based_node_id_to_libmesh_node_id.size() == 0)
libmesh_error_msg("No Abaqus->LibMesh mapping information for ElemType " \
<< Utility::enum_to_string(elem_type) \
<< "!");
// We will read elements until the next line begins with *, since that will be the
// next section.
while (_in.peek() != '*' && _in.peek() != EOF)
{
// Read the element ID, it is the first number on each line. It is
// followed by a comma, so read that also. We will need this ID later
// when we try to assign subdomain IDs
dof_id_type abaqus_elem_id = 0;
char c;
_in >> abaqus_elem_id >> c;
// Add an element of the appropriate type to the Mesh.
Elem* elem = the_mesh.add_elem(Elem::build(elem_type).release());
// Associate the ID returned from libmesh with the abaqus element ID
//_libmesh_to_abaqus_elem_mapping[elem->id()] = abaqus_elem_id;
_abaqus_to_libmesh_elem_mapping[abaqus_elem_id] = elem->id();
// The count of the total number of IDs read for the current element.
unsigned id_count=0;
// Continue reading line-by-line until we have read enough nodes for this element
while (id_count < n_nodes_per_elem)
{
// Read entire line (up to carriage return) of comma-separated values
std::string csv_line;
std::getline(_in, csv_line);
// Create a stream object out of the current line
std::stringstream line_stream(csv_line);
// Process the comma-separated values
std::string cell;
while (std::getline(line_stream, cell, ','))
{
// FIXME: factor out this strtol stuff into a utility function.
char* endptr;
dof_id_type abaqus_global_node_id = cast_int<dof_id_type>
(std::strtol(cell.c_str(), &endptr, /*base=*/10));
if (abaqus_global_node_id!=0 || cell.c_str() != endptr)
{
// Use the global node number mapping to determine the corresponding libmesh global node id
dof_id_type libmesh_global_node_id = _abaqus_to_libmesh_node_mapping[abaqus_global_node_id];
// Grab the node pointer from the mesh for this ID
Node* node = the_mesh.node_ptr(libmesh_global_node_id);
// If node_ptr() returns NULL, it may mean we have not yet read the
// *Nodes section, though I assumed that always came before the *Elements section...
if (node == NULL)
libmesh_error_msg("Error! Mesh returned NULL Node pointer. Either no node exists with ID " \
<< libmesh_global_node_id \
<< " or perhaps this input file has *Elements defined before *Nodes?");
// Note: id_count is the zero-based abaqus (elem local) node index. We therefore map
// it to a libmesh elem local node index using the element definition map
unsigned libmesh_elem_local_node_id =
eledef.abaqus_zero_based_node_id_to_libmesh_node_id[id_count];
// Set this node pointer within the element.
elem->set_node(libmesh_elem_local_node_id) = node;
// Increment the count of IDs read for this element
id_count++;
} // end if strtol success
} // end while getline(',')
} // end while (id_count)
// Ensure that we read *exactly* as many nodes as we were expecting to, no more.
if (id_count != n_nodes_per_elem)
libmesh_error_msg("Error: Needed to read " \
<< n_nodes_per_elem \
<< " nodes, but read " \
<< id_count \
<< " instead!");
// If we are recording Elset IDs, add this element to the correct set for later processing.
// Make sure to add it with the Abaqus ID, not the libmesh one!
if (elset_name != "")
_elemset_ids[elset_name].push_back(abaqus_elem_id);
} // end while (peek)
}
| void libMesh::AbaqusIO::read_ids | ( | std::string | set_name, |
| container_t & | container | ||
| ) | [private] |
This function reads all the IDs for the current node or element set of the given name, storing them in the passed map using the name as key.
Definition at line 697 of file abaqus_io.C.
References _in.
Referenced by read().
{
// Grab a reference to a vector that will hold all the IDs
std::vector<dof_id_type>& id_storage = container[set_name];
// Read until the start of another section is detected, or EOF is encountered
while (_in.peek() != '*' && _in.peek() != EOF)
{
// Read entire comma-separated line into a string
std::string csv_line;
std::getline(_in, csv_line);
// On that line, use std::getline again to parse each
// comma-separated entry.
std::string cell;
std::stringstream line_stream(csv_line);
while (std::getline(line_stream, cell, ','))
{
// If no conversion can be performed by strtol, 0 is returned.
//
// If endptr is not NULL, strtol() stores the address of the
// first invalid character in *endptr. If there were no
// digits at all, however, strtol() stores the original
// value of str in *endptr.
char* endptr;
// FIXME - this needs to be updated for 64-bit inputs
dof_id_type id = cast_int<dof_id_type>
(std::strtol(cell.c_str(), &endptr, /*base=*/10));
// Note that lists of comma-separated values in abaqus also
// *end* with a comma, so the last call to getline on a given
// line will get an empty string, which we must detect.
if (id != 0 || cell.c_str() != endptr)
{
// 'cell' is now a string with an integer id in it
id_storage.push_back( id );
}
}
}
}
| void libMesh::AbaqusIO::read_nodes | ( | std::string | nset_name | ) | [private] |
This function parses a block of nodes in the Abaqus file once such a block has been found. If the *NODE section specifies an NSET name, also pass that to this function.
Definition at line 410 of file abaqus_io.C.
References _abaqus_to_libmesh_node_mapping, _in, _nodeset_ids, libMesh::MeshBase::add_point(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::n_nodes(), libMesh::Real, and libMesh::x.
Referenced by read().
{
// Get a reference to the mesh we are reading
MeshBase& the_mesh = MeshInput<MeshBase>::mesh();
// In the input files I have, Abaqus neither tells what
// the mesh dimension is nor how many nodes it has...
//
// The node line format is:
// id, x, y, z
// and you do have to parse out the commas.
// The z-coordinate will only be present for 3D meshes
// Temporary variables for parsing lines of text
char c;
std::string dummy;
// Defines the sequential node numbering used by libmesh. Since
// there can be multiple *NODE sections in an Abaqus file, we always
// start our numbering with the number of nodes currently in the
// Mesh.
dof_id_type libmesh_node_id = the_mesh.n_nodes();
// We need to duplicate some of the read_ids code if this *NODE
// section also defines an NSET. We'll set up the id_storage
// pointer and push back IDs into this vector in the loop below...
std::vector<dof_id_type>* id_storage = NULL;
if (nset_name != "")
id_storage = &(_nodeset_ids[nset_name]);
// We will read nodes until the next line begins with *, since that will be the
// next section.
// TODO: Is Abaqus guaranteed to start the line with '*' or can there be leading white space?
while (_in.peek() != '*' && _in.peek() != EOF)
{
// Re-Initialize variables to be read in from file
dof_id_type abaqus_node_id=0;
Real x=0, y=0, z=0;
// Note: we assume *at least* 2D points here, should we worry about
// trying to read 1D Abaqus meshes?
_in >> abaqus_node_id >> c >> x >> c >> y;
// Peek at the next character. If it is a comma, then there is another
// value to read!
if (_in.peek() == ',')
_in >> c >> z;
// Read (and discard) the rest of the line, including the newline.
// This is required so that our 'peek()' at the beginning of this
// loop doesn't read the newline character, for example.
std::getline(_in, dummy);
// If this *NODE section defines an NSET, also store the abaqus ID in id_storage
if (id_storage)
id_storage->push_back(abaqus_node_id);
// Set up the abaqus -> libmesh node mapping. This is usually just the
// "off-by-one" map.
_abaqus_to_libmesh_node_mapping[abaqus_node_id] = libmesh_node_id;
// Add the point to the mesh using libmesh's numbering,
// and post-increment the libmesh node counter.
the_mesh.add_point(Point(x,y,z), libmesh_node_id++);
} // while
}
| void libMesh::AbaqusIO::read_sideset | ( | std::string | sideset_name, |
| sideset_container_t & | container | ||
| ) | [private] |
This function reads a sideset from the input file. This is defined by a "*Surface" section in the file, and then a list of element ID and side IDs for the set.
Definition at line 742 of file abaqus_io.C.
References _in.
Referenced by read().
{
// Grab a reference to a vector that will hold all the IDs
std::vector<std::pair<dof_id_type, unsigned> >& id_storage = container[sideset_name];
// Variables for storing values read in from file
dof_id_type elem_id=0;
unsigned side_id=0;
char c;
std::string dummy;
// Read until the start of another section is detected, or EOF is encountered
while (_in.peek() != '*' && _in.peek() != EOF)
{
// The strings are of the form: "391, S2"
// Read the element ID and the leading comma
_in >> elem_id >> c;
// Read another character (the 'S') and finally the side ID
_in >> c >> side_id;
// Store this pair of data in the vector
id_storage.push_back( std::make_pair(elem_id, side_id) );
// Extract remaining characters on line including newline
std::getline(_in, dummy);
} // while
}
| 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().
std::map<dof_id_type, dof_id_type> libMesh::AbaqusIO::_abaqus_to_libmesh_elem_mapping [private] |
Map from libmesh element number -> abaqus element number, and the converse.
Definition at line 193 of file abaqus_io.h.
Referenced by assign_sideset_ids(), assign_subdomain_ids(), and read_elements().
std::map<dof_id_type, dof_id_type> libMesh::AbaqusIO::_abaqus_to_libmesh_node_mapping [private] |
Map from abaqus node number -> sequential, 0-based libmesh node numbering. Note that in every Abaqus file I've ever seen the node numbers were 1-based, sequential, and all in order, so that this map is probably overkill. Nevertheless, it is the most general solution in case we come across a weird Abaqus file some day.
Definition at line 202 of file abaqus_io.h.
Referenced by assign_boundary_node_ids(), read_elements(), and read_nodes().
bool libMesh::AbaqusIO::_already_seen_part [private] |
This flag gets set to true after the first "*PART" section we see. If it is still true when we see a second PART section, we will print an error message... we don't currently handle input files with multiple parts.
Definition at line 210 of file abaqus_io.h.
Referenced by read().
std::set<ElemType> libMesh::AbaqusIO::_elem_types [private] |
A set of the different geometric element types detected when reading the mesh.
Definition at line 186 of file abaqus_io.h.
Referenced by assign_subdomain_ids(), and read_elements().
container_t libMesh::AbaqusIO::_elemset_ids [private] |
Definition at line 174 of file abaqus_io.h.
Referenced by assign_sideset_ids(), assign_subdomain_ids(), read(), and read_elements().
std::ifstream libMesh::AbaqusIO::_in [private] |
Stream object used to interact with the file
Definition at line 180 of file abaqus_io.h.
Referenced by process_and_discard_comments(), read(), read_elements(), read_ids(), read_nodes(), and read_sideset().
container_t libMesh::AbaqusIO::_nodeset_ids [private] |
Abaqus writes nodesets and elemsets with labels. As we read them in, we'll use these maps to provide a natural ordering for them.
Definition at line 173 of file abaqus_io.h.
Referenced by assign_boundary_node_ids(), read(), and read_nodes().
Definition at line 175 of file abaqus_io.h.
Referenced by assign_sideset_ids(), and read().
Default false. Abaqus files have only nodesets in them by default. Set this flag to true if you want libmesh to automatically generate sidesets from Abaqus' nodesets.
Definition at line 62 of file abaqus_io.h.
Referenced by read().
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(), max_elem_dimension_seen(), read(), libMesh::Nemesis_IO::read(), libMesh::ExodusII_IO::read(), libMesh::GMVIO::read(), libMesh::VTKIO::read(), read_elements(), libMesh::UCDIO::read_implementation(), libMesh::UNVIO::read_implementation(), libMesh::LegacyXdrIO::read_mesh(), and libMesh::XdrIO::read_serialized_connectivity().