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/mesh_tools.h" 26 #include "libmesh/int_range.h" 27 #include "libmesh/utility.h" 33 #ifdef LIBMESH_HAVE_GZSTREAM 34 # include "gzstream.h" 69 for (
unsigned int i=1; i != 2; ++i)
82 {0, 4, 1, 7, 8, 5, 3, 6, 2}));
85 {0, 1, 3, 2, 4, 5, 7, 6}));
87 { 0, 8, 1, 11, 20, 9, 3, 10, 2,
88 12, 21, 13, 24, 26, 22, 15, 23, 14,
89 4, 16, 5, 19, 25, 17, 7, 18, 6}));
103 dyna_type(dyna_type_in),
109 libmesh_not_implemented_msg(
"Support for Polygons/Polyhedra not yet implemented");
111 std::iota(nodes.begin(), nodes.end(), 0);
120 std::vector<unsigned int> && nodes_in) :
122 dyna_type(dyna_type_in),
131 bool keep_spline_nodes) :
133 _keep_spline_nodes (keep_spline_nodes)
141 const bool gzipped_file = (
name.rfind(
".gz") ==
name.size() - 3);
146 std::unique_ptr<std::istream> in;
150 #ifdef LIBMESH_HAVE_GZSTREAM 151 auto inf = std::make_unique<igzstream>();
153 inf->open(
name.c_str(), std::ios::in);
156 libmesh_error_msg(
"ERROR: need gzstream to handle .gz files!!!");
161 auto inf = std::make_unique<std::ifstream>();
166 inf->open(new_name.c_str(), std::ios::in);
186 libmesh_error_msg_if(!in.good(),
"Can't read input stream");
204 ELEM_SUBBLOCK_HEADER,
218 FileSection section = FILE_HEADER;
223 std::vector<dyna_int_type>
230 std::vector<dyna_int_type>
231 n_coef_vecs_in_subblock, n_coef_comp;
232 unsigned char weight_index = 0;
234 n_elem_blocks_read = 0,
236 n_elem_nodes_read = 0,
237 n_elem_cvids_read = 0,
238 n_coef_headers_read = 0,
239 n_coef_blocks_read = 0,
240 n_coef_comp_read = 0,
241 n_coef_vecs_read = 0;
248 std::vector<Real> spline_weights;
253 std::vector<std::vector<std::vector<dof_id_type>>> elem_global_nodes;
260 std::vector<std::vector<std::vector<Real>>> dense_constraint_vecs;
264 std::vector<std::vector<std::vector<dof_id_type>>> elem_constraint_rows;
275 if (s.find(
"B E X T 2.0") ==
static_cast<std::string::size_type
>(0))
277 libmesh_error_msg_if(section != FILE_HEADER,
278 "Found 'B E X T 2.0' outside file header?");
280 section = PATCH_HEADER;
285 if (s.find(
"$#") ==
static_cast<std::string::size_type
>(0))
289 if (s.find_first_not_of(
" \t") == std::string::npos)
293 std::stringstream stream(s);
297 stream >> n_spline_nodes;
299 stream >> n_coef_vec;
300 stream >> weight_control_flag;
301 libmesh_error_msg_if(stream.fail(),
"Failure to parse patch header\n");
304 spline_weights.resize(n_spline_nodes);
313 const Real default_weight = 1.0;
314 weight_index = cast_int<unsigned char>
321 section = NODE_LINES;
325 std::array<dyna_fp_type, 4> xyzw;
331 if (weight_control_flag)
332 spline_weights[n_nodes_read] = xyzw[3];
346 libmesh_error_msg_if(stream.fail(),
"Failure to parse node line\n");
348 if (n_nodes_read >= n_spline_nodes)
349 section = N_ELEM_SUBBLOCKS;
351 case N_ELEM_SUBBLOCKS:
352 stream >> n_elem_blocks;
353 libmesh_error_msg_if(stream.fail(),
"Failure to parse n_elem_blocks\n");
355 block_elem_type.resize(n_elem_blocks);
356 block_n_elem.resize(n_elem_blocks);
357 block_n_nodes.resize(n_elem_blocks);
358 block_n_coef_vec.resize(n_elem_blocks);
359 block_p.resize(n_elem_blocks);
360 block_dim.resize(n_elem_blocks);
362 elem_global_nodes.resize(n_elem_blocks);
363 elem_constraint_rows.resize(n_elem_blocks);
365 n_elem_blocks_read = 0;
366 section = ELEM_SUBBLOCK_HEADER;
368 case ELEM_SUBBLOCK_HEADER:
369 stream >> block_elem_type[n_elem_blocks_read];
370 stream >> block_n_elem[n_elem_blocks_read];
371 stream >> block_n_nodes[n_elem_blocks_read];
372 stream >> block_n_coef_vec[n_elem_blocks_read];
373 stream >> block_p[n_elem_blocks_read];
375 libmesh_error_msg_if(stream.fail(),
"Failure to parse elem block\n");
377 block_dim[n_elem_blocks_read] = 1;
380 stream >> block_other_p;
383 block_dim[n_elem_blocks_read] = 2;
385 if (block_other_p != block_p[n_elem_blocks_read])
386 libmesh_not_implemented();
388 stream >> block_other_p;
391 block_dim[n_elem_blocks_read] = 3;
393 if (block_other_p != block_p[n_elem_blocks_read])
394 libmesh_not_implemented();
399 auto & block_global_nodes = elem_global_nodes[n_elem_blocks_read];
400 auto & block_constraint_rows = elem_constraint_rows[n_elem_blocks_read];
402 block_global_nodes.resize(block_n_elem[n_elem_blocks_read]);
403 block_constraint_rows.resize(block_n_elem[n_elem_blocks_read]);
405 for (
auto e :
make_range(block_n_elem[n_elem_blocks_read]))
407 block_global_nodes[e].resize(block_n_nodes[n_elem_blocks_read]);
408 block_constraint_rows[e].resize(block_n_coef_vec[n_elem_blocks_read]);
412 n_elem_blocks_read++;
413 if (n_elem_blocks_read == n_elem_blocks)
415 n_elem_blocks_read = 0;
417 section = ELEM_NODES_LINES;
420 case ELEM_NODES_LINES:
422 const int end_node_to_read =
423 std::min(block_n_nodes[n_elem_blocks_read], n_elem_nodes_read +
max_ints_per_line);
424 for (; n_elem_nodes_read != end_node_to_read; ++n_elem_nodes_read)
429 elem_global_nodes[n_elem_blocks_read][n_elems_read][n_elem_nodes_read] = node_id;
434 libmesh_error_msg_if(stream.fail(),
"Failure to parse elem nodes\n");
437 if (n_elem_nodes_read == block_n_nodes[n_elem_blocks_read])
439 n_elem_nodes_read = 0;
440 section = ELEM_COEF_VEC_IDS;
444 case ELEM_COEF_VEC_IDS:
446 const int end_cvid_to_read =
447 std::min(block_n_coef_vec[n_elem_blocks_read], n_elem_cvids_read +
max_ints_per_line);
448 for (; n_elem_cvids_read != end_cvid_to_read; ++n_elem_cvids_read)
454 elem_constraint_rows[n_elem_blocks_read][n_elems_read][n_elem_cvids_read] = node_cvid;
459 libmesh_error_msg_if(stream.fail(),
"Failure to parse elem cvids\n");
461 if (n_elem_cvids_read == block_n_nodes[n_elem_blocks_read])
463 n_elem_cvids_read = 0;
465 section = ELEM_NODES_LINES;
466 if (n_elems_read == block_n_elem[n_elem_blocks_read])
469 n_elem_blocks_read++;
470 if (n_elem_blocks_read == n_elem_blocks)
471 section = N_COEF_BLOCKS;
478 stream >> n_dense_coef_vec_blocks;
480 stream >> n_sparse_coef_vec_blocks;
482 libmesh_error_msg_if(stream.fail(),
"Failure to parse n_*_coef_vec_blocks\n");
484 if (n_sparse_coef_vec_blocks != 0)
485 libmesh_not_implemented();
487 dense_constraint_vecs.resize(n_dense_coef_vec_blocks);
488 n_coef_vecs_in_subblock.resize(n_dense_coef_vec_blocks);
489 n_coef_comp.resize(n_dense_coef_vec_blocks);
491 section = N_VECS_PER_BLOCK;
494 case N_VECS_PER_BLOCK:
495 stream >> n_coef_vecs_in_subblock[n_coef_headers_read];
496 stream >> n_coef_comp[n_coef_headers_read];
498 libmesh_error_msg_if(stream.fail(),
"Failure to parse dense coef subblock header\n");
500 dense_constraint_vecs[n_coef_headers_read].resize
501 (n_coef_vecs_in_subblock[n_coef_headers_read]);
503 for (
auto & vec : dense_constraint_vecs[n_coef_headers_read])
504 vec.resize(n_coef_comp[n_coef_headers_read]);
506 n_coef_headers_read++;
507 if (n_coef_headers_read == n_dense_coef_vec_blocks)
509 n_coef_headers_read = 0;
510 section = COEF_VEC_COMPONENTS;
513 case COEF_VEC_COMPONENTS:
516 dense_constraint_vecs[n_coef_blocks_read][n_coef_vecs_read];
518 const int end_coef_to_read =
519 std::min(n_coef_comp[n_coef_blocks_read],
521 for (; n_coef_comp_read != end_coef_to_read; ++n_coef_comp_read)
526 current_vec[n_coef_comp_read] = coef_comp;
531 libmesh_error_msg_if(stream.fail(),
"Failure to parse coefficients\n");
533 if (n_coef_comp_read == n_coef_comp[n_coef_blocks_read])
535 n_coef_comp_read = 0;
537 if (n_coef_vecs_read == n_coef_vecs_in_subblock[n_coef_blocks_read])
539 n_coef_vecs_read = 0;
540 n_coef_blocks_read++;
541 if (n_coef_blocks_read == n_dense_coef_vec_blocks)
542 section = END_OF_FILE;
551 if (section == END_OF_FILE)
555 libmesh_error_msg(
"Premature end of file");
557 libmesh_error_msg(
"Input stream failure! Perhaps the file does not exist?");
561 if (n_dense_coef_vec_blocks)
562 for (
auto coef_vec_block :
565 auto & dcv0 = dense_constraint_vecs[0];
566 auto & dcvi = dense_constraint_vecs[coef_vec_block];
567 dcv0.insert(dcv0.end(),
568 std::make_move_iterator(dcvi.begin()),
569 std::make_move_iterator(dcvi.end()));
571 dense_constraint_vecs.resize(1);
575 std::vector<std::vector<std::vector<std::vector<Real>>>> elem_constraint_mat(n_elem_blocks);
581 std::map<std::vector<std::pair<dof_id_type, Real>>,
Node *> local_nodes;
585 for (
auto block_num :
make_range(n_elem_blocks))
587 elem_constraint_mat[block_num].resize(block_n_elem[block_num]);
595 block_dim[block_num],
599 libmesh_error_msg_if(elem->dim() != block_dim[block_num],
600 "Elem dim " << elem->dim() <<
601 " != block_dim " << block_dim[block_num]);
603 auto & my_constraint_rows = elem_constraint_rows[block_num][elem_num];
604 auto & my_global_nodes = elem_global_nodes[block_num][elem_num];
605 auto & my_constraint_mat = elem_constraint_mat[block_num][elem_num];
607 my_constraint_mat.resize(block_n_coef_vec[block_num]);
608 for (
auto spline_node_index :
610 my_constraint_mat[spline_node_index].resize(elem->n_nodes());
612 for (
auto spline_node_index :
617 my_constraint_rows[spline_node_index];
621 for (; elem_coef_vec_index >= first_block_coef_vec &&
622 coef_block_num != n_dense_coef_vec_blocks; ++coef_block_num)
624 first_block_coef_vec += n_coef_vecs_in_subblock[coef_block_num];
628 libmesh_error_msg_if(coef_block_num == n_dense_coef_vec_blocks &&
629 first_block_coef_vec <= elem_coef_vec_index,
630 "Can't find valid constraint coef vector");
635 (
dyna_int_type(elem->n_nodes()) != n_coef_comp[coef_block_num],
636 "Found " << n_coef_comp[coef_block_num] <<
637 " constraint coef vectors for " <<
638 elem->n_nodes() <<
" nodes");
640 for (
auto elem_node_index :
642 my_constraint_mat[spline_node_index][elem_node_index] =
643 dense_constraint_vecs[0][elem_coef_vec_index][elem_node_index];
646 for (
auto elem_node_index :
654 std::vector<std::pair<dof_id_type, Real>> key;
656 for (
auto spline_node_index :
660 my_constraint_rows[spline_node_index];
663 libmesh_vector_at(dense_constraint_vecs[0],
664 elem_coef_vec_index)[elem_node_index];
668 libmesh_error_msg_if(my_global_nodes[spline_node_index] <= global_node_idx,
669 "Found unsorted global node");
671 global_node_idx = my_global_nodes[spline_node_index];
674 key.emplace_back(global_node_idx, coef);
677 if (
const auto local_node_it = local_nodes.find(key);
678 local_node_it != local_nodes.end())
679 elem->set_node(elem_defn.
nodes[elem_node_index],
680 local_node_it->second);
685 std::vector<std::pair<std::pair<const Elem *, unsigned int>,
Real>> constraint_row;
687 for (
auto spline_node_index :
691 my_global_nodes[spline_node_index];
694 my_constraint_rows[spline_node_index];
701 libmesh_vector_at(dense_constraint_vecs[0],
702 elem_coef_vec_index)[elem_node_index];
704 w += coef * libmesh_vector_at(spline_weights,
713 constraint_row.emplace_back(std::make_pair(nodeelem, 0), coef);
718 if (weight_control_flag)
720 local_nodes[key] = n;
721 elem->set_node(elem_defn.
nodes[elem_node_index], n);
723 constraint_rows[n] = constraint_row;
743 #ifdef LIBMESH_ENABLE_DEPRECATED 746 libmesh_deprecated();
750 #endif // LIBMESH_ENABLE_DEPRECATED 764 "Element of type " << dyna_elem <<
766 " degree " << p <<
" not found!");
768 return eletypes_it->second;
775 int libmesh_dbg_var(
dim),
776 int libmesh_dbg_var(p))
784 "Element of type " << libmesh_elem <<
788 libmesh_assert_equal_to(eletypes_it->second.dim,
dim);
789 libmesh_assert_equal_to(eletypes_it->second.p, p);
792 return eletypes_it->second;
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
ElemType
Defines an enum for geometric element types.
virtual void read(const std::string &name) override
Reads in a mesh in the Dyna format from the ASCII file given by name.
std::vector< Node * > spline_node_ptrs
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
constraint_rows_type & get_constraint_rows()
Constraint rows accessors.
virtual Node *& set_node(const unsigned int i)
A Node is like a Point, but with more information.
int32_t dyna_int_type
The integer type DYNA uses.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
double dyna_fp_type
The floating-point type DYNA uses.
void read_mesh(std::istream &in)
Implementation of the read() function.
Defines mapping from libMesh element types to LS-DYNA element types or vice-versa.
This is the base class from which all geometric element types are derived.
void clear_spline_nodes()
Removes any spline nodes (both NodeElem and Node), leaving only the FE mesh generated from those spli...
void add_def(const ElementDefinition &eledef)
bool _keep_spline_nodes
Whether to keep or eventually discard spline nodes.
The libMesh namespace provides an interface to certain functionality in the library.
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.
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...
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota was created back when std::iota was just an SGI STL extension.
This is the MeshBase class.
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...
This class handles the numbering of degrees of freedom on a mesh.
static const ElementDefinition & find_elem_definition(dyna_int_type dyna_elem, int dim, int p)
Finds the ElementDefinition corresponding to a particular element type.
const dof_id_type n_nodes
std::map< ElemType, ElementDefinition > out
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
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...
std::string unzip_file(std::string_view name)
Create an unzipped copy of a bz2 or xz file, returning the name of the now-unzipped file that can be ...
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
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...
static ElementMaps build_element_maps()
A static function used to construct the _element_maps struct, statically.
static const int max_fps_per_line
How many can we find on a line?
virtual void clear()
Deletes all the element and node data that is currently stored.
unsigned int add_node_datum(const std::string &name, bool allocate_data=true, const T *default_value=nullptr)
Register a datum (of type T) to be added to each node in the mesh.
DynaIO(MeshBase &mesh, bool keep_spline_nodes=true)
Constructor.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
std::unordered_map< Node *, Elem * > spline_nodeelem_ptrs
static ElementMaps _element_maps
A static ElementMaps object that is built statically and used by all instances of this class...
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
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...
static const int max_ints_per_line
How many can we find on a line?
struct which holds a map from LS-DYNA to libMesh element numberings and vice-versa.
std::vector< unsigned int > nodes
processor_id_type processor_id() const
std::map< Key, ElementDefinition > in
ElementDefinition(ElemType type_in, dyna_int_type dyna_type_in, dyna_int_type dim_in, dyna_int_type p_in)
A Point defines a location in LIBMESH_DIM dimensional Real space.