libMesh
abaqus_io.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 // C++ includes
19 #include <string>
20 #include <cstdlib> // std::strtol
21 #include <sstream>
22 #include <ctype.h> // isspace
23 
24 // Local includes
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>
32 
33 // Anonymous namespace to hold mapping Data for Abaqus/libMesh element types
34 namespace
35 {
36 using namespace libMesh;
37 
44 bool string_to_num(const std::string & input, dof_id_type & output)
45 {
46  char * endptr;
47  output = cast_int<dof_id_type>
48  (std::strtol(input.c_str(), &endptr, /*base=*/10));
49 
50  return (output != 0 || endptr != input.c_str());
51 }
52 
57 void strip_ws(std::string & line)
58 {
59  line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end());
60 }
61 
66 struct ElementDefinition
67 {
68  // Maps (zero-based!) Abaqus local node numbers to libmesh local node numbers
69  std::vector<unsigned> abaqus_zero_based_node_id_to_libmesh_node_id;
70 
71  // Maps (zero-based!) Abaqus side numbers to libmesh side numbers
72  std::vector<unsigned short> abaqus_zero_based_side_id_to_libmesh_side_id;
73 };
74 
78 std::map<ElemType, ElementDefinition> eletypes;
79 
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)
88 {
89  // If map entry does not exist, this will create it
90  ElementDefinition & map_entry = eletypes[libmesh_elem_type];
91 
92 
93  // Use the "swap trick" from Scott Meyer's "Effective STL" to swap
94  // an unnamed temporary vector into the map_entry's vector. Note:
95  // the vector(iter, iter) constructor is used.
96  std::vector<unsigned>
97  (node_map, node_map+node_map_size).swap
98  (map_entry.abaqus_zero_based_node_id_to_libmesh_node_id);
99 
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);
103 }
104 
105 
109 void init_eletypes ()
110 {
111  // This should happen only once. The first time this method is
112  // called the eletypes data structure will be empty, and we will
113  // fill it. Any subsequent calls will find an initialized
114  // eletypes map and will do nothing.
115  if (eletypes.empty())
116  {
117  {
118  // EDGE2
119  const unsigned int node_map[] = {0,1}; // identity
120  const unsigned short side_map[] = {0,1}; // identity
121  add_eletype_entry(EDGE2, node_map, 2, side_map, 2);
122  }
123 
124  {
125  // TRI3
126  const unsigned int node_map[] = {0,1,2}; // identity
127  const unsigned short side_map[] = {0,1,2}; // identity
128  add_eletype_entry(TRI3, node_map, 3, side_map, 3);
129  }
130 
131  {
132  // QUAD4
133  const unsigned int node_map[] = {0,1,2,3}; // identity
134  const unsigned short side_map[] = {0,1,2,3}; // identity
135  add_eletype_entry(QUAD4, node_map, 4, side_map, 4);
136  }
137 
138  {
139  // TET4
140  const unsigned int node_map[] = {0,1,2,3}; // identity
141  const unsigned short side_map[] = {0,1,2,3}; // identity
142  add_eletype_entry(TET4, node_map, 4, side_map, 4);
143  }
144 
145  {
146  // TET10
147  const unsigned int node_map[] = {0,1,2,3,4,5,6,7,8,9}; // identity
148  const unsigned short side_map[] = {0,1,2,3}; // identity
149  add_eletype_entry(TET10, node_map, 10, side_map, 4);
150  }
151 
152  {
153  // HEX8
154  const unsigned int node_map[] = {0,1,2,3,4,5,6,7}; // identity
155  const unsigned short side_map[] = {0,5,1,2,3,4}; // inverse = 0,2,3,4,5,1
156  add_eletype_entry(HEX8, node_map, 8, side_map, 6);
157  }
158 
159  {
160  // HEX20
161  const unsigned int node_map[] = // map is its own inverse
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[] = // inverse = 0,2,3,4,5,1
164  {0,5,1,2,3,4};
165  add_eletype_entry(HEX20, node_map, 20, side_map, 6);
166  }
167 
168  {
169  // HEX27
170  const unsigned int node_map[] = // inverse = ...,21,23,24,25,26,22,20
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[] = // inverse = 0,2,3,4,5,1
173  {0,5,1,2,3,4};
174  add_eletype_entry(HEX27, node_map, 27, side_map, 6);
175  }
176 
177  {
178  // PRISM6
179  const unsigned int node_map[] = {0,1,2,3,4,5}; // identity
180  const unsigned short side_map[] = {0,4,1,2,3}; // inverse = 0,2,3,4,1
181  add_eletype_entry(PRISM6, node_map, 6, side_map, 5);
182  }
183 
184  {
185  // PRISM15
186  const unsigned int node_map[] = // map is its own inverse
187  {0,1,2,3,4,5,6,7,8,12,13,14,9,10,11};
188  const unsigned short side_map[] = // inverse = 0,2,3,4,1
189  {0,4,1,2,3};
190  add_eletype_entry(PRISM15, node_map, 15, side_map, 5);
191  }
192 
193  {
194  // PRISM18
195  const unsigned int node_map[] = // map is its own inverse
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[] = // inverse = 0,2,3,4,1
198  {0,4,1,2,3};
199  add_eletype_entry(PRISM18, node_map, 18, side_map, 5);
200  }
201  } // if (eletypes.empty())
202 }
203 } // anonymous namespace
204 
205 
206 
207 
208 
209 namespace libMesh
210 {
211 
213  MeshInput<MeshBase> (mesh_in),
214  build_sidesets_from_nodesets(false),
215  _already_seen_part(false)
216 {
217 }
218 
219 
220 
221 
223 {
224 }
225 
226 
227 
228 
229 void AbaqusIO::read (const std::string & fname)
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 }
435 
436 
437 
438 
439 
440 
441 
442 void AbaqusIO::read_nodes(std::string nset_name)
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 }
516 
517 
518 
519 
520 
521 void AbaqusIO::read_elements(std::string upper, std::string elset_name)
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 }
720 
721 
722 
723 
724 std::string AbaqusIO::parse_label(std::string line, std::string label_name) const
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 }
765 
766 
767 
768 
769 bool AbaqusIO::detect_generated_set(std::string upper) const
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 }
783 
784 
785 
786 void AbaqusIO::read_ids(std::string set_name, container_t & container)
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 }
815 
816 
817 
818 
819 void AbaqusIO::generate_ids(std::string set_name, container_t & container)
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 }
852 
853 
854 
855 
856 void AbaqusIO::read_sideset(std::string sideset_name, sideset_container_t & container)
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 }
904 
905 
906 
907 
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 }
973 
974 
975 
976 
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 }
1009 
1010 
1011 
1012 
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 }
1158 
1159 
1160 
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 }
1201 
1202 
1203 
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 }
1217 
1218 
1219 } // namespace
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::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::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
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::Elem::dim
virtual unsigned short dim() const =0
libMesh::AbaqusIO::sideset_container_t
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.
Definition: abaqus_io.h:79
libMesh::TET10
Definition: enum_elem_type.h:46
libMesh::AbaqusIO::AbaqusIO
AbaqusIO(MeshBase &mesh)
Constructor.
Definition: abaqus_io.C:212
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::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::AbaqusIO::container_t
std::map< std::string, std::vector< dof_id_type > > container_t
The type of data structure used to store Node and Elemset IDs.
Definition: abaqus_io.h:72
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::AbaqusIO::~AbaqusIO
virtual ~AbaqusIO()
Destructor.
Definition: abaqus_io.C:222
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::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::AbaqusIO::read
virtual void read(const std::string &name) override
This method implements reading a mesh from a specified file.
Definition: abaqus_io.C:229
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::PRISM18
Definition: enum_elem_type.h:52
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
This class defines an abstract interface for Mesh input.
Definition: mesh_base.h:60
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