libMesh
Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
libMesh::AbaqusIO Class Reference

The AbaqusIO class is a preliminary implementation for reading Abaqus mesh files in ASCII format. More...

#include <abaqus_io.h>

Inheritance diagram for libMesh::AbaqusIO:
[legend]

Public Member Functions

 AbaqusIO (MeshBase &mesh)
 Constructor. More...
 
virtual ~AbaqusIO ()
 Destructor. More...
 
virtual void read (const std::string &name) override
 This method implements reading a mesh from a specified file. More...
 

Public Attributes

bool build_sidesets_from_nodesets
 Default false. More...
 

Protected Member Functions

MeshBasemesh ()
 
void set_n_partitions (unsigned int n_parts)
 Sets the number of partitions in the mesh. More...
 
void skip_comment_lines (std::istream &in, const char comment_start)
 Reads input from in, skipping all the lines that start with the character comment_start. More...
 

Protected Attributes

std::vector< bool > elems_of_dimension
 A vector of bools describing what dimension elements have been encountered when reading a mesh. More...
 

Private Types

typedef std::map< std::string, std::vector< dof_id_type > > container_t
 The type of data structure used to store Node and Elemset IDs. More...
 
typedef std::map< std::string, std::vector< std::pair< dof_id_type, unsigned > > > sideset_container_t
 Type of the data structure for storing the (elem ID, side) pairs defining sidesets. More...
 

Private Member Functions

void read_nodes (std::string nset_name)
 This function parses a block of nodes in the Abaqus file once such a block has been found. More...
 
void read_elements (std::string upper, std::string elset_name)
 This function parses a block of elements in the Abaqus file. More...
 
std::string parse_label (std::string line, std::string label_name) const
 This function parses a label of the form foo=bar from a comma-delimited line of the form ..., foo=bar, ... More...
 
bool detect_generated_set (std::string upper) const
 
void read_ids (std::string set_name, container_t &container)
 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. More...
 
void generate_ids (std::string set_name, container_t &container)
 This function handles "generated" nset and elset sections. More...
 
void assign_subdomain_ids ()
 This function is called after all the elements have been read and assigns element subdomain IDs. More...
 
void read_sideset (std::string sideset_name, sideset_container_t &container)
 This function reads a sideset from the input file. More...
 
void assign_boundary_node_ids ()
 This function assigns boundary IDs to node sets based on the alphabetical order in which the sets are labeled in the Abaqus file. More...
 
void assign_sideset_ids ()
 Called at the end of the read() function, assigns any sideset IDs found when reading the file to the BoundaryInfo object. More...
 
void process_and_discard_comments ()
 Any of the various sections can start with some number of lines of comments, which start with "**". More...
 
unsigned char max_elem_dimension_seen ()
 

Private Attributes

container_t _nodeset_ids
 Abaqus writes nodesets and elemsets with labels. More...
 
container_t _elemset_ids
 
sideset_container_t _sideset_ids
 
std::ifstream _in
 Stream object used to interact with the file. More...
 
std::set< ElemType_elem_types
 A set of the different geometric element types detected when reading the mesh. More...
 
std::map< dof_id_type, dof_id_type_abaqus_to_libmesh_elem_mapping
 Map from libmesh element number -> abaqus element number, and the converse. More...
 
std::map< dof_id_type, dof_id_type_abaqus_to_libmesh_node_mapping
 Map from abaqus node number -> sequential, 0-based libmesh node numbering. More...
 
bool _already_seen_part
 This flag gets set to true after the first "*PART" section we see. More...
 
MeshBase_obj
 A pointer to a non-const object object. More...
 
const bool _is_parallel_format
 Flag specifying whether this format is parallel-capable. More...
 

Detailed Description

The AbaqusIO class is a preliminary implementation for reading Abaqus mesh files in ASCII format.

Author
John W. Peterson
Date
2011

Definition at line 40 of file abaqus_io.h.

Member Typedef Documentation

◆ container_t

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 72 of file abaqus_io.h.

◆ sideset_container_t

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 79 of file abaqus_io.h.

Constructor & Destructor Documentation

◆ AbaqusIO()

libMesh::AbaqusIO::AbaqusIO ( MeshBase mesh)
explicit

Constructor.

Takes a writable reference to a mesh object.

Definition at line 212 of file abaqus_io.C.

212  :
213  MeshInput<MeshBase> (mesh_in),
215  _already_seen_part(false)
216 {
217 }

◆ ~AbaqusIO()

libMesh::AbaqusIO::~AbaqusIO ( )
virtual

Destructor.

Definition at line 222 of file abaqus_io.C.

223 {
224 }

Member Function Documentation

◆ assign_boundary_node_ids()

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 labeled in the Abaqus file.

We choose the alphabetical ordering simply because Abaqus does not provide a numerical one within the file.

Definition at line 977 of file abaqus_io.C.

978 {
979  // Get a reference to the mesh we are reading
980  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
981 
982  // Iterate over the container of nodesets
983  container_t::iterator it = _nodeset_ids.begin(), end = _nodeset_ids.end();
984  for (unsigned short current_id=0; it != end; ++it, ++current_id)
985  {
986  // Associate current_id with the name we determined earlier
987  the_mesh.get_boundary_info().nodeset_name(current_id) = it->first;
988 
989  // Get a reference to the current vector of nodeset ID values
990  std::vector<dof_id_type> & nodeset_ids = it->second;
991 
992  for (const auto & id : nodeset_ids)
993  {
994  // Map the Abaqus global node ID to the libmesh node ID
995  dof_id_type libmesh_global_node_id = _abaqus_to_libmesh_node_mapping[id];
996 
997  // Get node pointer from the mesh
998  Node * node = the_mesh.node_ptr(libmesh_global_node_id);
999 
1000  if (node == nullptr)
1001  libmesh_error_msg("Error! Mesh::node_ptr() returned nullptr!");
1002 
1003  // Add this node with the current_id (which is determined by the
1004  // alphabetical ordering of the map) to the BoundaryInfo object
1005  the_mesh.get_boundary_info().add_node(node, current_id);
1006  }
1007  }
1008 }

