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

Reading and writing meshes in (a subset of) LS-DYNA format. More...

#include <dyna_io.h>

Inheritance diagram for libMesh::DynaIO:
[legend]

Classes

struct  ElementDefinition
 Defines mapping from libMesh element types to LS-DYNA element types or vice-versa. More...
 
struct  ElementMaps
 struct which holds a map from LS-DYNA to libMesh element numberings and vice-versa. More...
 

Public Member Functions

 DynaIO (MeshBase &mesh)
 Constructor. More...
 
virtual void read (const std::string &name) override
 Reads in a mesh in the Dyna format from the ASCII file given by name. More...
 
void add_spline_constraints (DofMap &dof_map, unsigned int sys_num, unsigned int var_num)
 Constrains finite element degrees of freedom in terms of spline degrees of freedom by adding user-defined constraint rows to sys. 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 int32_t dyna_int_type
 The integer type DYNA uses. More...
 
typedef double dyna_fp_type
 The floating-point type DYNA uses. More...
 

Private Member Functions

void read_mesh (std::istream &in)
 Implementation of the read() function. More...
 

Static Private Member Functions

static ElementMaps build_element_maps ()
 A static function used to construct the _element_maps struct, statically. More...
 

Private Attributes

std::vector< Node * > spline_node_ptrs
 
std::map< dof_id_type, std::vector< std::pair< dof_id_type, Real > > > constraint_rows
 
bool constraint_rows_broadcast
 
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...
 

Static Private Attributes

static const int max_ints_per_line = 10
 How many can we find on a line? More...
 
static const int max_fps_per_line = 5
 How many can we find on a line? More...
 
static ElementMaps _element_maps = DynaIO::build_element_maps()
 A static ElementMaps object that is built statically and used by all instances of this class. More...
 

Detailed Description

Reading and writing meshes in (a subset of) LS-DYNA format.

The initial implementation only handles cards in the format described in "Geometry import to LS-DYNA", for isogeometric analysis.

Author
Roy H. Stogner
Date
2019

Definition at line 52 of file dyna_io.h.

Member Typedef Documentation

◆ dyna_fp_type

typedef double libMesh::DynaIO::dyna_fp_type
private

The floating-point type DYNA uses.

Definition at line 131 of file dyna_io.h.

◆ dyna_int_type

typedef int32_t libMesh::DynaIO::dyna_int_type
private

The integer type DYNA uses.

Definition at line 121 of file dyna_io.h.

Constructor & Destructor Documentation

◆ DynaIO()

libMesh::DynaIO::DynaIO ( MeshBase mesh)
explicit

Constructor.

Takes a non-const Mesh reference which it will fill up with elements via the read() command.

Definition at line 121 of file dyna_io.C.

121  :
122  MeshInput<MeshBase> (mesh),
124 {
125 }

Member Function Documentation

◆ add_spline_constraints()

void libMesh::DynaIO::add_spline_constraints ( DofMap dof_map,
unsigned int  sys_num,
unsigned int  var_num 
)

Constrains finite element degrees of freedom in terms of spline degrees of freedom by adding user-defined constraint rows to sys.

Definition at line 685 of file dyna_io.C.

