libMesh
dyna_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 // Local includes
19 #include "libmesh/libmesh_config.h"
20 #include "libmesh/libmesh_logging.h"
21 #include "libmesh/dof_map.h"
22 #include "libmesh/elem.h"
23 #include "libmesh/dyna_io.h"
24 #include "libmesh/mesh_base.h"
25 #include "libmesh/int_range.h"
26 
27 // TIMPI includes
29 
30 // C++ includes
31 #include <array>
32 #include <cstddef>
33 #include <fstream>
34 #include <iterator>
35 #include <numeric> // iota
36 
37 namespace libMesh
38 {
39 
40 // Initialize the static data member
42 
43 
44 
45 // Definition of the static function which constructs the ElementMaps object.
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 }
87 
88 
89 
91  (ElemType type_in,
92  dyna_int_type dyna_type_in,
93  dyna_int_type dim_in,
94  dyna_int_type p_in) :
95  type(type_in),
96  dyna_type(dyna_type_in),
97  dim(dim_in),
98  p(p_in)
99 {
100  const unsigned int n_nodes = Elem::type_to_n_nodes_map[type_in];
101  nodes.resize(n_nodes);
102  std::iota(nodes.begin(), nodes.end(), 0);
103 }
104 
105 
107  (ElemType type_in,
108  dyna_int_type dyna_type_in,
109  dyna_int_type dim_in,
110  dyna_int_type p_in,
111  std::vector<unsigned int> && nodes_in) :
112  type(type_in),
113  dyna_type(dyna_type_in),
114  dim(dim_in),
115  p(p_in),
116  nodes(nodes_in)
117 {}
118 
119 
120 
123  constraint_rows_broadcast (false)
124 {
125 }
126 
127 
128 
129 void DynaIO::read (const std::string & name)
130 {
131  std::ifstream in (name.c_str());
132  this->read_mesh (in);
133 }
134 
135 
136 
137 void DynaIO::read_mesh(std::istream & in)
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
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 }
683 
684 
686  unsigned int sys_num,
687  unsigned int var_num)
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 }
728 
729 
730 } // namespace libMesh
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::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::Elem::n_nodes
virtual unsigned int n_nodes() const =0
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::EDGE4
Definition: enum_elem_type.h:37
libMesh::DynaIO::ElementDefinition::type
ElemType type
Definition: dyna_io.h:158
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::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::DynaIO::ElementDefinition::nodes
std::vector< unsigned int > nodes
Definition: dyna_io.h:162
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::DynaIO::ElementDefinition::ElementDefinition
ElementDefinition(ElemType type_in, dyna_int_type dyna_type_in, dyna_int_type dim_in, dyna_int_type p_in)
Definition: dyna_io.C:91
libMesh::DynaIO::add_spline_constraints
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-def...
Definition: dyna_io.C:685
libMesh::RATIONAL_BERNSTEIN_MAP
Definition: enum_elem_type.h:84
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DofObject::dof_number
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:956
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::IntRange
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition: int_range.h:53
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::DynaIO::build_element_maps
static ElementMaps build_element_maps()
A static function used to construct the _element_maps struct, statically.
Definition: dyna_io.C:46
libMesh::HEX27
Definition: enum_elem_type.h:49
libMesh::Utility::iota
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota is a duplication of the SGI STL extension std::iota.
Definition: utility.h:105
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
parallel_implementation.h
libMesh::DynaIO::ElementDefinition
Defines mapping from libMesh element types to LS-DYNA element types or vice-versa.
Definition: dyna_io.h:145
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::TypeVector::add_scaled
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
Definition: type_vector.h:665
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::Node
A Node is like a Point, but with more information.
Definition: node.h:52
n_nodes
const dof_id_type n_nodes
Definition: tecplot_io.C:68
libMesh::DynaIO::dyna_int_type
int32_t dyna_int_type
The integer type DYNA uses.
Definition: dyna_io.h:121
libMesh::DynaIO::ElementMaps::add_def
void add_def(const ElementDefinition &eledef)
Definition: dyna_io.h:172
libMesh::Elem::set_node
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2059
libMesh::MeshBase::node_ref
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:451
libMesh::Elem::type_to_n_nodes_map
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition: elem.h:576
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::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
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::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
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::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
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::DynaIO::read
virtual void read(const std::string &name) override
Reads in a mesh in the Dyna format from the ASCII file given by name.
Definition: dyna_io.C:129
libMesh::MeshBase::allow_renumbering
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use.
Definition: mesh_base.h:1025
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::DofMap::add_constraint_row
void add_constraint_row(const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...
Definition: dof_map_constraints.C:1364
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::DynaIO::DynaIO
DynaIO(MeshBase &mesh)
Constructor.
Definition: dyna_io.C:121
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::MeshInput
This class defines an abstract interface for Mesh input.
Definition: mesh_base.h:60
libMesh::MeshBase::is_replicated
virtual bool is_replicated() const
Definition: mesh_base.h:181
libMesh::EDGE2
Definition: enum_elem_type.h:35
libMesh::ElemType
ElemType
Defines an enum for geometric element types.
Definition: enum_elem_type.h:33
libMesh::DynaIO::ElementMaps
struct which holds a map from LS-DYNA to libMesh element numberings and vice-versa.
Definition: dyna_io.h:169