References _abaqus_to_libmesh_node_mapping, _nodeset_ids, libMesh::BoundaryInfo::add_node(), end, libMesh::MeshBase::get_boundary_info(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshBase::node_ptr(), and libMesh::BoundaryInfo::nodeset_name().

Referenced by read().

◆ assign_sideset_ids()

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 1013 of file abaqus_io.C.

1014 {
1015  // Get a reference to the mesh we are reading
1016  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
1017 
1018  // initialize the eletypes map (eletypes is a file-global variable)
1019  init_eletypes();
1020 
1021  // Iterate over the container of sidesets
1022  {
1023  sideset_container_t::iterator it = _sideset_ids.begin(), end = _sideset_ids.end();
1024  for (unsigned short current_id=0; it != end; ++it, ++current_id)
1025  {
1026  // Associate current_id with the name we determined earlier
1027  the_mesh.get_boundary_info().sideset_name(current_id) = it->first;
1028 
1029  // Get a reference to the current vector of nodeset ID values
1030  std::vector<std::pair<dof_id_type,unsigned>> & sideset_ids = it->second;
1031 
1032  for (const auto & id : sideset_ids)
1033  {
1034  // sideset_ids is a vector of pairs (elem id, side id). Pull them out
1035  // now to make the code below more readable.
1036  dof_id_type abaqus_elem_id = id.first;
1037  unsigned abaqus_side_number = id.second;
1038 
1039  // Map the Abaqus element ID to LibMesh numbering
1040  dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[ abaqus_elem_id ];
1041 
1042  // Get a reference to that element
1043  Elem & elem = the_mesh.elem_ref(libmesh_elem_id);
1044 
1045  // Grab a reference to the element definition for this element type
1046  const ElementDefinition & eledef = eletypes[elem.type()];
1047 
1048  // If the element definition was not found, the call above would have
1049  // created one with an uninitialized struct. Check for that here...
1050  if (eledef.abaqus_zero_based_side_id_to_libmesh_side_id.size() == 0)
1051  libmesh_error_msg("No Abaqus->LibMesh mapping information for ElemType " \
1052  << Utility::enum_to_string(elem.type()) \
1053  << "!");
1054 
1055  // Add this node with the current_id (which is determined by the
1056  // alphabetical ordering of the map). Side numbers in Abaqus are 1-based,
1057  // so we subtract 1 here before passing the abaqus side number to the
1058  // mapping array
1059  the_mesh.get_boundary_info().add_side
1060  (&elem,
1061  eledef.abaqus_zero_based_side_id_to_libmesh_side_id[abaqus_side_number-1],
1062  current_id);
1063  }
1064  }
1065  }
1066 
1067 
1068  // Some elsets (if they contain lower-dimensional elements) also
1069  // define sidesets. So loop over them and build a searchable data
1070  // structure we can use to assign sidesets.
1071  {
1072  unsigned char max_dim = this->max_elem_dimension_seen();
1073 
1074  // multimap from lower-dimensional-element-hash-key to
1075  // pair(lower-dimensional-element, boundary_id). The
1076  // lower-dimensional element is used to verify the results of the
1077  // hash table search. The boundary_id will be used to set a
1078  // boundary ID on a higher-dimensional element. We use a multimap
1079  // because the lower-dimensional elements can belong to more than
1080  // 1 sideset, and multiple lower-dimensional elements can hash to
1081  // the same value, but this is very rare.
1082  std::unordered_multimap<dof_id_type, std::pair<Elem *, boundary_id_type>> provide_bcs;
1083 
1084  // The elemset_id counter assigns a logical numbering to the
1085  // _elemset_ids keys. We are going to use these ids as boundary
1086  // ids, so elemset_id is of type boundary_id_type.
1087  container_t::iterator it = _elemset_ids.begin(), end = _elemset_ids.end();
1088  for (boundary_id_type elemset_id=0; it != end; ++it, ++elemset_id)
1089  {
1090  // Grab a reference to the vector of IDs
1091  std::vector<dof_id_type> & id_vector = it->second;
1092 
1093  // Loop over this vector
1094  for (const auto & id : id_vector)
1095  {
1096  // Map the id_vector[i]'th element ID (Abaqus numbering) to LibMesh numbering
1097  dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[id];
1098 
1099  // Get a reference to that element
1100  Elem & elem = the_mesh.elem_ref(libmesh_elem_id);
1101 
1102  // If the element dimension is equal to the maximum
1103  // dimension seen, we can break out of this for loop --
1104  // this elset does not contain sideset information.
1105  if (elem.dim() == max_dim)
1106  break;
1107 
1108  // We can only handle elements that are *exactly*
1109  // one dimension lower than the max element
1110  // dimension. Not sure if "edge" BCs in 3D
1111  // actually make sense/are required...
1112  if (elem.dim()+1 != max_dim)
1113  libmesh_error_msg("ERROR: Expected boundary element of dimension " << max_dim-1 << " but got " << elem.dim());
1114 
1115  // Insert the current (key, pair(elem,id)) into the multimap.
1116  provide_bcs.insert(std::make_pair(elem.key(),
1117  std::make_pair(&elem,
1118  elemset_id)));
1119 
1120  // Associate the name of this sideset with the ID we've
1121  // chosen. It's not necessary to do this for every
1122  // element in the set, but it's convenient to do it here
1123  // since we have all the necessary information...
1124  the_mesh.get_boundary_info().sideset_name(elemset_id) = it->first;
1125  }
1126  }
1127 
1128  // Loop over elements and try to assign boundary information
1129  for (auto & elem : the_mesh.active_element_ptr_range())
1130  if (elem->dim() == max_dim)
1131  for (auto sn : elem->side_index_range())
1132  {
1133  // This is a max-dimension element that may require BCs.
1134  // For each of its sides, including internal sides, we'll
1135  // see if a lower-dimensional element provides boundary
1136  // information for it. Note that we have not yet called
1137  // find_neighbors(), so we can't use elem->neighbor(sn) in
1138  // this algorithm...
1139  auto bounds = provide_bcs.equal_range (elem->key(sn));
1140 
1141  // Add boundary information for each side in the range.
1142  for (const auto & pr : as_range(bounds))
1143  {
1144  // We'll need to compare the lower dimensional element against the current side.
1145  std::unique_ptr<Elem> side (elem->build_side_ptr(sn));
1146 
1147  // Extract the relevant data. We don't need the key for anything.
1148  Elem * lower_dim_elem = pr.second.first;
1149  boundary_id_type bid = pr.second.second;
1150 
1151  // This was a hash, so it might not be perfect. Let's verify...
1152  if (*lower_dim_elem == *side)
1153  the_mesh.get_boundary_info().add_side(elem, sn, bid);
1154  }
1155  }
1156  }
1157 }

References _abaqus_to_libmesh_elem_mapping, _elemset_ids, _sideset_ids, libMesh::MeshBase::active_element_ptr_range(), libMesh::BoundaryInfo::add_side(), libMesh::as_range(), libMesh::Elem::dim(), libMesh::MeshBase::elem_ref(), end, libMesh::Utility::enum_to_string(), libMesh::MeshBase::get_boundary_info(), libMesh::Elem::key(), max_elem_dimension_seen(), libMesh::MeshInput< MT >::mesh(), libMesh::BoundaryInfo::sideset_name(), and libMesh::Elem::type().

Referenced by read().

◆ assign_subdomain_ids()

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 908 of file abaqus_io.C.

909 {
910  // Get a reference to the mesh we are reading
911  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
912 
913  // The number of elemsets we've found while reading
914  std::size_t n_elemsets = _elemset_ids.size();
915 
916  // Fill in a temporary map with (ElemType, index) pairs based on the _elem_types set. This
917  // will allow us to easily look up this index in the loop below.
918  std::map<ElemType, unsigned> elem_types_map;
919  {
920  unsigned ctr=0;
921  for (const auto & type : _elem_types)
922  elem_types_map[type] = ctr++;
923  }
924 
925  // Loop over each Elemset and assign subdomain IDs to Mesh elements
926  {
927  // The maximum element dimension seen while reading the Mesh
928  unsigned char max_dim = this->max_elem_dimension_seen();
929 
930  // The elemset_id counter assigns a logical numbering to the _elemset_ids keys
931  container_t::iterator it = _elemset_ids.begin(), end = _elemset_ids.end();
932  for (unsigned elemset_id=0; it != end; ++it, ++elemset_id)
933  {
934  // Grab a reference to the vector of IDs
935  std::vector<dof_id_type> & id_vector = it->second;
936 
937  // Loop over this vector
938  for (const auto & id : id_vector)
939  {
940  // Map the id'th element ID (Abaqus numbering) to LibMesh numbering
941  dof_id_type libmesh_elem_id = _abaqus_to_libmesh_elem_mapping[id];
942 
943  // Get reference to that element
944  Elem & elem = the_mesh.elem_ref(libmesh_elem_id);
945 
946  // We won't assign subdomain ids to lower-dimensional
947  // elements, as they are assumed to represent boundary
948  // conditions. Since lower-dimensional elements can
949  // appear in multiple sidesets, it doesn't make sense to
950  // assign them a single subdomain id... only the last one
951  // assigned would actually "stick".
952  if (elem.dim() < max_dim)
953  break;
954 
955  // Compute the proper subdomain ID, based on the formula in the
956  // documentation for this function.
957  subdomain_id_type computed_id = cast_int<subdomain_id_type>
958  (elemset_id + (elem_types_map[elem.type()] * n_elemsets));
959 
960  // Assign this ID to the element in question
961  elem.subdomain_id() = computed_id;
962 
963  // We will also assign a unique name to the computed_id,
964  // which is created by appending the geometric element
965  // name to the elset name provided by the user in the
966  // Abaqus file.
967  std::string computed_name = it->first + "_" + Utility::enum_to_string(elem.type());
968  the_mesh.subdomain_name(computed_id) = computed_name;
969  }
970  }
971  }
972 }

References _abaqus_to_libmesh_elem_mapping, _elem_types, _elemset_ids, libMesh::Elem::dim(), libMesh::MeshBase::elem_ref(), end, libMesh::Utility::enum_to_string(), max_elem_dimension_seen(), libMesh::MeshInput< MT >::mesh(), libMesh::Elem::subdomain_id(), libMesh::MeshBase::subdomain_name(), and libMesh::Elem::type().

Referenced by read().

◆ detect_generated_set()

bool libMesh::AbaqusIO::detect_generated_set ( std::string  upper) const
private
Returns
true if the input string is a generated elset or nset, false otherwise.

The input string is assumed to already be in all upper case. Generated nsets are assumed to have the following format: *Nset, nset=Set-1, generate

Definition at line 769 of file abaqus_io.C.

770 {
771  // Avoid issues with weird line endings, spaces before commas, etc.
772  strip_ws(upper);
773 
774  // Check each comma-separated value in "upper" to see if it is the generate flag.
775  std::string cell;
776  std::stringstream line_stream(upper);
777  while (std::getline(line_stream, cell, ','))
778  if (cell == "GENERATE")
779  return true;
780 
781  return false;
782 }

Referenced by read().

◆ generate_ids()

void libMesh::AbaqusIO::generate_ids ( std::string  set_name,
container_t container 
)
private

This function handles "generated" nset and elset sections.

These are denoted by having the comma-separated "GENERATE" keyword in their definition, e.g. *Nset, nset=Set-1, generate

Definition at line 819 of file abaqus_io.C.

820 {
821  // Grab a reference to a vector that will hold all the IDs
822  std::vector<dof_id_type> & id_storage = container[set_name];
823 
824  // Read until the start of another section is detected, or EOF is
825  // encountered. "generate" sections seem to only have one line,
826  // although I suppose it's possible they could have more.
827  while (_in.peek() != '*' && _in.peek() != EOF)
828  {
829  // Read entire comma-separated line into a string
830  std::string csv_line;
831  std::getline(_in, csv_line);
832 
833  // Remove all whitespaces from csv_line.
834  strip_ws(csv_line);
835 
836  // Create a new stringstream object from the string, and stream
837  // in the comma-separated values.
838  char c;
839  dof_id_type start, end, stride;
840  std::stringstream line_stream(csv_line);
841  line_stream >> start >> c >> end >> c >> stride;
842 
843  // Generate entries in the id_storage. Note: each element can
844  // only belong to a single Elset (since this corresponds to the
845  // subdomain_id) so if an element appears in multiple Elsets,
846  // the "last" one (alphabetically, based on set name) in the
847  // _elemset_ids map will "win".
848  for (dof_id_type current = start; current <= end; current += stride)
849  id_storage.push_back(current);
850  }
851 }

References _in, and end.

Referenced by read().

◆ max_elem_dimension_seen()

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 1204 of file abaqus_io.C.

1205 {
1206  unsigned char max_dim = 0;
1207 
1208  unsigned char elem_dimensions_size = cast_int<unsigned char>
1209  (elems_of_dimension.size());
1210  // The elems_of_dimension array is 1-based in the UNV reader
1211  for (unsigned char i=1; i<elem_dimensions_size; ++i)
1212  if (elems_of_dimension[i])
1213  max_dim = i;
1214 
1215  return max_dim;
1216 }

References libMesh::MeshInput< MeshBase >::elems_of_dimension.

Referenced by assign_sideset_ids(), assign_subdomain_ids(), and read().

◆ mesh()

MeshBase & libMesh::MeshInput< MeshBase >::mesh ( )
inlineprotectedinherited
Returns
The object as a writable reference.

Definition at line 169 of file mesh_input.h.

170 {
171  if (_obj == nullptr)
172  libmesh_error_msg("ERROR: _obj should not be nullptr!");
173  return *_obj;
174 }

◆ parse_label()

std::string libMesh::AbaqusIO::parse_label ( std::string  line,
std::string  label_name 
) const
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 724 of file abaqus_io.C.

725 {
726  // Handle files which have weird line endings from e.g. windows.
727  // You can check what kind of line endings you have with 'cat -vet'.
728  // For example, some files may have two kinds of line endings like:
729  //
730  // 4997,^I496,^I532,^I487,^I948^M$
731  //
732  // and we don't want to deal with this when extracting a label, so
733  // just remove all the space characters, which should include all
734  // kinds of remaining newlines. (I don't think Abaqus allows
735  // whitespace in label names.)
736  strip_ws(line);
737 
738  // Do all string comparisons in upper-case
739  std::string
740  upper_line(line),
741  upper_label_name(label_name);
742  std::transform(upper_line.begin(), upper_line.end(), upper_line.begin(), ::toupper);
743  std::transform(upper_label_name.begin(), upper_label_name.end(), upper_label_name.begin(), ::toupper);
744 
745  // Get index of start of "label="
746  size_t label_index = upper_line.find(upper_label_name + "=");
747 
748  if (label_index != std::string::npos)
749  {
750  // Location of the first comma following "label="
751  size_t comma_index = upper_line.find(",", label_index);
752 
753  // Construct iterators from which to build the sub-string.
754  // Note: The +1 while initializing beg is to skip past the "=" which follows the label name
755  std::string::iterator
756  beg = line.begin() + label_name.size() + 1 + label_index,
757  end = (comma_index == std::string::npos) ? line.end() : line.begin() + comma_index;
758 
759  return std::string(beg, end);
760  }
761 
762  // The label index was not found, return the empty string
763  return std::string("");
764 }

References end.

Referenced by read().

◆ process_and_discard_comments()

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 1161 of file abaqus_io.C.

1162 {
1163  std::string dummy;
1164  while (true)
1165  {
1166  // We assume we are at the beginning of a line that may be
1167  // comments or may be data. We need to only discard the line if
1168  // it begins with **, but we must avoid calling std::getline()
1169  // since there's no way to put that back.
1170  if (_in.peek() == '*')
1171  {
1172  // The first character was a star, so actually read it from the stream.
1173  _in.get();
1174 
1175  // Peek at the next character...
1176  if (_in.peek() == '*')
1177  {
1178  // OK, second character was star also, by definition this
1179  // line must be a comment! Read the rest of the line and discard!
1180  std::getline(_in, dummy);
1181  }
1182  else
1183  {
1184  // The second character was _not_ a star, so put back the first star
1185  // we pulled out so that the line can be parsed correctly by somebody
1186  // else!
1187  _in.unget();
1188 
1189  // Finally, break out of the while loop, we are done parsing comments
1190  break;
1191  }
1192  }
1193  else
1194  {
1195  // First character was not *, so this line must be data! Break out of the
1196  // while loop!
1197  break;
1198  }
1199  }
1200 }

References _in.

Referenced by read().

◆ read()

void libMesh::AbaqusIO::read ( const std::string &  name)
overridevirtual

This method implements reading a mesh from a specified file.

Implements libMesh::MeshInput< MeshBase >.

Definition at line 229 of file abaqus_io.C.

230 {
231  // Get a reference to the mesh we are reading
232  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
233 
234  // Clear any existing mesh data
235  the_mesh.clear();
236 
237  // Open stream for reading
238  _in.open(fname.c_str());
239  libmesh_assert(_in.good());
240 
241  // Initialize the elems_of_dimension array. We will use this in a
242  // "1-based" manner so that elems_of_dimension[d]==true means
243  // elements of dimension d have been seen.
244  elems_of_dimension.resize(4, false);
245 
246  // Read file line-by-line... this is based on a set of different
247  // test input files. I have not looked at the full input file
248  // specs for Abaqus.
249  std::string s;
250  while (true)
251  {
252  // Try to read something. This may set EOF!
253  std::getline(_in, s);
254 
255  if (_in)
256  {
257  // Process s...
258  //
259  // There are many sections in Abaqus files, we read some
260  // but others are just ignored... Some sections may occur
261  // more than once. For example for a hybrid grid, you
262  // will have multiple *Element sections...
263 
264  // Some Abaqus files use all upper-case for section names,
265  // so we will just convert s to uppercase
266  std::string upper(s);
267  std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
268 
269  // 0.) Look for the "*Part" section
270  if (upper.find("*PART") == static_cast<std::string::size_type>(0))
271  {
272  if (_already_seen_part)
273  libmesh_error_msg("We currently don't support reading Abaqus files with multiple PART sections");
274 
275  _already_seen_part = true;
276  }
277 
278  // 1.) Look for the "*Nodes" section
279  if (upper.find("*NODE") == static_cast<std::string::size_type>(0))
280  {
281  // Some sections that begin with *NODE are actually
282  // "*NODE OUTPUT" sections which we want to skip. I
283  // have only seen this with a single space, but it would
284  // probably be more robust to remove whitespace before
285  // making this check.
286  if (upper.find("*NODE OUTPUT") == static_cast<std::string::size_type>(0))
287  continue;
288 
289  // Some *Node sections also specify an Nset name on the same line.
290  // Look for one here.
291  std::string nset_name = this->parse_label(s, "nset");
292 
293  // Process any lines of comments that may be present
295 
296  // Read a block of nodes
297  this->read_nodes(nset_name);
298  }
299 
300 
301 
302  // 2.) Look for the "*Element" section
303  else if (upper.find("*ELEMENT,") == static_cast<std::string::size_type>(0))
304  {
305  // Some sections that begin with *ELEMENT are actually
306  // "*ELEMENT OUTPUT" sections which we want to skip. I
307  // have only seen this with a single space, but it would
308  // probably be more robust to remove whitespace before
309  // making this check.
310  if (upper.find("*ELEMENT OUTPUT") == static_cast<std::string::size_type>(0))
311  continue;
312 
313  // Some *Element sections also specify an Elset name on the same line.
314  // Look for one here.
315  std::string elset_name = this->parse_label(s, "elset");
316 
317  // Process any lines of comments that may be present
319 
320  // Read a block of elements
321  this->read_elements(upper, elset_name);
322  }
323 
324 
325 
326  // 3.) Look for a Nodeset section
327  else if (upper.find("*NSET") == static_cast<std::string::size_type>(0))
328  {
329  std::string nset_name = this->parse_label(s, "nset");
330 
331  // I haven't seen an unnamed nset yet, but let's detect it
332  // just in case...
333  if (nset_name == "")
334  libmesh_error_msg("Unnamed nset encountered!");
335 
336  // Is this a "generated" nset, i.e. one which has three
337  // entries corresponding to (first, last, stride)?
338  bool is_generated = this->detect_generated_set(upper);
339 
340  // Process any lines of comments that may be present
342 
343  // Read the IDs, storing them in _nodeset_ids
344  if (is_generated)
345  this->generate_ids(nset_name, _nodeset_ids);
346  else
347  this->read_ids(nset_name, _nodeset_ids);
348  } // *Nodeset
349 
350 
351 
352  // 4.) Look for an Elset section
353  else if (upper.find("*ELSET") == static_cast<std::string::size_type>(0))
354  {
355  std::string elset_name = this->parse_label(s, "elset");
356 
357  // I haven't seen an unnamed elset yet, but let's detect it
358  // just in case...
359  if (elset_name == "")
360  libmesh_error_msg("Unnamed elset encountered!");
361 
362  // Is this a "generated" elset, i.e. one which has three
363  // entries corresponding to (first, last, stride)?
364  bool is_generated = this->detect_generated_set(upper);
365 
366  // Process any lines of comments that may be present
368 
369  // Read the IDs, storing them in _elemset_ids
370  if (is_generated)
371  this->generate_ids(elset_name, _elemset_ids);
372  else
373  this->read_ids(elset_name, _elemset_ids);
374  } // *Elset
375 
376 
377 
378  // 5.) Look for a Surface section. Need to be a little
379  // careful, since there are also "surface interaction"
380  // sections we don't want to read here.
381  else if (upper.find("*SURFACE,") == static_cast<std::string::size_type>(0))
382  {
383  // Get the name from the Name=Foo label. This will be the map key.
384  std::string sideset_name = this->parse_label(s, "name");
385 
386  // Process any lines of comments that may be present
388 
389  // Read the sideset IDs
390  this->read_sideset(sideset_name, _sideset_ids);
391  }
392 
393  continue;
394  } // if (_in)
395 
396  // If !file, check to see if EOF was set. If so, break out
397  // of while loop.
398  if (_in.eof())
399  break;
400 
401  // If !in and !in.eof(), stream is in a bad state!
402  libmesh_error_msg("Stream is bad! Perhaps the file: " << fname << " does not exist?");
403  } // while
404 
405  // Set the Mesh dimension based on the highest dimension element seen.
407 
408  // Set element IDs based on the element sets.
409  this->assign_subdomain_ids();
410 
411  // Assign nodeset values to the BoundaryInfo object
412  this->assign_boundary_node_ids();
413 
414  // Assign sideset values in the BoundaryInfo object
415  this->assign_sideset_ids();
416 
417  // If the Abaqus file contains only nodesets, we can have libmesh
418  // generate sidesets from them. This BoundaryInfo function currently
419  // *overwrites* existing sidesets in surprising ways, so we don't
420  // call it if there are already sidesets present in the original file.
423 
424  // Delete lower-dimensional elements from the Mesh. We assume these
425  // were only used for setting BCs, and aren't part of the actual
426  // Mesh.
427  {
428  unsigned char max_dim = this->max_elem_dimension_seen();
429 
430  for (auto & elem : the_mesh.element_ptr_range())
431  if (elem->dim() < max_dim)
432  the_mesh.delete_elem(elem);
433  }
434 }

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(), detect_generated_set(), libMesh::MeshBase::element_ptr_range(), libMesh::MeshInput< MeshBase >::elems_of_dimension, generate_ids(), libMesh::MeshBase::get_boundary_info(), libMesh::libmesh_assert(), max_elem_dimension_seen(), libMesh::MeshInput< MT >::mesh(), libMesh::BoundaryInfo::n_boundary_conds(), 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().

◆ read_elements()

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 521 of file abaqus_io.C.

522 {
523  // Get a reference to the mesh we are reading
524  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
525 
526  // initialize the eletypes map (eletypes is a file-global variable)
527  init_eletypes();
528 
529  ElemType elem_type = INVALID_ELEM;
530  unsigned n_nodes_per_elem = 0;
531 
532  // Within s, we should have "type=XXXX"
533  if (upper.find("T3D2") != std::string::npos ||
534  upper.find("B31") != std::string::npos)
535  {
536  elem_type = EDGE2;
537  n_nodes_per_elem = 2;
538  elems_of_dimension[1] = true;
539  }
540  else if (upper.find("B32") != std::string::npos)
541  {
542  elem_type = EDGE3;
543  n_nodes_per_elem = 3;
544  elems_of_dimension[1] = true;
545  }
546  else if (upper.find("S3") != std::string::npos ||
547  upper.find("CPE3") != std::string::npos ||
548  upper.find("2D3") != std::string::npos)
549  {
550  elem_type = TRI3;
551  n_nodes_per_elem = 3;
552  elems_of_dimension[2] = true;
553  }
554  else if (upper.find("CPE4") != std::string::npos ||
555  upper.find("S4") != std::string::npos ||
556  upper.find("CPEG4") != std::string::npos ||
557  upper.find("2D4") != std::string::npos)
558  {
559  elem_type = QUAD4;
560  n_nodes_per_elem = 4;
561  elems_of_dimension[2] = true;
562  }
563  else if (upper.find("CPE6") != std::string::npos ||
564  upper.find("S6") != std::string::npos ||
565  upper.find("CPEG6") != std::string::npos ||
566  upper.find("2D6") != std::string::npos)
567  {
568  elem_type = TRI6;
569  n_nodes_per_elem = 6;
570  elems_of_dimension[2] = true;
571  }
572  else if (upper.find("CPE8") != std::string::npos ||
573  upper.find("S8") != std::string::npos ||
574  upper.find("CPEG8") != std::string::npos ||
575  upper.find("2D8") != std::string::npos)
576  {
577  elem_type = QUAD8;
578  n_nodes_per_elem = 8;
579  elems_of_dimension[2] = true;
580  }
581  else if (upper.find("3D8") != std::string::npos)
582  {
583  elem_type = HEX8;
584  n_nodes_per_elem = 8;
585  elems_of_dimension[3] = true;
586  }
587  else if (upper.find("3D4") != std::string::npos)
588  {
589  elem_type = TET4;
590  n_nodes_per_elem = 4;
591  elems_of_dimension[3] = true;
592  }
593  else if (upper.find("3D20") != std::string::npos)
594  {
595  elem_type = HEX20;
596  n_nodes_per_elem = 20;
597  elems_of_dimension[3] = true;
598  }
599  else if (upper.find("3D27") != std::string::npos)
600  {
601  elem_type = HEX27;
602  n_nodes_per_elem = 27;
603  elems_of_dimension[3] = true;
604  }
605  else if (upper.find("3D6") != std::string::npos)
606  {
607  elem_type = PRISM6;
608  n_nodes_per_elem = 6;
609  elems_of_dimension[3] = true;
610  }
611  else if (upper.find("3D15") != std::string::npos)
612  {
613  elem_type = PRISM15;
614  n_nodes_per_elem = 15;
615  elems_of_dimension[3] = true;
616  }
617  else if (upper.find("3D10") != std::string::npos)
618  {
619  elem_type = TET10;
620  n_nodes_per_elem = 10;
621  elems_of_dimension[3] = true;
622  }
623  else
624  libmesh_error_msg("Unrecognized element type: " << upper);
625 
626  // Insert the elem type we detected into the set of all elem types for this mesh
627  _elem_types.insert(elem_type);
628 
629  // Grab a reference to the element definition for this element type
630  const ElementDefinition & eledef = eletypes[elem_type];
631 
632  // If the element definition was not found, the call above would have
633  // created one with an uninitialized struct. Check for that here...
634  if (eledef.abaqus_zero_based_node_id_to_libmesh_node_id.size() == 0)
635  libmesh_error_msg("No Abaqus->LibMesh mapping information for ElemType " \
636  << Utility::enum_to_string(elem_type) \
637  << "!");
638 
639  // We will read elements until the next line begins with *, since that will be the
640  // next section.
641  while (_in.peek() != '*' && _in.peek() != EOF)
642  {
643  // Read the element ID, it is the first number on each line. It is
644  // followed by a comma, so read that also. We will need this ID later
645  // when we try to assign subdomain IDs
646  dof_id_type abaqus_elem_id = 0;
647  char c;
648  _in >> abaqus_elem_id >> c;
649 
650  // Add an element of the appropriate type to the Mesh.
651  Elem * elem = the_mesh.add_elem(Elem::build(elem_type).release());
652 
653  // Associate the ID returned from libmesh with the abaqus element ID
654  //_libmesh_to_abaqus_elem_mapping[elem->id()] = abaqus_elem_id;
655  _abaqus_to_libmesh_elem_mapping[abaqus_elem_id] = elem->id();
656 
657  // The count of the total number of IDs read for the current element.
658  unsigned id_count=0;
659 
660  // Continue reading line-by-line until we have read enough nodes for this element
661  while (id_count < n_nodes_per_elem)
662  {
663  // Read entire line (up to carriage return) of comma-separated values
664  std::string csv_line;
665  std::getline(_in, csv_line);
666 
667  // Create a stream object out of the current line
668  std::stringstream line_stream(csv_line);
669 
670  // Process the comma-separated values
671  std::string cell;
672  while (std::getline(line_stream, cell, ','))
673  {
674  dof_id_type abaqus_global_node_id;
675  bool success = string_to_num(cell, abaqus_global_node_id);
676 
677  if (success)
678  {
679  // Use the global node number mapping to determine the corresponding libmesh global node id
680  dof_id_type libmesh_global_node_id = _abaqus_to_libmesh_node_mapping[abaqus_global_node_id];
681 
682  // Grab the node pointer from the mesh for this ID
683  Node * node = the_mesh.node_ptr(libmesh_global_node_id);
684 
685  // If node_ptr() returns nullptr, it may mean we have not yet read the
686  // *Nodes section, though I assumed that always came before the *Elements section...
687  if (node == nullptr)
688  libmesh_error_msg("Error! Mesh::node_ptr() returned nullptr. Either no node exists with ID " \
689  << libmesh_global_node_id \
690  << " or perhaps this input file has *Elements defined before *Nodes?");
691 
692  // Note: id_count is the zero-based abaqus (elem local) node index. We therefore map
693  // it to a libmesh elem local node index using the element definition map
694  unsigned libmesh_elem_local_node_id =
695  eledef.abaqus_zero_based_node_id_to_libmesh_node_id[id_count];
696 
697  // Set this node pointer within the element.
698  elem->set_node(libmesh_elem_local_node_id) = node;
699 
700  // Increment the count of IDs read for this element
701  id_count++;
702  } // end if (success)
703  } // end while getline(',')
704  } // end while (id_count)
705 
706  // Ensure that we read *exactly* as many nodes as we were expecting to, no more.
707  if (id_count != n_nodes_per_elem)
708  libmesh_error_msg("Error: Needed to read " \
709  << n_nodes_per_elem \
710  << " nodes, but read " \
711  << id_count \
712  << " instead!");
713 
714  // If we are recording Elset IDs, add this element to the correct set for later processing.
715  // Make sure to add it with the Abaqus ID, not the libmesh one!
716  if (elset_name != "")
717  _elemset_ids[elset_name].push_back(abaqus_elem_id);
718  } // end while (peek)
719 }

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::EDGE3, libMesh::MeshInput< MeshBase >::elems_of_dimension, libMesh::Utility::enum_to_string(), libMesh::HEX20, libMesh::HEX27, libMesh::HEX8, libMesh::DofObject::id(), libMesh::INVALID_ELEM, libMesh::MeshInput< MT >::mesh(), libMesh::MeshBase::node_ptr(), libMesh::PRISM15, libMesh::PRISM6, libMesh::QUAD4, libMesh::QUAD8, libMesh::Elem::set_node(), libMesh::TET10, libMesh::TET4, libMesh::TRI3, and libMesh::TRI6.

Referenced by read().

◆ read_ids()

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 786 of file abaqus_io.C.

787 {
788  // Grab a reference to a vector that will hold all the IDs
789  std::vector<dof_id_type> & id_storage = container[set_name];
790 
791  // Read until the start of another section is detected, or EOF is encountered
792  while (_in.peek() != '*' && _in.peek() != EOF)
793  {
794  // Read entire comma-separated line into a string
795  std::string csv_line;
796  std::getline(_in, csv_line);
797 
798  // On that line, use std::getline again to parse each
799  // comma-separated entry.
800  std::string cell;
801  std::stringstream line_stream(csv_line);
802  while (std::getline(line_stream, cell, ','))
803  {
804  dof_id_type id;
805  bool success = string_to_num(cell, id);
806 
807  // Note that lists of comma-separated values in abaqus also
808  // *end* with a comma, so the last call to getline on a given
809  // line will get an empty string, which we must detect.
810  if (success)
811  id_storage.push_back(id);
812  }
813  }
814 }

References _in.

Referenced by read().

◆ read_nodes()

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 442 of file abaqus_io.C.

443 {
444  // Get a reference to the mesh we are reading
445  MeshBase & the_mesh = MeshInput<MeshBase>::mesh();
446 
447  // In the input files I have, Abaqus neither tells what
448  // the mesh dimension is nor how many nodes it has...
449  //
450  // The node line format is:
451  // id, x, y, z
452  // and you do have to parse out the commas.
453  // The z-coordinate will only be present for 3D meshes
454 
455  // Temporary variables for parsing lines of text
456  char c;
457  std::string line;
458 
459  // Defines the sequential node numbering used by libmesh. Since
460  // there can be multiple *NODE sections in an Abaqus file, we always
461  // start our numbering with the number of nodes currently in the
462  // Mesh.
463  dof_id_type libmesh_node_id = the_mesh.n_nodes();
464 
465  // We need to duplicate some of the read_ids code if this *NODE
466  // section also defines an NSET. We'll set up the id_storage
467  // pointer and push back IDs into this vector in the loop below...
468  std::vector<dof_id_type> * id_storage = nullptr;
469  if (nset_name != "")
470  id_storage = &(_nodeset_ids[nset_name]);
471 
472  // We will read nodes until the next line begins with *, since that will be the
473  // next section.
474  // TODO: Is Abaqus guaranteed to start the line with '*' or can there be leading white space?
475  while (_in.peek() != '*' && _in.peek() != EOF)
476  {
477  // Read an entire line which corresponds to a single point's id
478  // and (x,y,z) values.
479  std::getline(_in, line);
480 
481  // Remove all whitespace characters from the line. This way we
482  // can do the remaining parsing without worrying about tabs,
483  // different numbers of spaces, etc.
484  strip_ws(line);
485 
486  // Make a stream out of the modified line so we can stream values
487  // from it in the usual way.
488  std::stringstream ss(line);
489 
490  // Values to be read in from file
491  dof_id_type abaqus_node_id=0;
492  Real x=0, y=0, z=0;
493 
494  // Note: we assume *at least* 2D points here, should we worry about
495  // trying to read 1D Abaqus meshes?
496  ss >> abaqus_node_id >> c >> x >> c >> y;
497 
498  // Peek at the next character. If it is a comma, then there is another
499  // value to read!
500  if (ss.peek() == ',')
501  ss >> c >> z;
502 
503  // If this *NODE section defines an NSET, also store the abaqus ID in id_storage
504  if (id_storage)
505  id_storage->push_back(abaqus_node_id);
506 
507  // Set up the abaqus -> libmesh node mapping. This is usually just the
508  // "off-by-one" map, but it doesn't have to be.
509  _abaqus_to_libmesh_node_mapping[abaqus_node_id] = libmesh_node_id;
510 
511  // Add the point to the mesh using libmesh's numbering,
512  // and post-increment the libmesh node counter.
513  the_mesh.add_point(Point(x,y,z), libmesh_node_id++);
514  } // while
515 }

References _abaqus_to_libmesh_node_mapping, _in, _nodeset_ids, libMesh::MeshBase::add_point(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshBase::n_nodes(), and libMesh::Real.

Referenced by read().

◆ read_sideset()

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 856 of file abaqus_io.C.

857 {
858  // Grab a reference to a vector that will hold all the IDs
859  std::vector<std::pair<dof_id_type, unsigned>> & id_storage = container[sideset_name];
860 
861  // Variables for storing values read in from file
862  unsigned side_id=0;
863  char c;
864  std::string elem_id_or_set, dummy;
865 
866  // Read until the start of another section is detected, or EOF is encountered
867  while (_in.peek() != '*' && _in.peek() != EOF)
868  {
869  // This line is of the form: "391, S2" or "Elset_1, S3"
870 
871  // Read first string up to and including the comma, which is discarded.
872  std::getline(_in, elem_id_or_set, ',');
873 
874  // Strip any leading or trailing trailing whitespace from this
875  // string, since some Abaqus files may have this.
876  strip_ws(elem_id_or_set);
877 
878  // Read the character "S", followed by the side id. Note: the >> operator
879  // eats whitespace until it reaches a valid character, so this should work
880  // whether or not there is a space after the previous comma.
881  _in >> c >> side_id;
882 
883  // Try to convert first string to an integer.
884  dof_id_type elem_id;
885  bool success = string_to_num(elem_id_or_set, elem_id);
886 
887  if (success)
888  {
889  // if the side set is of the form of "391, S2"
890  id_storage.push_back( std::make_pair(elem_id, side_id) );
891  }
892  else
893  {
894  // if the side set is of the form of "Elset_1, S3"
895  const auto & vec = libmesh_map_find(_elemset_ids, elem_id_or_set);
896  for (const auto & elem_id_in_elset : vec)
897  id_storage.push_back( std::make_pair(elem_id_in_elset, side_id) );
898  }
899 
900  // Extract remaining characters on line including newline
901  std::getline(_in, dummy);
902  } // while
903 }

References _elemset_ids, and _in.

Referenced by read().

◆ set_n_partitions()

void libMesh::MeshInput< MeshBase >::set_n_partitions ( unsigned int  n_parts)
inlineprotectedinherited

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 91 of file mesh_input.h.

91 { this->mesh().set_n_partitions() = n_parts; }

◆ skip_comment_lines()

void libMesh::MeshInput< MeshBase >::skip_comment_lines ( std::istream &  in,
const char  comment_start 
)
protectedinherited

Reads input from in, skipping all the lines that start with the character comment_start.

Definition at line 179 of file mesh_input.h.

181 {
182  char c, line[256];
183 
184  while (in.get(c), c==comment_start)
185  in.getline (line, 255);
186 
187  // put back first character of
188  // first non-comment line
189  in.putback (c);
190 }

Member Data Documentation

◆ _abaqus_to_libmesh_elem_mapping

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 217 of file abaqus_io.h.

Referenced by assign_sideset_ids(), assign_subdomain_ids(), and read_elements().

◆ _abaqus_to_libmesh_node_mapping

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
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 227 of file abaqus_io.h.

Referenced by assign_boundary_node_ids(), read_elements(), and read_nodes().

◆ _already_seen_part

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 235 of file abaqus_io.h.

Referenced by read().

◆ _elem_types

std::set<ElemType> libMesh::AbaqusIO::_elem_types
private

A set of the different geometric element types detected when reading the mesh.

Definition at line 210 of file abaqus_io.h.

Referenced by assign_subdomain_ids(), and read_elements().

◆ _elemset_ids

container_t libMesh::AbaqusIO::_elemset_ids
private

◆ _in

std::ifstream libMesh::AbaqusIO::_in
private

Stream object used to interact with the file.

Definition at line 204 of file abaqus_io.h.

Referenced by generate_ids(), process_and_discard_comments(), read(), read_elements(), read_ids(), read_nodes(), and read_sideset().

◆ _is_parallel_format

const bool libMesh::MeshInput< MeshBase >::_is_parallel_format
privateinherited

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 121 of file mesh_input.h.

◆ _nodeset_ids

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 197 of file abaqus_io.h.

Referenced by assign_boundary_node_ids(), read(), and read_nodes().

◆ _obj

MeshBase * libMesh::MeshInput< MeshBase >::_obj
privateinherited

A pointer to a non-const object object.

This allows us to read the object from file.

Definition at line 114 of file mesh_input.h.

◆ _sideset_ids

sideset_container_t libMesh::AbaqusIO::_sideset_ids
private

Definition at line 199 of file abaqus_io.h.

Referenced by assign_sideset_ids(), and read().

◆ build_sidesets_from_nodesets

bool libMesh::AbaqusIO::build_sidesets_from_nodesets

Default false.

Set this flag to true if you want libmesh to automatically generate sidesets from Abaqus' nodesets. If the Abaqus file already contains some sidesets, we ignore this flag and don't generate sidesets, because the algorithm to do so currently does not take into account existing sidesets.

Definition at line 66 of file abaqus_io.h.

Referenced by read().

◆ elems_of_dimension

std::vector<bool> libMesh::MeshInput< MeshBase >::elems_of_dimension
protectedinherited

A vector of bools describing what dimension elements have been encountered when reading a mesh.

Definition at line 97 of file mesh_input.h.


The documentation for this class was generated from the following files:
libMesh::HEX20
Definition: enum_elem_type.h:48
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::PRISM6
Definition: enum_elem_type.h:50
libMesh::MeshBase::set_n_partitions
unsigned int & set_n_partitions()
Definition: mesh_base.h:1667
libMesh::AbaqusIO::_elem_types
std::set< ElemType > _elem_types
A set of the different geometric element types detected when reading the mesh.
Definition: abaqus_io.h:210
libMesh::Elem::build_side_ptr
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
libMesh::AbaqusIO::_sideset_ids
sideset_container_t _sideset_ids
Definition: abaqus_io.h:199
libMesh::MeshBase::get_boundary_info
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:132
libMesh::AbaqusIO::_in
std::ifstream _in
Stream object used to interact with the file.
Definition: abaqus_io.h:204
libMesh::AbaqusIO::parse_label
std::string parse_label(std::string line, std::string label_name) const
This function parses a label of the form foo=bar from a comma-delimited line of the form ....
Definition: abaqus_io.C:724
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::BoundaryInfo::add_node
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
Definition: boundary_info.C:636
libMesh::AbaqusIO::max_elem_dimension_seen
unsigned char max_elem_dimension_seen()
Definition: abaqus_io.C:1204
libMesh::BoundaryInfo::n_boundary_conds
std::size_t n_boundary_conds() const
Definition: boundary_info.C:1615
libMesh::MeshBase::delete_elem
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
libMesh::MeshBase::active_element_ptr_range
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
libMesh::MeshBase::elem_ref
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:521
libMesh::Elem::dim
virtual unsigned short dim() const =0
libMesh::TET10
Definition: enum_elem_type.h:46
libMesh::AbaqusIO::_abaqus_to_libmesh_node_mapping
std::map< dof_id_type, dof_id_type > _abaqus_to_libmesh_node_mapping
Map from abaqus node number -> sequential, 0-based libmesh node numbering.
Definition: abaqus_io.h:227
end
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end.
Definition: variant_filter_iterator.h:343
libMesh::BoundaryInfo::sideset_name
std::string & sideset_name(boundary_id_type id)
Definition: boundary_info.C:2341
libMesh::MeshBase::node_ptr
virtual const Node * node_ptr(const dof_id_type i) const =0
libMesh::boundary_id_type
int8_t boundary_id_type
Definition: id_types.h:51
libMesh::MeshInput< MeshBase >::_obj
MeshBase * _obj
A pointer to a non-const object object.
Definition: mesh_input.h:114
libMesh::TET4
Definition: enum_elem_type.h:45
libMesh::PRISM15
Definition: enum_elem_type.h:51
libMesh::BoundaryInfo::nodeset_name
std::string & nodeset_name(boundary_id_type id)
Definition: boundary_info.C:2357
libMesh::MeshBase::element_ptr_range
virtual SimpleRange< element_iterator > element_ptr_range()=0
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::AbaqusIO::_already_seen_part
bool _already_seen_part
This flag gets set to true after the first "*PART" section we see.
Definition: abaqus_io.h:235
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::AbaqusIO::assign_sideset_ids
void assign_sideset_ids()
Called at the end of the read() function, assigns any sideset IDs found when reading the file to the ...
Definition: abaqus_io.C:1013
libMesh::HEX27
Definition: enum_elem_type.h:49
libMesh::AbaqusIO::generate_ids
void generate_ids(std::string set_name, container_t &container)
This function handles "generated" nset and elset sections.
Definition: abaqus_io.C:819
libMesh::AbaqusIO::read_sideset
void read_sideset(std::string sideset_name, sideset_container_t &container)
This function reads a sideset from the input file.
Definition: abaqus_io.C:856
libMesh::BoundaryInfo::build_side_list_from_node_list
void build_side_list_from_node_list()
Adds sides to a sideset if every node on that side are in the same sideset.
Definition: boundary_info.C:1928
libMesh::QUAD4
Definition: enum_elem_type.h:41
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::AbaqusIO::detect_generated_set
bool detect_generated_set(std::string upper) const
Definition: abaqus_io.C:769
libMesh::TRI3
Definition: enum_elem_type.h:39
libMesh::AbaqusIO::_abaqus_to_libmesh_elem_mapping
std::map< dof_id_type, dof_id_type > _abaqus_to_libmesh_elem_mapping
Map from libmesh element number -> abaqus element number, and the converse.
Definition: abaqus_io.h:217
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::as_range
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libMesh::AbaqusIO::process_and_discard_comments
void process_and_discard_comments()
Any of the various sections can start with some number of lines of comments, which start with "**".
Definition: abaqus_io.C:1161
libMesh::Utility::enum_to_string
std::string enum_to_string(const T e)
libMesh::Elem::set_node
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2059
libMesh::MeshBase::n_nodes
virtual dof_id_type n_nodes() const =0
libMesh::TRI6
Definition: enum_elem_type.h:40
libMesh::AbaqusIO::read_nodes
void read_nodes(std::string nset_name)
This function parses a block of nodes in the Abaqus file once such a block has been found.
Definition: abaqus_io.C:442
libMesh::INVALID_ELEM
Definition: enum_elem_type.h:75
libMesh::MeshBase::add_elem
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
libMesh::Elem::subdomain_id
subdomain_id_type subdomain_id() const
Definition: elem.h:2069
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::EDGE3
Definition: enum_elem_type.h:36
libMesh::Elem::side_index_range
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2188
libMesh::MeshBase::subdomain_name
std::string & subdomain_name(subdomain_id_type id)
Definition: mesh_base.C:717
libMesh::AbaqusIO::_nodeset_ids
container_t _nodeset_ids
Abaqus writes nodesets and elemsets with labels.
Definition: abaqus_io.h:197
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
libMesh::AbaqusIO::_elemset_ids
container_t _elemset_ids
Definition: abaqus_io.h:198
libMesh::MeshInput::mesh
MT & mesh()
Definition: mesh_input.h:169
libMesh::MeshBase::add_point
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
libMesh::AbaqusIO::assign_boundary_node_ids
void assign_boundary_node_ids()
This function assigns boundary IDs to node sets based on the alphabetical order in which the sets are...
Definition: abaqus_io.C:977
libMesh::TestClass
Definition: id_types.h:33
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::Elem::key
virtual dof_id_type key(const unsigned int s) const =0
libMesh::AbaqusIO::read_elements
void read_elements(std::string upper, std::string elset_name)
This function parses a block of elements in the Abaqus file.
Definition: abaqus_io.C:521
libMesh::MeshBase::clear
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition: mesh_base.C:429
libMesh::MeshBase::set_mesh_dimension
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
Definition: mesh_base.h:218
libMesh::Elem::build
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:246
libMesh::AbaqusIO::assign_subdomain_ids
void assign_subdomain_ids()
This function is called after all the elements have been read and assigns element subdomain IDs.
Definition: abaqus_io.C:908
libMesh::BoundaryInfo::add_side
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure.
Definition: boundary_info.C:886
libMesh::AbaqusIO::read_ids
void read_ids(std::string set_name, container_t &container)
This function reads all the IDs for the current node or element set of the given name,...
Definition: abaqus_io.C:786
libMesh::Elem::type
virtual ElemType type() const =0
libMesh::MeshInput< MeshBase >
libMesh::EDGE2
Definition: enum_elem_type.h:35
libMesh::MeshInput< MeshBase >::elems_of_dimension
std::vector< bool > elems_of_dimension
A vector of bools describing what dimension elements have been encountered when reading a mesh.
Definition: mesh_input.h:97
libMesh::QUAD8
Definition: enum_elem_type.h:42
libMesh::ElemType
ElemType
Defines an enum for geometric element types.
Definition: enum_elem_type.h:33
libMesh::AbaqusIO::build_sidesets_from_nodesets
bool build_sidesets_from_nodesets
Default false.
Definition: abaqus_io.h:66