23 #include <unordered_map> 68 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,8,11,12,9,13,10,14,15,16,19,17,18};
69 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).
swap(eledef.
nodes);
76 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,8,11,12,9,13,10,14,
77 15,16,19,17,18,20,21,24,22,23,25,26};
78 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).
swap(eledef.
nodes);
85 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,9,8};
86 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).
swap(eledef.
nodes);
93 const unsigned int nodes[] = {0,1,2,3,4,5,6,8,9,7,10,11,12,14,13};
94 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).
swap(eledef.
nodes);
101 const unsigned int nodes[] = {0,1,2,3,4,5,6,8,9,7,10,11,12,14,13,15,17,16};
102 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).
swap(eledef.
nodes);
114 _write_lower_dimensional_elements(true)
124 _write_lower_dimensional_elements(true)
146 std::ifstream in (
name.c_str());
159 libmesh_assert(in.good());
166 int format=0, size=0;
171 std::set<subdomain_id_type> lower_dimensional_blocks;
179 typedef std::pair<unsigned, std::string> GmshPhysical;
180 std::map<int, GmshPhysical> gmsh_physicals;
184 std::map<unsigned int, unsigned int> nodetrans;
198 if (s.find(
"$MeshFormat") ==
static_cast<std::string::size_type
>(0))
200 in >> version >> format >> size;
201 if ((version != 2.0) && (version != 2.1) && (version != 2.2))
216 libmesh_error_msg(
"Error: Unknown msh file version " << version);
220 libmesh_error_msg(
"Error: Unknown data format for mesh in Gmsh reader.");
224 else if (s.find(
"$PhysicalNames") ==
static_cast<std::string::size_type
>(0))
233 unsigned int num_physical_groups = 0;
234 in >> num_physical_groups;
239 for (
unsigned int i=0; i<num_physical_groups; ++i)
247 std::istringstream s_stream(s);
250 std::string phys_name;
251 s_stream >> phys_dim >> phys_id >> phys_name;
256 phys_name.erase(std::remove(phys_name.begin(), phys_name.end(),
'"'), phys_name.end());
259 gmsh_physicals[phys_id] = std::make_pair(phys_dim, phys_name);
265 if (s.find(
"lower_dimensional_block") != std::string::npos)
267 lower_dimensional_blocks.insert(cast_int<subdomain_id_type>(phys_id));
278 else if (s.find(
"$NOD") ==
static_cast<std::string::size_type
>(0) ||
279 s.find(
"$NOE") ==
static_cast<std::string::size_type
>(0) ||
280 s.find(
"$Nodes") ==
static_cast<std::string::size_type
>(0))
282 unsigned int num_nodes = 0;
291 for (
unsigned int i=0; i<num_nodes; ++i)
293 in >>
id >> x >> y >> z;
304 else if (s.find(
"$ELM") ==
static_cast<std::string::size_type
>(0) ||
305 s.find(
"$Elements") ==
static_cast<std::string::size_type
>(0))
332 std::vector<unsigned> elem_dimensions_seen(3);
335 for (
unsigned int iel=0; iel<num_elem; ++iel)
339 physical=1, elementary=1,
347 in >>
id >> type >> physical >> elementary >> nnodes;
351 in >>
id >> type >> ntags;
354 libmesh_do_once(
libMesh::err <<
"Warning, ntags=" << ntags <<
", but we currently only support reading 2 flags." << std::endl;);
356 for (
unsigned int j = 0; j < ntags; j++)
371 libmesh_error_msg(
"Element type " << type <<
" not found!");
377 if (nnodes != 0 && nnodes != eletype.
nnodes)
378 libmesh_error_msg(
"nnodes = " << nnodes <<
" and eletype.nnodes = " << eletype.
nnodes <<
" do not match.");
393 elem_dimensions_seen[eletype.
dim-1] = 1;
403 libmesh_error_msg(
"Number of nodes for element " \
405 <<
" of type " << eletype.
type \
406 <<
" (Gmsh type " << type \
407 <<
") does not match Libmesh definition. " \
408 <<
"I expected " << elem->
n_nodes() \
409 <<
" nodes, but got " << nnodes);
413 if (eletype.
nodes.size() > 0)
414 for (
unsigned int i=0; i<nnodes; i++)
421 for (
unsigned int i=0; i<nnodes; i++)
446 static_cast<boundary_id_type>(physical));
455 max_elem_dimension_seen=1,
456 min_elem_dimension_seen=3;
458 for (std::size_t i=0; i<elem_dimensions_seen.size(); ++i)
459 if (elem_dimensions_seen[i])
463 max_elem_dimension_seen =
464 std::max(max_elem_dimension_seen, cast_int<unsigned char>(i+1));
465 min_elem_dimension_seen =
466 std::min(min_elem_dimension_seen, cast_int<unsigned char>(i+1));
475 if (max_elem_dimension_seen - min_elem_dimension_seen > 1)
476 libmesh_error_msg(
"Cannot handle meshes with dimension mismatch greater than 1.");
479 unsigned n_dims_seen = std::accumulate(elem_dimensions_seen.begin(),
480 elem_dimensions_seen.end(),
481 static_cast<unsigned>(0),
482 std::plus<unsigned>());
486 if (n_dims_seen == 3)
487 libmesh_error_msg(
"Reading meshes with 1, 2, and 3D elements not currently supported.");
495 for (
const auto & pr : gmsh_physicals)
498 int phys_id = pr.first;
499 unsigned phys_dim = pr.second.first;
500 const std::string & phys_name = pr.second.second;
504 if (phys_dim == max_elem_dimension_seen)
509 else if (phys_dim < max_elem_dimension_seen &&
510 !lower_dimensional_blocks.count(cast_int<boundary_id_type>(phys_id)))
528 typedef std::unordered_multimap<dof_id_type, Elem *> provide_container_t;
529 provide_container_t provide_bcs;
533 if (elem->dim() < max_elem_dimension_seen &&
534 !lower_dimensional_blocks.count(elem->subdomain_id()))
542 for (
auto n : elem->node_index_range())
544 elem->subdomain_id());
549 provide_bcs.insert(std::make_pair(elem->key(), elem));
554 if (elem->dim() == max_elem_dimension_seen)
564 for (
auto sn : elem->side_index_range())
565 for (
const auto & pr :
as_range(provide_bcs.equal_range(elem->key(sn))))
569 std::unique_ptr<Elem>
side (elem->build_side_ptr(sn));
572 Elem * lower_dim_elem = pr.second;
575 if (*lower_dim_elem == *
side)
581 boundary_id_type bid = cast_int<boundary_id_type>(lower_dim_elem->subdomain_id());
589 if (elem->dim() < max_elem_dimension_seen &&
590 !lower_dimensional_blocks.count(elem->subdomain_id()))
605 libmesh_error_msg(
"Stream is bad! Perhaps the file does not exist?");
617 std::ofstream out_stream (
name.c_str());
620 if (!out_stream.good())
621 libmesh_file_error(
name.c_str());
630 const std::vector<Number> & soln,
631 const std::vector<std::string> & names)
633 LOG_SCOPE(
"write_nodal_data()",
"GmshIO");
644 libmesh_assert (out_stream.good());
651 std::size_t n_boundary_faces = 0;
658 out_stream <<
"$MeshFormat\n";
659 out_stream <<
"2.0 0 " <<
sizeof(
Real) <<
'\n';
660 out_stream <<
"$EndMeshFormat\n";
663 out_stream <<
"$Nodes\n";
671 out_stream <<
"$EndNodes\n";
675 out_stream <<
"$Elements\n";
690 libmesh_error_msg(
"Element type " << elem->type() <<
" not found in _element_maps.");
697 libmesh_assert_less_equal (eletype.
nodes.size(), elem->n_nodes());
700 out_stream << elem->id()+1 <<
" ";
709 <<
static_cast<unsigned int>(elem->subdomain_id())
711 << elem->processor_id()+1
715 if (eletype.
nodes.size() > 0)
716 for (
auto i : elem->node_index_range())
717 out_stream << elem->node_id(eletype.
nodes[i])+1 <<
" ";
720 for (
auto i : elem->node_index_range())
721 out_stream << elem->node_id(i)+1 <<
" ";
737 if (n_boundary_faces)
743 for (
const auto & t : bc_triples)
754 libmesh_error_msg(
"Element type " <<
side->type() <<
" not found in _element_maps.");
761 libmesh_assert_less_equal (eletype.
nodes.size(),
side->n_nodes());
764 out_stream << e_id+1 <<
" ";
780 if (eletype.
nodes.size() > 0)
781 for (
auto i :
side->node_index_range())
782 out_stream <<
side->node_id(eletype.
nodes[i])+1 <<
" ";
786 for (
auto i :
side->node_index_range())
787 out_stream <<
side->node_id(i)+1 <<
" ";
797 out_stream <<
"$EndElements\n";
804 const std::vector<Number> * v,
805 const std::vector<std::string> * solution_names)
812 std::ofstream out_stream(fname.c_str());
815 if (!out_stream.good())
816 libmesh_file_error(fname.c_str());
825 if ((solution_names !=
nullptr) && (v !=
nullptr))
827 const unsigned int n_vars =
828 cast_int<unsigned int>(solution_names->size());
840 out_stream <<
"$PostFormat\n";
842 out_stream <<
"1.2 1 " <<
sizeof(
double) <<
"\n";
844 out_stream <<
"1.2 0 " <<
sizeof(double) <<
"\n";
845 out_stream <<
"$EndPostFormat\n";
848 unsigned int n_points=0, n_lines=0, n_triangles=0, n_quadrangles=0,
849 n_tetrahedra=0, n_hexahedra=0, n_prisms=0, n_pyramids=0;
850 unsigned int n_scalar=0, n_vector=0, n_tensor=0;
851 unsigned int nb_text2d=0, nb_text2d_chars=0, nb_text3d=0, nb_text3d_chars=0;
856 const ElemType elemtype = elem->type();
906 libmesh_error_msg(
"ERROR: Nonexistent element type " << elem->type());
912 for (
unsigned int ivar=0; ivar <
n_vars; ivar++)
914 std::string varname = (*solution_names)[ivar];
922 out_stream <<
"$View\n" << varname <<
" " << 1 <<
"\n";
925 out_stream << n_points * n_scalar <<
" " 926 << n_points * n_vector <<
" " 927 << n_points * n_tensor <<
" " 928 << n_lines * n_scalar <<
" " 929 << n_lines * n_vector <<
" " 930 << n_lines * n_tensor <<
" " 931 << n_triangles * n_scalar <<
" " 932 << n_triangles * n_vector <<
" " 933 << n_triangles * n_tensor <<
" " 934 << n_quadrangles * n_scalar <<
" " 935 << n_quadrangles * n_vector <<
" " 936 << n_quadrangles * n_tensor <<
" " 937 << n_tetrahedra * n_scalar <<
" " 938 << n_tetrahedra * n_vector <<
" " 939 << n_tetrahedra * n_tensor <<
" " 940 << n_hexahedra * n_scalar <<
" " 941 << n_hexahedra * n_vector <<
" " 942 << n_hexahedra * n_tensor <<
" " 943 << n_prisms * n_scalar <<
" " 944 << n_prisms * n_vector <<
" " 945 << n_prisms * n_tensor <<
" " 946 << n_pyramids * n_scalar <<
" " 947 << n_pyramids * n_vector <<
" " 948 << n_pyramids * n_tensor <<
" " 950 << nb_text2d_chars <<
" " 952 << nb_text3d_chars <<
"\n";
958 std::memcpy(buf, &one,
sizeof(
int));
959 out_stream.write(buf,
sizeof(
int));
966 std::memcpy(buf, &one,
sizeof(
double));
967 out_stream.write(buf,
sizeof(
double));
976 for (
unsigned int d=0; d<3; d++)
978 for (
unsigned int n=0; n < elem->n_vertices(); n++)
980 const Point & vertex = elem->point(n);
983 double tmp = vertex(d);
984 std::memcpy(buf, &tmp,
sizeof(
double));
985 out_stream.write(reinterpret_cast<char *>(buf),
sizeof(
double));
988 out_stream << vertex(d) <<
" ";
995 for (
unsigned int i=0; i < elem->n_vertices(); i++)
998 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 999 libMesh::out <<
"WARNING: Gmsh::write_post does not fully support " 1000 <<
"complex numbers. Will only write the real part of " 1001 <<
"variable " << varname << std::endl;
1004 std::memcpy(buf, &tmp,
sizeof(
double));
1005 out_stream.write(reinterpret_cast<char *>(buf),
sizeof(
double));
1009 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 1010 libMesh::out <<
"WARNING: Gmsh::write_post does not fully support " 1011 <<
"complex numbers. Will only write the real part of " 1012 <<
"variable " << varname << std::endl;
1019 out_stream <<
"$EndView\n";
std::string name(const ElemQuality q)
std::size_t n_boundary_conds() const
virtual void reserve_nodes(const dof_id_type nn)=0
virtual void write(const std::string &name) override
virtual dof_id_type n_active_elem() const =0
virtual Node *& set_node(const unsigned int i)
bool & write_lower_dimensional_elements()
The base class for all geometric element types.
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
const unsigned int n_vars
const BoundaryInfo & get_boundary_info() const
std::map< unsigned int, ElementDefinition > in
long double max(long double a, double b)
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
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
std::map< ElemType, ElementDefinition > out
void add_node(const Node *node, const boundary_id_type id)
virtual void delete_elem(Elem *e)=0
virtual unsigned int n_nodes() const =0
virtual Elem * add_elem(Elem *e)=0
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
virtual dof_id_type max_elem_id() const =0
SimpleRange< I > as_range(const std::pair< I, I > &p)
void write_mesh(std::ostream &out)
std::string & subdomain_name(subdomain_id_type id)
OStreamProxy err(std::cerr)
void set_mesh_dimension(unsigned char d)
bool _write_lower_dimensional_elements
std::string & sideset_name(boundary_id_type id)
static ElementMaps build_element_maps()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
void swap(Iterator &lhs, Iterator &rhs)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
virtual const Elem & elem_ref(const dof_id_type i) const
static ElementMaps _element_maps
virtual const Node & node_ref(const dof_id_type i) const
void add_def(const ElementDefinition &eledef)
virtual void read(const std::string &name) override
virtual const Node * node_ptr(const dof_id_type i) const =0
OStreamProxy out(std::cout)
void write_post(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
processor_id_type processor_id() const
long double min(long double a, double b)
A geometric point in (x,y,z) space.
virtual void reserve_elem(const dof_id_type ne)=0
virtual dof_id_type n_nodes() const =0
void read_mesh(std::istream &in)
std::vector< unsigned int > nodes