688 {
689 #ifdef LIBMESH_ENABLE_CONSTRAINTS
690  const MeshBase & mesh = this->mesh();
691 
692  // We have some strict compatibility requirements here still
693  if (mesh.allow_renumbering() ||
694  (!mesh.is_replicated() &&
696  libmesh_not_implemented();
697 
698  // We do mesh reads in serial, and the mesh broadcast doesn't
699  // broadcast our internal data, so we may need to do that now
701  {
702  mesh.comm().broadcast(constraint_rows);
704  }
705 
706  for (auto & node_row : constraint_rows)
707  {
708  DofConstraintRow dc_row;
709  const Node * node = mesh.query_node_ptr(node_row.first);
710  if (!node)
711  continue;
712  const dof_id_type constrained_id =
713  node->dof_number(sys_num, var_num, 0);
714  for (auto pr : node_row.second)
715  {
716  const Node & spline_node = mesh.node_ref(pr.first);
717  const dof_id_type spline_dof_id =
718  spline_node.dof_number(sys_num, var_num, 0);
719  dc_row[spline_dof_id] = pr.second;
720  }
721  dof_map.add_constraint_row(constrained_id, dc_row);
722  }
723 #else
724  libmesh_ignore(dof_map, sys_num, var_num);
725  libmesh_not_implemented();
726 #endif
727 }

References libMesh::DofMap::add_constraint_row(), libMesh::MeshBase::allow_remote_element_removal(), libMesh::MeshBase::allow_renumbering(), libMesh::ParallelObject::comm(), constraint_rows, constraint_rows_broadcast, libMesh::DofObject::dof_number(), libMesh::MeshBase::is_replicated(), libMesh::libmesh_ignore(), libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshBase::node_ref(), and libMesh::MeshBase::query_node_ptr().

Referenced by MeshInputTest::testDynaReadPatch().

◆ build_element_maps()

DynaIO::ElementMaps libMesh::DynaIO::build_element_maps ( )
staticprivate

A static function used to construct the _element_maps struct, statically.

Definition at line 46 of file dyna_io.C.

47 {
48  // Object to be filled up
49  ElementMaps em;
50 
51  // em.add_def(ElementDefinition(TRI3, 2, 2, 1)); // node mapping?
52  // em.add_def(ElementDefinition(TRI6, 2, 2, 2)); // node mapping?
53  // em.add_def(ElementDefinition(TET4, 2, 3, 1)); // node mapping?
54  // em.add_def(ElementDefinition(TET10, 2, 3, 2)); // node mapping?
55  // em.add_def(ElementDefinition(PRISM6, 3, 3, 1)); // node mapping?
56  // em.add_def(ElementDefinition(PRISM18, 3, 3, 2)); // node mapping?
57 
58  // Eventually we'll map both tensor-product and non-tensor-product
59  // BEXT elements to ours; for now we only support non-tensor-product
60  // Bezier elements.
61  // for (unsigned int i=0; i != 2; ++i)
62  for (unsigned int i=1; i != 2; ++i)
63  {
64  // We only have one element for whom node orders match...
65  em.add_def(ElementDefinition(EDGE2, i, 1, 1));
66 
67  em.add_def(ElementDefinition(EDGE3, i, 1, 2,
68  {0, 2, 1}));
69  em.add_def(ElementDefinition(EDGE4, i, 1, 2,
70  {0, 2, 3, 1}));
71 
72  em.add_def(ElementDefinition(QUAD4, i, 2, 1,
73  {0, 1, 3, 2}));
74  em.add_def(ElementDefinition(QUAD9, i, 2, 2,
75  {0, 4, 1, 7, 8, 5, 3, 6, 2}));
76 
77  em.add_def(ElementDefinition(HEX8, i, 3, 1,
78  {0, 1, 3, 2, 4, 5, 7, 6}));
79  em.add_def(ElementDefinition(HEX27, i, 3, 2,
80  { 0, 8, 1, 11, 20, 9, 3, 10, 2,
81  12, 21, 13, 24, 26, 22, 15, 23, 14,
82  4, 16, 5, 19, 25, 17, 7, 18, 6}));
83  }
84 
85  return em;
86 }

References libMesh::DynaIO::ElementMaps::add_def(), libMesh::EDGE2, libMesh::EDGE3, libMesh::EDGE4, libMesh::HEX27, libMesh::HEX8, libMesh::QUAD4, and libMesh::QUAD9.

◆ 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 }

◆ read()

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

Reads in a mesh in the Dyna format from the ASCII file given by name.

Note
The user is responsible for calling Mesh::prepare_for_use() after reading the mesh and before using it.
To safely use DynaIO::add_spline_constraints with a DistributedMesh, currently the user must allow_remote_element_removal(false) and allow_renumbering(false) before the mesh is read.

The patch ids defined in the Dyna file are stored as subdomain ids.

The spline nodes defined in the Dyna file are added to the mesh with type NodeElem. The only connection between spline nodes and finite element nodes will be user constraint equations, so using a space-filling-curve partitioner for these meshes might be a good idea.

Implements libMesh::MeshInput< MeshBase >.

Definition at line 129 of file dyna_io.C.

130 {
131  std::ifstream in (name.c_str());
132  this->read_mesh (in);
133 }

References libMesh::Quality::name(), and read_mesh().

Referenced by libMesh::NameBasedIO::read(), MeshInputTest::testDynaReadElem(), and MeshInputTest::testDynaReadPatch().

◆ read_mesh()

void libMesh::DynaIO::read_mesh ( std::istream &  in)
private

Implementation of the read() function.

This function is called by the public interface function and implements reading the file.

Definition at line 137 of file dyna_io.C.

138 {
139  // This is a serial-only process for now;
140  // the Mesh should be read on processor 0 and
141  // broadcast later
142  libmesh_assert_equal_to (MeshInput<MeshBase>::mesh().processor_id(), 0);
143 
144  libmesh_assert(in.good());
145 
146  // clear any data in the mesh
147  MeshBase & mesh = MeshInput<MeshBase>::mesh();
148  mesh.clear();
149 
150  // clear any of our own data
151  spline_node_ptrs.clear();
152  constraint_rows.clear();
154 
155  // Expect different sections, in this order, perhaps with blank
156  // lines and/or comments in between:
157 
158  enum FileSection {
159  FILE_HEADER,
160  PATCH_HEADER,
161  NODE_LINES,
162  // (repeat for each node)
163  N_ELEM_SUBBLOCKS,
164  ELEM_SUBBLOCK_HEADER,
165  // (repeat for each subblock)
166  ELEM_NODES_LINES,
167  ELEM_COEF_VEC_IDS,
168  // (repeat nodes lines + coef vec ids for each elem, subblock)
169  N_COEF_BLOCKS, // number of coef vec blocks of each type
170  N_VECS_PER_BLOCK, // number of coef vecs in each dense block
171  COEF_VEC_COMPONENTS,
172  // (repeat coef vec components as necessary)
173  // (repeat coef blocks as necessary)
174  //
175  // reserved for sparse block stuff we don't support yet
176  END_OF_FILE };
177 
178  FileSection section = FILE_HEADER;
179 
180  // Values to remember from section to section
181  dyna_int_type patch_id, n_spline_nodes, n_elem, n_coef_vec, weight_control_flag;
182  dyna_int_type n_elem_blocks, n_dense_coef_vec_blocks;
183  std::vector<dyna_int_type> // indexed from 0 to n_elem_blocks
184  block_elem_type,
185  block_n_elem,
186  block_n_nodes, // Number of *spline* nodes constraining elements
187  block_n_coef_vec, // Number of coefficient vectors for each elem
188  block_p,
189  block_dim;
190  std::vector<dyna_int_type> // indexed from 0 to n_dense_coef_vec_blocks
191  n_coef_vecs_in_subblock, n_coef_comp;
192  unsigned char weight_index = 0;
193  dyna_int_type n_nodes_read = 0,
194  n_elem_blocks_read = 0,
195  n_elems_read = 0,
196  n_elem_nodes_read = 0,
197  n_elem_cvids_read = 0,
198  n_coef_headers_read = 0,
199  n_coef_blocks_read = 0,
200  n_coef_comp_read = 0,
201  n_coef_vecs_read = 0;
202 
203  // For reading the file line by line
204  std::string s;
205 
206  // For storing global (spline) weights, until we have enough data to
207  // use them for calculating local (Bezier element) nodes
208  std::vector<Real> spline_weights;
209 
210  // For storing elements' constraint equations:
211  // Global node indices (1-based in file, 0-based in memory):
212  // elem_global_nodes[block_num][elem_num][local_index] = global_index
213  std::vector<std::vector<std::vector<dof_id_type>>> elem_global_nodes;
214 
215  // Dense constraint vectors in the Dyna file
216  // When first read:
217  // dense_constraint_vecs[block_num][vec_in_block][column_num] = coef
218  // When used:
219  // dense_constraint_vecs[0][vec_num][column_num] = coef
220  std::vector<std::vector<std::vector<Real>>> dense_constraint_vecs;
221 
222  // Constraint vector indices (1-based in file, 0-based in memory):
223  // elem_constraint_rows[block_num][elem_num][row_num] = cv_index
224  std::vector<std::vector<std::vector<dof_id_type>>> elem_constraint_rows;
225 
226  while (true)
227  {
228  // Try to read something. This may set EOF!
229  std::getline(in, s);
230 
231  if (in)
232  {
233  // Process s...
234 
235  if (s.find("B E X T 2.0") == static_cast<std::string::size_type>(0))
236  {
237  libmesh_assert_equal_to(section, FILE_HEADER);
238  section = PATCH_HEADER;
239  continue;
240  }
241 
242  // Ignore comments
243  if (s.find("$#") == static_cast<std::string::size_type>(0))
244  continue;
245 
246  // Ignore blank lines
247  if (s.find_first_not_of(" \t") == std::string::npos)
248  continue;
249 
250  // Parse each important section
251  std::stringstream stream(s);
252  switch (section) {
253  case PATCH_HEADER:
254  stream >> patch_id;
255  stream >> n_spline_nodes;
256  stream >> n_elem;
257  stream >> n_coef_vec;
258  stream >> weight_control_flag;
259  if (stream.fail())
260  libmesh_error_msg("Failure to parse patch header\n");
261 
262  spline_node_ptrs.resize(n_spline_nodes);
263  spline_weights.resize(n_spline_nodes);
264 
265  if (weight_control_flag)
266  {
267  weight_index = cast_int<unsigned char>
268  (mesh.add_node_datum<Real>("rational_weight"));
270  mesh.set_default_mapping_data(weight_index);
271  }
272 
273  section = NODE_LINES;
274  break;
275  case NODE_LINES:
276  {
277  std::array<dyna_fp_type, 4> xyzw;
278  stream >> xyzw[0];
279  stream >> xyzw[1];
280  stream >> xyzw[2];
281  stream >> xyzw[3];
282 
283  if (weight_control_flag)
284  spline_weights[n_nodes_read] = xyzw[3];
285 
286  // We'll use the spline nodes via NodeElem as the "true"
287  // degrees of freedom, to which other Elem degrees of
288  // freedom will be tied via constraint equations.
289  Node *n = spline_node_ptrs[n_nodes_read] =
290  mesh.add_point(Point(xyzw[0], xyzw[1], xyzw[2]));
291  Elem * elem = Elem::build(NODEELEM).release();
292  elem->set_node(0) = n;
293  mesh.add_elem(elem);
294  }
295  ++n_nodes_read;
296 
297  if (stream.fail())
298  libmesh_error_msg("Failure to parse node line\n");
299 
300  if (n_nodes_read >= n_spline_nodes)
301  section = N_ELEM_SUBBLOCKS;
302  break;
303  case N_ELEM_SUBBLOCKS:
304  stream >> n_elem_blocks;
305  if (stream.fail())
306  libmesh_error_msg("Failure to parse n_elem_blocks\n");
307 
308  block_elem_type.resize(n_elem_blocks);
309  block_n_elem.resize(n_elem_blocks);
310  block_n_nodes.resize(n_elem_blocks);
311  block_n_coef_vec.resize(n_elem_blocks);
312  block_p.resize(n_elem_blocks);
313  block_dim.resize(n_elem_blocks);
314 
315  elem_global_nodes.resize(n_elem_blocks);
316  elem_constraint_rows.resize(n_elem_blocks);
317 
318  n_elem_blocks_read = 0;
319  section = ELEM_SUBBLOCK_HEADER;
320  break;
321  case ELEM_SUBBLOCK_HEADER:
322  stream >> block_elem_type[n_elem_blocks_read];
323  stream >> block_n_elem[n_elem_blocks_read];
324  stream >> block_n_nodes[n_elem_blocks_read];
325  stream >> block_n_coef_vec[n_elem_blocks_read];
326  stream >> block_p[n_elem_blocks_read];
327 
328  if (stream.fail())
329  libmesh_error_msg("Failure to parse elem block\n");
330 
331  block_dim[n_elem_blocks_read] = 1; // All blocks here are at least 1D
332 
333  dyna_int_type block_other_p; // Check for isotropic p
334  stream >> block_other_p;
335  if (!stream.fail())
336  {
337  block_dim[n_elem_blocks_read] = 2; // Found a second dimension!
338 
339  if (block_other_p != block_p[n_elem_blocks_read])
340  libmesh_not_implemented(); // We don't support p anisotropy
341 
342  stream >> block_other_p;
343  if (!stream.fail())
344  {
345  block_dim[n_elem_blocks_read] = 3; // Found a third dimension!
346 
347  if (block_other_p != block_p[n_elem_blocks_read])
348  libmesh_not_implemented();
349  }
350  }
351 
352  {
353  auto & block_global_nodes = elem_global_nodes[n_elem_blocks_read];
354  auto & block_constraint_rows = elem_constraint_rows[n_elem_blocks_read];
355 
356  block_global_nodes.resize(block_n_elem[n_elem_blocks_read]);
357  block_constraint_rows.resize(block_n_elem[n_elem_blocks_read]);
358 
359  for (auto e : IntRange<dyna_int_type>
360  (0, block_n_elem[n_elem_blocks_read]))
361  {
362  block_global_nodes[e].resize(block_n_nodes[n_elem_blocks_read]);
363  block_constraint_rows[e].resize(block_n_coef_vec[n_elem_blocks_read]);
364  }
365  }
366 
367  n_elem_blocks_read++;
368  if (n_elem_blocks_read == n_elem_blocks)
369  {
370  n_elem_blocks_read = 0;
371  n_elems_read = 0;
372  section = ELEM_NODES_LINES;
373  }
374  break;
375  case ELEM_NODES_LINES:
376  {
377  const int end_node_to_read =
378  std::min(block_n_nodes[n_elem_blocks_read], n_elem_nodes_read + max_ints_per_line);
379  for (; n_elem_nodes_read != end_node_to_read; ++n_elem_nodes_read)
380  {
381  dyna_int_type node_id;
382  stream >> node_id;
383  node_id--;
384  elem_global_nodes[n_elem_blocks_read][n_elems_read][n_elem_nodes_read] = node_id;
385 
386  // Let's assume that our *only* mid-line breaks are
387  // due to the max_ints_per_line limit. This should be
388  // less flexible but better for error detection.
389  if (stream.fail())
390  libmesh_error_msg("Failure to parse elem nodes\n");
391  }
392 
393  if (n_elem_nodes_read == block_n_nodes[n_elem_blocks_read])
394  {
395  n_elem_nodes_read = 0;
396  section = ELEM_COEF_VEC_IDS;
397  }
398  }
399  break;
400  case ELEM_COEF_VEC_IDS:
401  {
402  const int end_cvid_to_read =
403  std::min(block_n_coef_vec[n_elem_blocks_read], n_elem_cvids_read + max_ints_per_line);
404  for (; n_elem_cvids_read != end_cvid_to_read; ++n_elem_cvids_read)
405  {
406  dyna_int_type node_cvid;
407  stream >> node_cvid;
408  node_cvid--;
409 
410  elem_constraint_rows[n_elem_blocks_read][n_elems_read][n_elem_cvids_read] = node_cvid;
411 
412  // Let's assume that our *only* mid-line breaks are
413  // due to the max_ints_per_line limit. This should be
414  // less flexible but better for error detection.
415  if (stream.fail())
416  libmesh_error_msg("Failure to parse elem cvids\n");
417  }
418  if (n_elem_cvids_read == block_n_nodes[n_elem_blocks_read])
419  {
420  n_elem_cvids_read = 0;
421  n_elems_read++;
422  section = ELEM_NODES_LINES; // Read another elem, nodes first
423  if (n_elems_read == block_n_elem[n_elem_blocks_read])
424  {
425  n_elems_read = 0;
426  n_elem_blocks_read++;
427  if (n_elem_blocks_read == n_elem_blocks)
428  section = N_COEF_BLOCKS; // Move on to coefficient vectors
429  }
430  }
431  }
432  break;
433  case N_COEF_BLOCKS:
434  {
435  stream >> n_dense_coef_vec_blocks;
436  dyna_int_type n_sparse_coef_vec_blocks;
437  stream >> n_sparse_coef_vec_blocks;
438 
439  if (stream.fail())
440  libmesh_error_msg("Failure to parse n_*_coef_vec_blocks\n");
441 
442  if (n_sparse_coef_vec_blocks != 0)
443  libmesh_not_implemented();
444 
445  dense_constraint_vecs.resize(n_dense_coef_vec_blocks);
446  n_coef_vecs_in_subblock.resize(n_dense_coef_vec_blocks);
447  n_coef_comp.resize(n_dense_coef_vec_blocks);
448 
449  section = N_VECS_PER_BLOCK;
450  }
451  break;
452  case N_VECS_PER_BLOCK:
453  stream >> n_coef_vecs_in_subblock[n_coef_headers_read];
454  stream >> n_coef_comp[n_coef_headers_read];
455 
456  if (stream.fail())
457  libmesh_error_msg("Failure to parse dense coef subblock header\n");
458 
459  dense_constraint_vecs[n_coef_headers_read].resize
460  (n_coef_vecs_in_subblock[n_coef_headers_read]);
461 
462  for (auto & vec : dense_constraint_vecs[n_coef_headers_read])
463  vec.resize(n_coef_comp[n_coef_headers_read]);
464 
465  n_coef_headers_read++;
466  if (n_coef_headers_read == n_dense_coef_vec_blocks)
467  {
468  n_coef_headers_read = 0;
469  section = COEF_VEC_COMPONENTS;
470  }
471  break;
472  case COEF_VEC_COMPONENTS:
473  {
474  auto & current_vec =
475  dense_constraint_vecs[n_coef_blocks_read][n_coef_vecs_read];
476 
477  const int end_coef_to_read =
478  std::min(n_coef_comp[n_coef_blocks_read],
479  n_coef_comp_read + max_fps_per_line);
480  for (; n_coef_comp_read != end_coef_to_read; ++n_coef_comp_read)
481  {
482  dyna_fp_type coef_comp;
483  stream >> coef_comp;
484 
485  current_vec[n_coef_comp_read] = coef_comp;
486 
487  // Let's assume that our *only* mid-line breaks are
488  // due to the max_fps_per_line limit. This should be
489  // less flexible but better for error detection.
490  if (stream.fail())
491  libmesh_error_msg("Failure to parse coefficients\n");
492  }
493  if (n_coef_comp_read == n_coef_comp[n_coef_blocks_read])
494  {
495  n_coef_comp_read = 0;
496  n_coef_vecs_read++;
497  if (n_coef_vecs_read == n_coef_vecs_in_subblock[n_coef_blocks_read])
498  {
499  n_coef_vecs_read = 0;
500  n_coef_blocks_read++;
501  if (n_coef_blocks_read == n_dense_coef_vec_blocks)
502  section = END_OF_FILE;
503  }
504  }
505  }
506  break;
507  default:
508  libmesh_error();
509  }
510 
511  if (section == END_OF_FILE)
512  break;
513  } // if (in)
514  else if (in.eof())
515  libmesh_error_msg("Premature end of file");
516  else
517  libmesh_error_msg("Input stream failure! Perhaps the file does not exist?");
518  }
519 
520  // Merge dense_constraint_vecs blocks
521  for (auto coef_vec_block :
522  IntRange<dyna_int_type>(0, n_dense_coef_vec_blocks))
523  {
524  auto & dcv0 = dense_constraint_vecs[0];
525  auto & dcvi = dense_constraint_vecs[coef_vec_block];
526  dcv0.insert(dcv0.end(),
527  std::make_move_iterator(dcvi.begin()),
528  std::make_move_iterator(dcvi.end()));
529  }
530  dense_constraint_vecs.resize(1);
531 
532  // Constraint matrices:
533  // elem_constraint_mat[block_num][elem_num][local_node_index][elem_global_nodes_index] = c
534  std::vector<std::vector<std::vector<std::vector<Real>>>> elem_constraint_mat(n_elem_blocks);
535 
536  // We need to calculate local nodes on the fly, and we'll be
537  // calculating them from constraint matrix columns, and we'll need
538  // to make sure that the same node is found each time it's
539  // calculated from multiple neighboring elements.
540  std::map<std::vector<std::pair<dof_id_type, Real>>, Node *> local_nodes;
541 
542  for (auto block_num : IntRange<dyna_int_type>(0, n_elem_blocks))
543  {
544  elem_constraint_mat[block_num].resize(block_n_elem[block_num]);
545 
546  for (auto elem_num :
547  IntRange<dyna_int_type>(0, block_n_elem[block_num]))
548  {
549  // Consult the import element table to determine which element to build
550  auto eletypes_it =
551  _element_maps.in.find(std::make_tuple(block_elem_type[block_num],
552  block_dim[block_num],
553  block_p[block_num]));
554 
555  // Make sure we actually found something
556  if (eletypes_it == _element_maps.in.end())
557  libmesh_error_msg
558  ("Element of type " << block_elem_type[block_num] <<
559  " dim " << block_dim[block_num] <<
560  " degree " << block_p[block_num] << " not found!");
561 
562  const ElementDefinition * elem_defn = &(eletypes_it->second);
563  Elem * elem = Elem::build(elem_defn->type).release();
564  libmesh_assert_equal_to(elem->dim(), block_dim[block_num]);
565 
566  auto & my_constraint_rows = elem_constraint_rows[block_num][elem_num];
567  auto & my_global_nodes = elem_global_nodes[block_num][elem_num];
568  auto & my_constraint_mat = elem_constraint_mat[block_num][elem_num];
569 
570  my_constraint_mat.resize(block_n_coef_vec[block_num]);
571  for (auto spline_node_index :
572  IntRange<dyna_int_type>(0, block_n_coef_vec[block_num]))
573  my_constraint_mat[spline_node_index].resize(elem->n_nodes());
574 
575  for (auto spline_node_index :
576  IntRange<dyna_int_type>(0, block_n_coef_vec[block_num]))
577  {
578  // Find which coef block this elem's vectors are from
579  const dyna_int_type elem_coef_vec_index =
580  my_constraint_rows[spline_node_index];
581 
582  dyna_int_type coef_block_num = 0;
583  dyna_int_type first_block_coef_vec = 0;
584  for (; elem_coef_vec_index >= first_block_coef_vec &&
585  coef_block_num != n_dense_coef_vec_blocks; ++coef_block_num)
586  {
587  first_block_coef_vec += n_coef_vecs_in_subblock[coef_block_num];
588  }
589 
590  // Make sure we did find a valid coef block
591  if (coef_block_num == n_dense_coef_vec_blocks &&
592  first_block_coef_vec <= elem_coef_vec_index)
593  libmesh_error_msg("Can't find valid constraint coef vector");
594 
595  coef_block_num--;
596 
597  if (dyna_int_type(elem->n_nodes()) !=
598  n_coef_comp[coef_block_num])
599  libmesh_error_msg("Found " <<
600  n_coef_comp[coef_block_num] <<
601  " constraint coef vectors for " <<
602  elem->n_nodes() << " nodes");
603 
604  for (auto elem_node_index :
605  IntRange<dyna_int_type>(0, elem->n_nodes()))
606  my_constraint_mat[spline_node_index][elem_node_index] =
607  dense_constraint_vecs[0][elem_coef_vec_index][elem_node_index];
608  }
609 
610  for (auto elem_node_index :
611  IntRange<dyna_int_type>(0, elem->n_nodes()))
612  {
613  dof_id_type global_node_idx = DofObject::invalid_id;
614 
615  // New finite element node data: dot product of
616  // constraint matrix columns with spline node data.
617  // Store that column as a key.
618  std::vector<std::pair<dof_id_type, Real>> key;
619 
620  for (auto spline_node_index :
621  IntRange<dyna_int_type>(0, block_n_coef_vec[block_num]))
622  {
623  const dyna_int_type elem_coef_vec_index =
624  my_constraint_rows[spline_node_index];
625 
626  const Real coef =
627  dense_constraint_vecs[0][elem_coef_vec_index][elem_node_index];
628 
629  // Global nodes are supposed to be in sorted order
630  if (global_node_idx != DofObject::invalid_id)
631  libmesh_assert_greater(my_global_nodes[spline_node_index],
632  global_node_idx);
633  global_node_idx = my_global_nodes[spline_node_index];
634 
635  if (coef != 0) // Ignore irrelevant spline nodes
636  key.push_back(std::make_pair(global_node_idx, coef));
637  }
638 
639  auto local_node_it = local_nodes.find(key);
640 
641  if (local_node_it != local_nodes.end())
642  elem->set_node(elem_defn->nodes[elem_node_index]) =
643  local_node_it->second;
644  else
645  {
646  Point p(0);
647  Real w = 0;
648  std::vector<std::pair<dof_id_type, Real>> constraint_row;
649 
650  for (auto spline_node_index :
651  IntRange<dyna_int_type>(0, block_n_coef_vec[block_num]))
652  {
653  const dof_id_type my_node_idx =
654  my_global_nodes[spline_node_index];
655 
656  const dyna_int_type elem_coef_vec_index =
657  my_constraint_rows[spline_node_index];
658 
659  const Node * spline_node = spline_node_ptrs[my_node_idx];
660 
661  const Real coef =
662  dense_constraint_vecs[0][elem_coef_vec_index][elem_node_index];
663  p.add_scaled(*spline_node, coef);
664  w += coef * spline_weights[my_node_idx];
665 
666  constraint_row.push_back(std::make_pair(spline_node->id(), coef));
667  }
668 
669  Node *n = mesh.add_point(p);
670  if (weight_control_flag)
671  n->set_extra_datum<Real>(weight_index, w);
672  local_nodes[key] = n;
673  elem->set_node(elem_defn->nodes[elem_node_index]) = n;
674 
675  constraint_rows[n->id()] = constraint_row;
676  }
677  }
678 
679  mesh.add_elem(elem);
680  }
681  }
682 }

References _element_maps, libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_node_datum(), libMesh::MeshBase::add_point(), libMesh::TypeVector< T >::add_scaled(), libMesh::Elem::build(), libMesh::MeshBase::clear(), constraint_rows, constraint_rows_broadcast, libMesh::Elem::dim(), libMesh::DofObject::id(), libMesh::DynaIO::ElementMaps::in, libMesh::DofObject::invalid_id, libMesh::libmesh_assert(), max_fps_per_line, max_ints_per_line, libMesh::MeshInput< MeshBase >::mesh(), libMesh::MeshInput< MT >::mesh(), libMesh::MeshTools::n_elem(), libMesh::Elem::n_nodes(), libMesh::NODEELEM, libMesh::DynaIO::ElementDefinition::nodes, libMesh::RATIONAL_BERNSTEIN_MAP, libMesh::Real, libMesh::MeshBase::set_default_mapping_data(), libMesh::MeshBase::set_default_mapping_type(), libMesh::DofObject::set_extra_datum(), libMesh::Elem::set_node(), spline_node_ptrs, and libMesh::DynaIO::ElementDefinition::type.

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

◆ _element_maps

DynaIO::ElementMaps libMesh::DynaIO::_element_maps = DynaIO::build_element_maps()
staticprivate

A static ElementMaps object that is built statically and used by all instances of this class.

Definition at line 189 of file dyna_io.h.

Referenced by read_mesh().

◆ _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.

◆ _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.

◆ constraint_rows

std::map<dof_id_type, std::vector<std::pair<dof_id_type, Real> > > libMesh::DynaIO::constraint_rows
private

Definition at line 106 of file dyna_io.h.

Referenced by add_spline_constraints(), and read_mesh().

◆ constraint_rows_broadcast

bool libMesh::DynaIO::constraint_rows_broadcast
private

Definition at line 109 of file dyna_io.h.

Referenced by add_spline_constraints(), and read_mesh().

◆ 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.

◆ max_fps_per_line

const int libMesh::DynaIO::max_fps_per_line = 5
staticprivate

How many can we find on a line?

Definition at line 136 of file dyna_io.h.

Referenced by read_mesh().

◆ max_ints_per_line

const int libMesh::DynaIO::max_ints_per_line = 10
staticprivate

How many can we find on a line?

Definition at line 126 of file dyna_io.h.

Referenced by read_mesh().

◆ spline_node_ptrs

std::vector<Node *> libMesh::DynaIO::spline_node_ptrs
private

Definition at line 98 of file dyna_io.h.

Referenced by read_mesh().


The documentation for this class was generated from the following files:
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::DynaIO::ElementMaps::in
std::map< Key, ElementDefinition > in
Definition: dyna_io.h:182
libMesh::MeshBase::set_n_partitions
unsigned int & set_n_partitions()
Definition: mesh_base.h:1667
libMesh::DofObject::set_extra_datum
void set_extra_datum(const unsigned int index, const T value)
Sets the value on this object of the extra datum associated with index, which should have been obtain...
Definition: dof_object.h:1042
libMesh::MeshTools::n_elem
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:705
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::EDGE4
Definition: enum_elem_type.h:37
libMesh::DynaIO::spline_node_ptrs
std::vector< Node * > spline_node_ptrs
Definition: dyna_io.h:98
libMesh::MeshBase::set_default_mapping_data
void set_default_mapping_data(const unsigned char data)
Set the default master space to physical space mapping basis functions to be used on newly added elem...
Definition: mesh_base.h:732
libMesh::ParallelObject::comm
const Parallel::Communicator & comm() const
Definition: parallel_object.h:94
libMesh::RATIONAL_BERNSTEIN_MAP
Definition: enum_elem_type.h:84
libMesh::MeshInput< MeshBase >::_obj
MeshBase * _obj
A pointer to a non-const object object.
Definition: mesh_input.h:114
libMesh::DynaIO::read_mesh
void read_mesh(std::istream &in)
Implementation of the read() function.
Definition: dyna_io.C:137
libMesh::DynaIO::dyna_fp_type
double dyna_fp_type
The floating-point type DYNA uses.
Definition: dyna_io.h:131
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::HEX27
Definition: enum_elem_type.h:49
libMesh::libmesh_ignore
void libmesh_ignore(const Args &...)
Definition: libmesh_common.h:526
libMesh::DynaIO::constraint_rows_broadcast
bool constraint_rows_broadcast
Definition: dyna_io.h:109
libMesh::DofObject::invalid_id
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:421
libMesh::QUAD4
Definition: enum_elem_type.h:41
libMesh::DynaIO::_element_maps
static ElementMaps _element_maps
A static ElementMaps object that is built statically and used by all instances of this class.
Definition: dyna_io.h:189
libMesh::DynaIO::dyna_int_type
int32_t dyna_int_type
The integer type DYNA uses.
Definition: dyna_io.h:121
libMesh::MeshBase::node_ref
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:451
libMesh::DynaIO::max_ints_per_line
static const int max_ints_per_line
How many can we find on a line?
Definition: dyna_io.h:126
libMesh::MeshBase::add_elem
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
libMesh::DynaIO::max_fps_per_line
static const int max_fps_per_line
How many can we find on a line?
Definition: dyna_io.h:136
libMesh::MeshBase::set_default_mapping_type
void set_default_mapping_type(const ElemMappingType type)
Set the default master space to physical space mapping basis functions to be used on newly added elem...
Definition: mesh_base.h:716
libMesh::EDGE3
Definition: enum_elem_type.h:36
libMesh::MeshBase::add_node_datum
unsigned int add_node_datum(const std::string &name, bool allocate_data=true)
Register a datum (of type T) to be added to each node in the mesh.
Definition: mesh_base.h:2011
libMesh::NODEELEM
Definition: enum_elem_type.h:66
libMesh::DynaIO::constraint_rows
std::map< dof_id_type, std::vector< std::pair< dof_id_type, Real > > > constraint_rows
Definition: dyna_io.h:106
libMesh::MeshInput< MeshBase >::mesh
MeshBase & mesh()
Definition: mesh_input.h:169
libMesh::MeshBase::allow_remote_element_removal
void allow_remote_element_removal(bool allow)
If false is passed in then this mesh will no longer have remote elements deleted when being prepared ...
Definition: mesh_base.h:1034
libMesh::QUAD9
Definition: enum_elem_type.h:43
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::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::MeshBase::clear
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition: mesh_base.C:429
libMesh::Elem::build
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:246
libMesh::MeshBase::query_node_ptr
virtual const Node * query_node_ptr(const dof_id_type i) const =0
libMesh::DofConstraintRow
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
Definition: dof_map.h:97
libMesh::Quality::name
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
libMesh::MeshBase::is_replicated
virtual bool is_replicated() const
Definition: mesh_base.h:181
libMesh::EDGE2
Definition: enum_elem_type.h:35