20 #include "libmesh/libmesh_config.h" 21 #include "libmesh/libmesh_logging.h" 22 #include "libmesh/unv_io.h" 23 #include "libmesh/mesh_base.h" 24 #include "libmesh/edge_edge2.h" 25 #include "libmesh/face_quad4.h" 26 #include "libmesh/face_tri3.h" 27 #include "libmesh/face_tri6.h" 28 #include "libmesh/face_quad8.h" 29 #include "libmesh/face_quad9.h" 30 #include "libmesh/cell_tet4.h" 31 #include "libmesh/cell_hex8.h" 32 #include "libmesh/cell_hex20.h" 33 #include "libmesh/cell_tet10.h" 34 #include "libmesh/cell_prism6.h" 35 #include "libmesh/utility.h" 36 #include "libmesh/boundary_info.h" 37 #include "libmesh/enum_to_string.h" 46 #include <unordered_map> 48 #ifdef LIBMESH_HAVE_GZSTREAM 49 # include "gzstream.h" 98 if (file_name.rfind(
".gz") < file_name.size())
100 #ifdef LIBMESH_HAVE_GZSTREAM 102 igzstream in_stream (file_name.c_str());
107 libmesh_error_msg(
"ERROR: You must have the zlib.h header files and libraries to read and write compressed streams.");
115 std::ifstream in_stream (file_name.c_str());
129 libmesh_error_msg_if(!in_stream.good(),
"ERROR: Input file not good.");
146 old_line = current_line;
149 std::getline(in_stream, current_line);
157 current_line.erase(std::remove_if(current_line.begin(), current_line.end(),
158 [](
unsigned char const c){
return std::isspace(c);}),
176 libmesh_error_msg_if(!found_node,
177 "ERROR: The Nodes section must come before the Elements section of the UNV file!");
190 libmesh_error_msg_if(!found_node || !found_elem,
191 "ERROR: The Nodes and Elements sections must come before the Groups section of the UNV file!");
199 if (found_node && found_elem && found_group)
211 libmesh_error_msg(
"Stream is bad! Perhaps the file does not exist?");
216 libmesh_error_msg_if(!found_node,
"ERROR: Could not find nodes!");
217 libmesh_error_msg_if(!found_elem,
"ERROR: Could not find elements!");
228 "Cannot open dimension " 230 <<
" mesh file when configured without " 243 for (
const auto & elem :
mesh.element_ptr_range())
244 if (elem->dim() < max_dim)
259 if (file_name.rfind(
".gz") < file_name.size())
261 #ifdef LIBMESH_HAVE_GZSTREAM 263 ogzstream out_stream(file_name.c_str());
268 libmesh_error_msg(
"ERROR: You must have the zlib.h header files and libraries to read and write compressed streams.");
277 std::ofstream out_stream (file_name.c_str());
288 libmesh_error_msg_if(!out_file.good(),
"ERROR: Output file not good.");
300 LOG_SCOPE(
"nodes_in()",
"UNVIO");
315 std::istringstream coords_stream;
322 in_file >> node_label;
325 if (node_label == -1)
333 std::getline(in_file, line);
336 std::getline(in_file, line);
342 last_pos = line.find(
"D", last_pos);
344 if (last_pos != std::string::npos)
345 line.replace(last_pos, 1,
"E");
352 coords_stream.str(line);
353 coords_stream.clear();
357 std::array<Real, 3> xyz;
359 coords_stream >> xyz[0] >> xyz[1] >> xyz[2];
365 libmesh_assert_equal_to(xyz[1], 0);
370 libmesh_assert_equal_to(xyz[2], 0);
386 unsigned char max_dim = 0;
388 unsigned char elem_dimensions_size = cast_int<unsigned char>
391 for (
unsigned char i=1; i<elem_dimensions_size; ++i)
403 std::string::size_type position = number.find(
"D", 6);
405 if (position != std::string::npos)
408 number.replace(position, 1,
"e");
431 typedef std::unordered_multimap<dof_id_type, Elem *> map_type;
432 map_type provide_bcs;
439 in_file >> group_number;
441 if (group_number == -1)
454 unsigned num_entities;
455 std::string group_name;
458 in_file >> dummy >> dummy >> dummy >> dummy >> dummy >> dummy
462 in_file >> group_name;
468 is_subdomain_group =
false,
469 is_sideset_group =
false;
485 unsigned entity_type_code, entity_tag, dummy;
486 for (
unsigned entity=0; entity<num_entities; ++entity)
488 in_file >> entity_type_code >> entity_tag >> dummy >> dummy;
490 if (entity_type_code != 8)
491 libMesh::err <<
"Warning, unrecognized entity type code = " 501 unsigned libmesh_elem_id = it->second;
507 if (group_elem->
dim() < max_dim)
509 is_sideset_group =
true;
515 libmesh_error_msg_if(group_elem->
dim()+1 != max_dim,
516 "ERROR: Expected boundary element of dimension " 517 << max_dim-1 <<
" but got " << group_elem->
dim());
522 cast_int<subdomain_id_type>(group_number);
525 provide_bcs.emplace(group_elem->
key(), group_elem);
529 else if (group_elem->
dim() == max_dim)
531 is_subdomain_group =
true;
533 cast_int<subdomain_id_type>(group_number);
537 libmesh_error_msg(
"ERROR: Found an elem with dim=" \
538 << group_elem->
dim() <<
" > " <<
"max_dim=" << +max_dim);
541 libMesh::err <<
"WARNING: UNV Element " << entity_tag <<
" not found while parsing groups." << std::endl;
546 if (is_sideset_group)
548 (cast_int<boundary_id_type>(group_number)) = group_name;
550 if (is_subdomain_group)
552 (cast_int<subdomain_id_type>(group_number)) = group_name;
557 for (
auto & elem :
mesh.active_element_ptr_range())
558 if (elem->dim() == max_dim)
559 for (
auto sn : elem->side_index_range())
560 for (
const auto & pr :
as_range(provide_bcs.equal_range (elem->key(sn))))
570 std::unique_ptr<Elem> side (elem->build_side_ptr(sn));
573 Elem * lower_dim_elem = pr.second;
576 if (*lower_dim_elem == *side)
585 LOG_SCOPE(
"elements_in()",
"UNVIO");
603 std::vector<unsigned int> node_labels (21);
617 unsigned int assign_elem_nodes[21];
624 in_file >> element_label;
626 if (element_label == -1)
629 in_file >> fe_descriptor_id
647 if (fe_descriptor_id < 25)
650 in_file >> dummy >> dummy >> dummy;
654 for (
unsigned int j=1; j<=
n_nodes; j++)
655 in_file >> node_labels[j];
658 std::unique_ptr<Elem> elem;
660 switch (fe_descriptor_id)
666 assign_elem_nodes[1]=0;
667 assign_elem_nodes[2]=1;
676 assign_elem_nodes[1]=0;
677 assign_elem_nodes[2]=2;
678 assign_elem_nodes[3]=1;
687 assign_elem_nodes[1]=0;
688 assign_elem_nodes[2]=5;
689 assign_elem_nodes[3]=2;
690 assign_elem_nodes[4]=4;
691 assign_elem_nodes[5]=1;
692 assign_elem_nodes[6]=3;
697 libmesh_error_msg(
"ERROR: UNV-element type 43: Plane Stress Cubic Triangle not supported.");
704 assign_elem_nodes[1]=0;
705 assign_elem_nodes[2]=3;
706 assign_elem_nodes[3]=2;
707 assign_elem_nodes[4]=1;
716 assign_elem_nodes[1]=0;
717 assign_elem_nodes[2]=7;
718 assign_elem_nodes[3]=3;
719 assign_elem_nodes[4]=6;
720 assign_elem_nodes[5]=2;
721 assign_elem_nodes[6]=5;
722 assign_elem_nodes[7]=1;
723 assign_elem_nodes[8]=4;
731 assign_elem_nodes[1]=0;
732 assign_elem_nodes[2]=7;
733 assign_elem_nodes[3]=3;
734 assign_elem_nodes[4]=6;
735 assign_elem_nodes[5]=2;
736 assign_elem_nodes[6]=5;
737 assign_elem_nodes[7]=1;
738 assign_elem_nodes[8]=4;
739 assign_elem_nodes[9]=8;
744 libmesh_error_msg(
"ERROR: UNV-element type 46: Plane Stress Cubic Quadrilateral not supported.");
750 assign_elem_nodes[1]=0;
751 assign_elem_nodes[2]=1;
752 assign_elem_nodes[3]=2;
753 assign_elem_nodes[4]=3;
761 assign_elem_nodes[1]=0;
762 assign_elem_nodes[2]=1;
763 assign_elem_nodes[3]=2;
764 assign_elem_nodes[4]=3;
765 assign_elem_nodes[5]=4;
766 assign_elem_nodes[6]=5;
774 assign_elem_nodes[1]=0;
775 assign_elem_nodes[2]=4;
776 assign_elem_nodes[3]=5;
777 assign_elem_nodes[4]=1;
778 assign_elem_nodes[5]=3;
779 assign_elem_nodes[6]=7;
780 assign_elem_nodes[7]=6;
781 assign_elem_nodes[8]=2;
789 assign_elem_nodes[1]=0;
790 assign_elem_nodes[2]=12;
791 assign_elem_nodes[3]=4;
792 assign_elem_nodes[4]=16;
793 assign_elem_nodes[5]=5;
794 assign_elem_nodes[6]=13;
795 assign_elem_nodes[7]=1;
796 assign_elem_nodes[8]=8;
798 assign_elem_nodes[9]=11;
799 assign_elem_nodes[10]=19;
800 assign_elem_nodes[11]=17;
801 assign_elem_nodes[12]=9;
803 assign_elem_nodes[13]=3;
804 assign_elem_nodes[14]=15;
805 assign_elem_nodes[15]=7;
806 assign_elem_nodes[16]=18;
807 assign_elem_nodes[17]=6;
808 assign_elem_nodes[18]=14;
809 assign_elem_nodes[19]=2;
810 assign_elem_nodes[20]=10;
815 libmesh_error_msg(
"Error: UNV-element type 117: Solid Cubic Brick not supported.");
821 assign_elem_nodes[1]=0;
822 assign_elem_nodes[2]=4;
823 assign_elem_nodes[3]=1;
824 assign_elem_nodes[4]=5;
825 assign_elem_nodes[5]=2;
826 assign_elem_nodes[6]=6;
827 assign_elem_nodes[7]=7;
828 assign_elem_nodes[8]=8;
829 assign_elem_nodes[9]=9;
830 assign_elem_nodes[10]=3;
835 libmesh_error_msg(
"ERROR: UNV-element type " << fe_descriptor_id <<
" not supported.");
845 elem->set_node(assign_elem_nodes[j], node_ptr);
882 exp_coord_sys_dummy = 0,
883 disp_coord_sys_dummy = 0,
890 out_file << std::scientific << std::setprecision(this->
ascii_precision()) << std::uppercase;
892 for (
const auto & current_node :
mesh.node_ptr_range())
896 out_file << std::setw(10) << node_id
897 << std::setw(10) << exp_coord_sys_dummy
898 << std::setw(10) << disp_coord_sys_dummy
899 << std::setw(10) << color_dummy
903 Real x = (*current_node)(0);
906 Real y = (*current_node)(1);
912 Real z = (*current_node)(2);
917 out_file << std::setw(25) << x
918 << std::setw(25) << y
919 << std::setw(25) << z
944 fe_descriptor_id = 0,
945 phys_prop_tab_dummy = 2,
946 mat_prop_tab_dummy = 1,
962 unsigned int assign_elem_nodes[20];
964 unsigned int n_elem_written=0;
969 for (
const auto & elem :
mesh.element_ptr_range())
971 switch (elem->type())
976 fe_descriptor_id = 41;
977 assign_elem_nodes[0] = 0;
978 assign_elem_nodes[1] = 2;
979 assign_elem_nodes[2] = 1;
985 fe_descriptor_id = 42;
986 assign_elem_nodes[0] = 0;
987 assign_elem_nodes[1] = 5;
988 assign_elem_nodes[2] = 2;
989 assign_elem_nodes[3] = 4;
990 assign_elem_nodes[4] = 1;
991 assign_elem_nodes[5] = 3;
997 fe_descriptor_id = 44;
998 assign_elem_nodes[0] = 0;
999 assign_elem_nodes[1] = 3;
1000 assign_elem_nodes[2] = 2;
1001 assign_elem_nodes[3] = 1;
1007 fe_descriptor_id = 45;
1008 assign_elem_nodes[0] = 0;
1009 assign_elem_nodes[1] = 7;
1010 assign_elem_nodes[2] = 3;
1011 assign_elem_nodes[3] = 6;
1012 assign_elem_nodes[4] = 2;
1013 assign_elem_nodes[5] = 5;
1014 assign_elem_nodes[6] = 1;
1015 assign_elem_nodes[7] = 4;
1021 fe_descriptor_id = 300;
1022 assign_elem_nodes[0] = 0;
1023 assign_elem_nodes[1] = 7;
1024 assign_elem_nodes[2] = 3;
1025 assign_elem_nodes[3] = 6;
1026 assign_elem_nodes[4] = 2;
1027 assign_elem_nodes[5] = 5;
1028 assign_elem_nodes[6] = 1;
1029 assign_elem_nodes[7] = 4;
1030 assign_elem_nodes[8] = 8;
1036 fe_descriptor_id = 111;
1037 assign_elem_nodes[0] = 0;
1038 assign_elem_nodes[1] = 1;
1039 assign_elem_nodes[2] = 2;
1040 assign_elem_nodes[3] = 3;
1046 fe_descriptor_id = 112;
1047 assign_elem_nodes[0] = 0;
1048 assign_elem_nodes[1] = 1;
1049 assign_elem_nodes[2] = 2;
1050 assign_elem_nodes[3] = 3;
1051 assign_elem_nodes[4] = 4;
1052 assign_elem_nodes[5] = 5;
1058 fe_descriptor_id = 115;
1059 assign_elem_nodes[0] = 0;
1060 assign_elem_nodes[1] = 4;
1061 assign_elem_nodes[2] = 5;
1062 assign_elem_nodes[3] = 1;
1063 assign_elem_nodes[4] = 3;
1064 assign_elem_nodes[5] = 7;
1065 assign_elem_nodes[6] = 6;
1066 assign_elem_nodes[7] = 2;
1072 fe_descriptor_id = 116;
1073 assign_elem_nodes[ 0] = 0;
1074 assign_elem_nodes[ 1] = 12;
1075 assign_elem_nodes[ 2] = 4;
1076 assign_elem_nodes[ 3] = 16;
1077 assign_elem_nodes[ 4] = 5;
1078 assign_elem_nodes[ 5] = 13;
1079 assign_elem_nodes[ 6] = 1;
1080 assign_elem_nodes[ 7] = 8;
1082 assign_elem_nodes[ 8] = 11;
1083 assign_elem_nodes[ 9] = 19;
1084 assign_elem_nodes[10] = 17;
1085 assign_elem_nodes[11] = 9;
1087 assign_elem_nodes[12] = 3;
1088 assign_elem_nodes[13] = 15;
1089 assign_elem_nodes[14] = 7;
1090 assign_elem_nodes[15] = 18;
1091 assign_elem_nodes[16] = 6;
1092 assign_elem_nodes[17] = 14;
1093 assign_elem_nodes[18] = 2;
1094 assign_elem_nodes[19] = 10;
1102 fe_descriptor_id = 118;
1103 assign_elem_nodes[0] = 0;
1104 assign_elem_nodes[1] = 4;
1105 assign_elem_nodes[2] = 1;
1106 assign_elem_nodes[3] = 5;
1107 assign_elem_nodes[4] = 2;
1108 assign_elem_nodes[5] = 6;
1109 assign_elem_nodes[6] = 7;
1110 assign_elem_nodes[7] = 8;
1111 assign_elem_nodes[8] = 9;
1112 assign_elem_nodes[9] = 3;
1117 libmesh_error_msg(
"ERROR: Element type = " <<
Utility::enum_to_string(elem->type()) <<
" not supported in " <<
"UNVIO!");
1122 out_file << std::setw(10) << elem_id
1123 << std::setw(10) << fe_descriptor_id
1124 << std::setw(10) << phys_prop_tab_dummy
1125 << std::setw(10) << mat_prop_tab_dummy
1126 << std::setw(10) << color_dummy
1127 << std::setw(10) << elem->n_nodes()
1130 for (
auto j : elem->node_index_range())
1135 const Node * node_in_unv_order = elem->node_ptr(assign_elem_nodes[j]);
1144 out_file << std::setw(10) << node_id;
1153 libMesh::out <<
" Finished writing " << n_elem_written <<
" elements" << std::endl;
1156 out_file <<
" -1\n";
1163 std::ifstream in_stream(file_name.c_str());
1165 libmesh_error_msg_if(!in_stream.good(),
"Error opening UNV data file.");
1167 std::string olds, news, dummy;
1171 in_stream >> olds >> news;
1174 while (((olds !=
"-1") || (news ==
"-1")) && !in_stream.eof())
1180 if (in_stream.eof())
1188 for (
unsigned int i=0; i<3; i++)
1189 std::getline(in_stream, dummy);
1195 unsigned int dataset_location;
1196 in_stream >> dataset_location;
1199 libmesh_error_msg_if(dataset_location != 1,
"ERROR: Currently only Data at nodes is supported.");
1202 for (
unsigned int i=0; i<6; i++)
1203 std::getline(in_stream, dummy);
1209 data_characteristic,
1217 unsigned int num_vals_per_node;
1219 in_stream >> model_type
1221 >> data_characteristic
1224 >> num_vals_per_node;
1227 for (
unsigned int i=0; i<5; i++)
1228 std::getline(in_stream, dummy);
1233 std::vector<Number> values;
1237 in_stream >> f_n_id;
1245 values.resize(num_vals_per_node);
1248 for (
unsigned int data_cnt=0; data_cnt<num_vals_per_node; data_cnt++)
1261 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1262 values[data_cnt] =
Complex(std::atof(buf.c_str()), 0.);
1264 values[data_cnt] = std::atof(buf.c_str());
1270 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1271 Real re_val, im_val;
1278 re_val = std::atof(buf.c_str());
1281 im_val = std::atof(buf.c_str());
1285 re_val = std::atof(buf.c_str());
1286 in_stream >> im_val;
1289 values[data_cnt] =
Complex(re_val,im_val);
1292 libmesh_error_msg(
"ERROR: Complex data only supported when libMesh is configured with --enable-complex!");
1297 libmesh_error_msg(
"ERROR: Data type not supported.");
1316 const std::vector<Number> *
1323 return &(it->second);
void write_implementation(std::ostream &out_stream)
The actual implementation of the write function.
bool _verbose
should be be verbose?
UNVIO(MeshBase &mesh)
Constructor.
A Node is like a Point, but with more information.
bool & verbose()
Set the flag indicating if we should be verbose.
std::map< dof_id_type, Node * > _unv_node_id_to_libmesh_node_ptr
Maps UNV node IDs to libMesh Node*s.
static const std::string _elements_dataset_label
label for the element dataset
void nodes_in(std::istream &in_file)
Read nodes from file.
void read_implementation(std::istream &in_stream)
The actual implementation of the read function.
void read_dataset(std::string file_name)
Read a UNV data file containing a dataset of type "2414".
This is the base class from which all geometric element types are derived.
std::map< Node *, std::vector< Number > > _node_data
Map from libMesh Node* to data at that node, as read in by the read_dataset() function.
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
This class defines an abstract interface for Mesh output.
unsigned char max_elem_dimension_seen()
The libMesh namespace provides an interface to certain functionality in the library.
void nodes_out(std::ostream &out_file)
Outputs nodes to the file out_file.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
static const std::string _groups_dataset_label
label for the groups dataset
void elements_out(std::ostream &out_file)
Outputs the element data to the file out_file.
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.
This is the MeshBase class.
virtual void write(const std::string &) override
This method implements writing a mesh to a specified file.
const dof_id_type n_nodes
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
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)
virtual dof_id_type key(const unsigned int s) const =0
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
std::string & subdomain_name(subdomain_id_type id)
std::map< unsigned, unsigned > _unv_elem_id_to_libmesh_elem_id
Map UNV element IDs to libmesh element IDs.
std::string & sideset_name(boundary_id_type id)
std::string enum_to_string(const T e)
virtual const Elem * elem_ptr(const dof_id_type i) const =0
std::complex< Real > Complex
bool need_D_to_e(std::string &number)
Replaces "1.1111D+00" with "1.1111e+00" if necessary.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
virtual unsigned short dim() const =0
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...
const std::vector< Number > * get_data(Node *node) const
virtual ~UNVIO()
Destructor.
static const std::string _nodes_dataset_label
label for the node dataset
virtual void read(const std::string &) override
This method implements reading a mesh from a specified file.
A Point defines a location in LIBMESH_DIM dimensional Real space.
void elements_in(std::istream &in_file)
Method reads elements and stores them in std::vector<Elem *> _elements in the same order as they come...
void groups_in(std::istream &in_file)
Reads the "groups" section of the file.