25 #include "libmesh/abaqus_io.h"
26 #include "libmesh/point.h"
27 #include "libmesh/elem.h"
28 #include "libmesh/enum_to_string.h"
29 #include "libmesh/boundary_info.h"
30 #include "libmesh/utility.h"
31 #include <unordered_map>
44 bool string_to_num(
const std::string & input,
dof_id_type & output)
47 output = cast_int<dof_id_type>
48 (std::strtol(input.c_str(), &endptr, 10));
50 return (output != 0 || endptr != input.c_str());
57 void strip_ws(std::string & line)
59 line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end());
66 struct ElementDefinition
69 std::vector<unsigned> abaqus_zero_based_node_id_to_libmesh_node_id;
72 std::vector<unsigned short> abaqus_zero_based_side_id_to_libmesh_side_id;
78 std::map<ElemType, ElementDefinition> eletypes;
83 void add_eletype_entry(
ElemType libmesh_elem_type,
84 const unsigned * node_map,
85 unsigned node_map_size,
86 const unsigned short * side_map,
87 unsigned side_map_size)
90 ElementDefinition & map_entry = eletypes[libmesh_elem_type];
97 (node_map, node_map+node_map_size).swap
98 (map_entry.abaqus_zero_based_node_id_to_libmesh_node_id);
100 std::vector<unsigned short>
101 (side_map, side_map+side_map_size).swap
102 (map_entry.abaqus_zero_based_side_id_to_libmesh_side_id);
109 void init_eletypes ()
115 if (eletypes.empty())
119 const unsigned int node_map[] = {0,1};
120 const unsigned short side_map[] = {0,1};
121 add_eletype_entry(
EDGE2, node_map, 2, side_map, 2);
126 const unsigned int node_map[] = {0,1,2};
127 const unsigned short side_map[] = {0,1,2};
128 add_eletype_entry(
TRI3, node_map, 3, side_map, 3);
133 const unsigned int node_map[] = {0,1,2,3};
134 const unsigned short side_map[] = {0,1,2,3};
135 add_eletype_entry(
QUAD4, node_map, 4, side_map, 4);
140 const unsigned int node_map[] = {0,1,2,3};
141 const unsigned short side_map[] = {0,1,2,3};
142 add_eletype_entry(
TET4, node_map, 4, side_map, 4);
147 const unsigned int node_map[] = {0,1,2,3,4,5,6,7,8,9};
148 const unsigned short side_map[] = {0,1,2,3};
149 add_eletype_entry(
TET10, node_map, 10, side_map, 4);
154 const unsigned int node_map[] = {0,1,2,3,4,5,6,7};
155 const unsigned short side_map[] = {0,5,1,2,3,4};
156 add_eletype_entry(
HEX8, node_map, 8, side_map, 6);
161 const unsigned int node_map[] =
162 {0,1,2,3,4,5,6,7,8,9,10,11,16,17,18,19,12,13,14,15};
163 const unsigned short side_map[] =
165 add_eletype_entry(
HEX20, node_map, 20, side_map, 6);
170 const unsigned int node_map[] =
171 {0,1,2,3,4,5,6,7,8,9,10,11,16,17,18,19,12,13,14,15,26,20,25,21,22,23,24};
172 const unsigned short side_map[] =
174 add_eletype_entry(
HEX27, node_map, 27, side_map, 6);
179 const unsigned int node_map[] = {0,1,2,3,4,5};
180 const unsigned short side_map[] = {0,4,1,2,3};
181 add_eletype_entry(
PRISM6, node_map, 6, side_map, 5);
186 const unsigned int node_map[] =
187 {0,1,2,3,4,5,6,7,8,12,13,14,9,10,11};
188 const unsigned short side_map[] =
190 add_eletype_entry(
PRISM15, node_map, 15, side_map, 5);
195 const unsigned int node_map[] =
196 {0,1,2,3,4,5,6,7,8,12,13,14,9,10,11,15,16,17};
197 const unsigned short side_map[] =
199 add_eletype_entry(
PRISM18, node_map, 18, side_map, 5);
214 build_sidesets_from_nodesets(false),
215 _already_seen_part(false)
238 _in.open(fname.c_str());
253 std::getline(
_in, s);
266 std::string upper(s);
267 std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
270 if (upper.find(
"*PART") == static_cast<std::string::size_type>(0))
273 libmesh_error_msg(
"We currently don't support reading Abaqus files with multiple PART sections");
279 if (upper.find(
"*NODE") == static_cast<std::string::size_type>(0))
286 if (upper.find(
"*NODE OUTPUT") == static_cast<std::string::size_type>(0))
291 std::string nset_name = this->
parse_label(s,
"nset");
303 else if (upper.find(
"*ELEMENT,") == static_cast<std::string::size_type>(0))
310 if (upper.find(
"*ELEMENT OUTPUT") == static_cast<std::string::size_type>(0))
315 std::string elset_name = this->
parse_label(s,
"elset");
327 else if (upper.find(
"*NSET") == static_cast<std::string::size_type>(0))
329 std::string nset_name = this->
parse_label(s,
"nset");
334 libmesh_error_msg(
"Unnamed nset encountered!");
353 else if (upper.find(
"*ELSET") == static_cast<std::string::size_type>(0))
355 std::string elset_name = this->
parse_label(s,
"elset");
359 if (elset_name ==
"")
360 libmesh_error_msg(
"Unnamed elset encountered!");
381 else if (upper.find(
"*SURFACE,") == static_cast<std::string::size_type>(0))
384 std::string sideset_name = this->
parse_label(s,
"name");
402 libmesh_error_msg(
"Stream is bad! Perhaps the file: " << fname <<
" does not exist?");
431 if (elem->dim() < max_dim)
468 std::vector<dof_id_type> * id_storage =
nullptr;
475 while (
_in.peek() !=
'*' &&
_in.peek() != EOF)
479 std::getline(
_in, line);
488 std::stringstream ss(line);
496 ss >> abaqus_node_id >> c >> x >> c >> y;
500 if (ss.peek() ==
',')
505 id_storage->push_back(abaqus_node_id);
530 unsigned n_nodes_per_elem = 0;
533 if (upper.find(
"T3D2") != std::string::npos ||
534 upper.find(
"B31") != std::string::npos)
537 n_nodes_per_elem = 2;
540 else if (upper.find(
"B32") != std::string::npos)
543 n_nodes_per_elem = 3;
546 else if (upper.find(
"S3") != std::string::npos ||
547 upper.find(
"CPE3") != std::string::npos ||
548 upper.find(
"2D3") != std::string::npos)
551 n_nodes_per_elem = 3;
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)
560 n_nodes_per_elem = 4;
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)
569 n_nodes_per_elem = 6;
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)
578 n_nodes_per_elem = 8;
581 else if (upper.find(
"3D8") != std::string::npos)
584 n_nodes_per_elem = 8;
587 else if (upper.find(
"3D4") != std::string::npos)
590 n_nodes_per_elem = 4;
593 else if (upper.find(
"3D20") != std::string::npos)
596 n_nodes_per_elem = 20;
599 else if (upper.find(
"3D27") != std::string::npos)
602 n_nodes_per_elem = 27;
605 else if (upper.find(
"3D6") != std::string::npos)
608 n_nodes_per_elem = 6;
611 else if (upper.find(
"3D15") != std::string::npos)
614 n_nodes_per_elem = 15;
617 else if (upper.find(
"3D10") != std::string::npos)
620 n_nodes_per_elem = 10;
624 libmesh_error_msg(
"Unrecognized element type: " << upper);
630 const ElementDefinition & eledef = eletypes[elem_type];
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 " \
641 while (
_in.peek() !=
'*' &&
_in.peek() != EOF)
648 _in >> abaqus_elem_id >> c;
661 while (id_count < n_nodes_per_elem)
664 std::string csv_line;
665 std::getline(
_in, csv_line);
668 std::stringstream line_stream(csv_line);
672 while (std::getline(line_stream, cell,
','))
675 bool success = string_to_num(cell, abaqus_global_node_id);
683 Node * node = the_mesh.
node_ptr(libmesh_global_node_id);
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?");
694 unsigned libmesh_elem_local_node_id =
695 eledef.abaqus_zero_based_node_id_to_libmesh_node_id[id_count];
698 elem->
set_node(libmesh_elem_local_node_id) = node;
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 " \
716 if (elset_name !=
"")
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);
746 size_t label_index = upper_line.find(upper_label_name +
"=");
748 if (label_index != std::string::npos)
751 size_t comma_index = upper_line.find(
",", label_index);
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;
759 return std::string(beg,
end);
763 return std::string(
"");
776 std::stringstream line_stream(upper);
777 while (std::getline(line_stream, cell,
','))
778 if (cell ==
"GENERATE")
789 std::vector<dof_id_type> & id_storage = container[set_name];
792 while (
_in.peek() !=
'*' &&
_in.peek() != EOF)
795 std::string csv_line;
796 std::getline(
_in, csv_line);
801 std::stringstream line_stream(csv_line);
802 while (std::getline(line_stream, cell,
','))
805 bool success = string_to_num(cell,
id);
811 id_storage.push_back(
id);
822 std::vector<dof_id_type> & id_storage = container[set_name];
827 while (
_in.peek() !=
'*' &&
_in.peek() != EOF)
830 std::string csv_line;
831 std::getline(
_in, csv_line);
840 std::stringstream line_stream(csv_line);
841 line_stream >> start >> c >>
end >> c >> stride;
848 for (
dof_id_type current = start; current <=
end; current += stride)
849 id_storage.push_back(current);
859 std::vector<std::pair<dof_id_type, unsigned>> & id_storage = container[sideset_name];
864 std::string elem_id_or_set, dummy;
867 while (
_in.peek() !=
'*' &&
_in.peek() != EOF)
872 std::getline(
_in, elem_id_or_set,
',');
876 strip_ws(elem_id_or_set);
885 bool success = string_to_num(elem_id_or_set, elem_id);
890 id_storage.push_back( std::make_pair(elem_id, side_id) );
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) );
901 std::getline(
_in, dummy);
918 std::map<ElemType, unsigned> elem_types_map;
922 elem_types_map[type] = ctr++;
932 for (
unsigned elemset_id=0; it !=
end; ++it, ++elemset_id)
935 std::vector<dof_id_type> & id_vector = it->second;
938 for (
const auto &
id : id_vector)
952 if (elem.
dim() < max_dim)
958 (elemset_id + (elem_types_map[elem.
type()] * n_elemsets));
984 for (
unsigned short current_id=0; it !=
end; ++it, ++current_id)
990 std::vector<dof_id_type> & nodeset_ids = it->second;
992 for (
const auto &
id : nodeset_ids)
998 Node * node = the_mesh.
node_ptr(libmesh_global_node_id);
1000 if (node ==
nullptr)
1001 libmesh_error_msg(
"Error! Mesh::node_ptr() returned nullptr!");
1024 for (
unsigned short current_id=0; it !=
end; ++it, ++current_id)
1030 std::vector<std::pair<dof_id_type,unsigned>> & sideset_ids = it->second;
1032 for (
const auto &
id : sideset_ids)
1037 unsigned abaqus_side_number =
id.second;
1046 const ElementDefinition & eledef = eletypes[elem.
type()];
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 " \
1061 eledef.abaqus_zero_based_side_id_to_libmesh_side_id[abaqus_side_number-1],
1082 std::unordered_multimap<dof_id_type, std::pair<Elem *, boundary_id_type>> provide_bcs;
1091 std::vector<dof_id_type> & id_vector = it->second;
1094 for (
const auto &
id : id_vector)
1105 if (elem.
dim() == max_dim)
1112 if (elem.
dim()+1 != max_dim)
1113 libmesh_error_msg(
"ERROR: Expected boundary element of dimension " << max_dim-1 <<
" but got " << elem.
dim());
1116 provide_bcs.insert(std::make_pair(elem.
key(),
1117 std::make_pair(&elem,
1130 if (elem->dim() == max_dim)
1131 for (
auto sn : elem->side_index_range())
1139 auto bounds = provide_bcs.equal_range (elem->key(sn));
1142 for (
const auto & pr :
as_range(bounds))
1145 std::unique_ptr<Elem> side (elem->build_side_ptr(sn));
1148 Elem * lower_dim_elem = pr.second.first;
1152 if (*lower_dim_elem == *side)
1170 if (
_in.peek() ==
'*')
1176 if (
_in.peek() ==
'*')
1180 std::getline(
_in, dummy);
1206 unsigned char max_dim = 0;
1208 unsigned char elem_dimensions_size = cast_int<unsigned char>
1211 for (
unsigned char i=1; i<elem_dimensions_size; ++i)