73 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,8,11,12,9,13,10,14,15,16,19,17,18};
74 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).swap(eledef.
nodes);
81 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,8,11,12,9,13,10,14,
82 15,16,19,17,18,20,21,24,22,23,25,26};
83 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).swap(eledef.
nodes);
90 const unsigned int nodes[] = {0,1,2,3,4,5,6,7,9,8};
91 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).swap(eledef.
nodes);
98 const unsigned int nodes[] = {0,1,2,3,4,5,6,8,9,7,10,11,12,14,13};
99 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).swap(eledef.
nodes);
106 const unsigned int nodes[] = {0,1,2,3,4,5,6,8,9,7,10,11,12,14,13,15,17,16};
107 std::vector<unsigned int>(nodes, nodes+eledef.
nnodes).swap(eledef.
nodes);
171 int format=0, size=0;
176 std::set<subdomain_id_type> lower_dimensional_blocks;
184 std::map<std::pair<std::ptrdiff_t, unsigned>, std::string> gmsh_physicals;
188 std::map<unsigned int, unsigned int> nodetrans;
193 std::map<std::pair<unsigned, int>,
int> entity_to_physical_id;
196 std::map<std::pair<unsigned, int>,
BoundingBox> entity_to_bounding_box;
210 if (s.find(
"$MeshFormat") ==
static_cast<std::string::size_type
>(0))
212 in >> version >> format >> size;
229 libmesh_error_msg_if(version < 2.0,
"Error: Unknown msh file version " << version);
230 libmesh_error_msg_if(format,
"Error: Unknown data format for mesh in Gmsh reader.");
234 else if (s.find(
"$PhysicalNames") ==
static_cast<std::string::size_type
>(0))
243 unsigned int num_physical_groups = 0;
244 in >> num_physical_groups;
249 for (
unsigned int i=0; i<num_physical_groups; ++i)
257 std::istringstream s_stream(s);
260 std::string phys_name;
261 s_stream >> phys_dim >> phys_id >> phys_name;
266 phys_name.erase(std::remove(phys_name.begin(), phys_name.end(),
'"'), phys_name.end());
269 gmsh_physicals[std::make_pair(phys_id, phys_dim)] = phys_name;
275 if (s.find(
"lower_dimensional_block") != std::string::npos)
277 lower_dimensional_blocks.insert(restrict_int<subdomain_id_type>(phys_id));
287 else if (s.find(
"$Entities") ==
static_cast<std::string::size_type
>(0))
291 std::size_t num_point_entities, num_curve_entities, num_surface_entities, num_volume_entities;
292 in >> num_point_entities >> num_curve_entities >> num_surface_entities >> num_volume_entities;
294 for (std::size_t n = 0; n < num_point_entities; ++n)
296 int point_tag, physical_tag;
298 std::size_t num_physical_tags;
299 in >> point_tag >> x >> y >> z >> num_physical_tags;
301 libmesh_error_msg_if(num_physical_tags > 1,
302 "Sorry, you cannot currently specify multiple subdomain or "
303 "boundary ids for a given geometric entity");
305 entity_to_bounding_box[std::make_pair(0, point_tag)] =
308 if (num_physical_tags)
311 entity_to_physical_id[std::make_pair(0, point_tag)] = physical_tag;
314 for (std::size_t n = 0; n < num_curve_entities; ++n)
316 int curve_tag, physical_tag;
317 Real minx, miny, minz, maxx, maxy, maxz;
318 std::size_t num_physical_tags;
319 in >> curve_tag >> minx >> miny >> minz >> maxx >> maxy >> maxz >> num_physical_tags;
321 libmesh_error_msg_if(num_physical_tags > 1,
322 "I don't believe that we can specify multiple subdomain or "
323 "boundary ids for a given geometric entity");
325 entity_to_bounding_box[std::make_pair(1, curve_tag)] =
328 if (num_physical_tags)
331 entity_to_physical_id[std::make_pair(1, curve_tag)] = physical_tag;
337 for (std::size_t n = 0; n < num_surface_entities; ++n)
339 int surface_tag, physical_tag;
340 Real minx, miny, minz, maxx, maxy, maxz;
341 std::size_t num_physical_tags;
342 in >> surface_tag >> minx >> miny >> minz >> maxx >> maxy >> maxz >> num_physical_tags;
344 libmesh_error_msg_if(num_physical_tags > 1,
345 "I don't believe that we can specify multiple subdomain or "
346 "boundary ids for a given geometric entity");
348 entity_to_bounding_box[std::make_pair(2, surface_tag)] =
351 if (num_physical_tags)
354 entity_to_physical_id[std::make_pair(2, surface_tag)] = physical_tag;
360 for (std::size_t n = 0; n < num_volume_entities; ++n)
362 int volume_tag, physical_tag;
363 Real minx, miny, minz, maxx, maxy, maxz;
364 std::size_t num_physical_tags;
365 in >> volume_tag >> minx >> miny >> minz >> maxx >> maxy >> maxz >> num_physical_tags;
367 libmesh_error_msg_if(num_physical_tags > 1,
368 "I don't believe that we can specify multiple subdomain or "
369 "boundary ids for a given geometric entity");
371 entity_to_bounding_box[std::make_pair(3, volume_tag)] =
374 if (num_physical_tags)
377 entity_to_physical_id[std::make_pair(3, volume_tag)] = physical_tag;
388 libmesh_error_msg(
"The Entities block was introduced in mesh version 4.0");
392 else if (s.find(
"$NOD") ==
static_cast<std::string::size_type
>(0) ||
393 s.find(
"$NOE") ==
static_cast<std::string::size_type
>(0) ||
394 s.find(
"$Nodes") ==
static_cast<std::string::size_type
>(0))
398 unsigned int num_nodes = 0;
407 for (
unsigned int i=0; i<num_nodes; ++i)
409 in >>
id >> x >> y >> z;
417 std::size_t num_entities = 0, num_nodes = 0, min_node_tag, max_node_tag;
418 in >> num_entities >> num_nodes >> min_node_tag >> max_node_tag;
422 std::size_t node_counter = 0;
425 for (std::size_t i = 0; i < num_entities; ++i)
427 int entity_dim, entity_tag, parametric;
428 std::size_t num_nodes_in_block = 0;
429 in >> entity_dim >> entity_tag >> parametric >> num_nodes_in_block;
430 libmesh_error_msg_if(parametric,
"We don't currently support reading parametric gmsh entities");
434 for (std::size_t n = 0; n < num_nodes_in_block; ++n)
438 nodetrans[gmsh_id] = node_counter++;
443 for (std::size_t libmesh_id = node_counter - num_nodes_in_block;
444 libmesh_id < node_counter;
457 else if (s.find(
"$ELM") ==
static_cast<std::string::size_type
>(0) ||
458 s.find(
"$Elements") ==
static_cast<std::string::size_type
>(0))
461 std::vector<unsigned> elem_dimensions_seen(3);
490 for (
unsigned int iel=0; iel<num_elem; ++iel)
494 physical=1, elementary=1,
502 in >>
id >> type >> physical >> elementary >> nnodes;
506 in >>
id >> type >> ntags;
509 libmesh_do_once(
libMesh::err <<
"Warning, ntags=" << ntags <<
", but we currently only support reading 2 flags." << std::endl;);
511 for (
unsigned int j = 0; j < ntags; j++)
526 libmesh_error_msg_if(nnodes != 0 && nnodes != eletype.
nnodes,
527 "nnodes = " << nnodes <<
" and eletype.nnodes = " << eletype.
nnodes <<
" do not match.");
542 elem_dimensions_seen[eletype.
dim-1] = 1;
550 libmesh_error_msg_if(elem->
n_nodes() != nnodes,
551 "Number of nodes for element "
553 <<
" of type " << eletype.
type
554 <<
" (Gmsh type " << type
555 <<
") does not match Libmesh definition. "
556 <<
"I expected " << elem->
n_nodes()
557 <<
" nodes, but got " << nnodes);
561 if (eletype.
nodes.size() > 0)
562 for (
unsigned int i=0; i<nnodes; i++)
569 for (
unsigned int i=0; i<nnodes; i++)
601 std::size_t num_entity_blocks = 0, num_elem = 0, min_element_tag, max_element_tag;
604 in >> num_entity_blocks >> num_elem >> min_element_tag >> max_element_tag;
611 for (std::size_t i = 0; i < num_entity_blocks; ++i)
613 int entity_dim, entity_tag;
614 unsigned int element_type;
615 std::size_t num_elems_in_block = 0;
616 in >> entity_dim >> entity_tag >> element_type >> num_elems_in_block;
632 elem_dimensions_seen[eletype.
dim-1] = 1;
635 for (std::size_t n = 0; n < num_elems_in_block; ++n)
640 std::size_t gmsh_element_id;
641 in >> gmsh_element_id;
649 std::swap(expected_bounding_box.
min(),
650 expected_bounding_box.
max());
652 if (
auto it = entity_to_bounding_box.find
653 (std::make_pair(entity_dim, entity_tag));
654 it != entity_to_bounding_box.end())
655 expected_bounding_box = it->second;
659 std::istringstream
is(s);
660 std::size_t local_node_counter = 0, gmsh_node_id;
661 while (
is >> gmsh_node_id)
672 "$Elements dim " << entity_dim <<
" element "
673 << gmsh_element_id <<
" (entity " << entity_tag
676 ") has node at " << *
static_cast<Node*
>(node)
677 <<
"\n outside entity physical bounding box " <<
678 expected_bounding_box);
682 if (eletype.
nodes.size() > 0)
686 elem->
set_node(local_node_counter++, node);
690 libmesh_error_msg_if(elem->
n_nodes() != local_node_counter,
691 "Number of nodes for element "
693 <<
" of type " << eletype.
type
694 <<
" (Gmsh type " << element_type
695 <<
") does not match Libmesh definition. "
696 <<
"I expected " << elem->
n_nodes()
697 <<
" nodes, but got " << local_node_counter);
702 entity_to_physical_id[std::make_pair(entity_dim, entity_tag)]);
709 for (std::size_t n = 0; n < num_elems_in_block; ++n)
711 std::size_t gmsh_element_id, gmsh_node_id;
712 in >> gmsh_element_id;
721 std::swap(expected_bounding_box.
min(),
722 expected_bounding_box.
max());
724 if (
auto it = entity_to_bounding_box.find
725 (std::make_pair(entity_dim, entity_tag));
726 it != entity_to_bounding_box.end())
727 expected_bounding_box = it->second;
737 "$Elements dim " << entity_dim <<
" element "
738 << gmsh_element_id <<
" (entity " << entity_tag <<
739 ") has node at " << *
static_cast<Node*
>(node)
740 <<
"\n outside entity physical bounding box " <<
741 expected_bounding_box);
746 std::make_pair(entity_dim, entity_tag)]));
757 max_elem_dimension_seen=1,
758 min_elem_dimension_seen=3;
761 if (elem_dimensions_seen[i])
765 max_elem_dimension_seen =
766 std::max(max_elem_dimension_seen, cast_int<unsigned char>(i+1));
767 min_elem_dimension_seen =
768 std::min(min_elem_dimension_seen, cast_int<unsigned char>(i+1));
777 unsigned n_dims_seen = std::accumulate(elem_dimensions_seen.begin(),
778 elem_dimensions_seen.end(),
779 static_cast<unsigned>(0),
780 std::plus<unsigned>());
789 for (
const auto & pr : gmsh_physicals)
792 auto [phys_id, phys_dim] = pr.first;
793 const std::string & phys_name = pr.second;
797 if (phys_dim == max_elem_dimension_seen)
801 else if (phys_dim == 0)
806 else if (phys_dim < max_elem_dimension_seen &&
807 !lower_dimensional_blocks.count(cast_int<boundary_id_type>(phys_id)))
825 typedef std::unordered_multimap<dof_id_type, Elem *> provide_container_t;
826 provide_container_t provide_bcs;
829 for (
auto & elem :
mesh.active_element_ptr_range())
830 if (elem->dim() < max_elem_dimension_seen &&
831 !lower_dimensional_blocks.count(elem->subdomain_id()))
839 for (
auto n : elem->node_index_range())
841 elem->subdomain_id());
846 provide_bcs.emplace(elem->key(), elem);
850 for (
auto & elem :
mesh.active_element_ptr_range())
851 if (elem->dim() == max_elem_dimension_seen)
861 for (
auto sn : elem->side_index_range())
862 for (
const auto & pr :
as_range(provide_bcs.equal_range(elem->key(sn))))
866 std::unique_ptr<Elem> side (elem->build_side_ptr(sn));
869 Elem * lower_dim_elem = pr.second;
872 if (*lower_dim_elem == *side)
885 for (
auto & elem :
mesh.active_element_ptr_range())
886 if (elem->dim() < max_elem_dimension_seen &&
887 !lower_dimensional_blocks.count(elem->subdomain_id()))
902 libmesh_error_msg(
"Stream is bad! Perhaps the file does not exist?");
1085 const std::vector<Number> * v,
1086 const std::vector<std::string> * solution_names)
1093 std::ofstream out_stream(fname.c_str());
1096 if (!out_stream.good())
1097 libmesh_file_error(fname.c_str());
1106 if ((solution_names !=
nullptr) && (v !=
nullptr))
1108 const unsigned int n_vars =
1109 cast_int<unsigned int>(solution_names->size());
1121 out_stream <<
"$PostFormat\n";
1123 out_stream <<
"1.2 1 " <<
sizeof(double) <<
"\n";
1125 out_stream <<
"1.2 0 " <<
sizeof(double) <<
"\n";
1126 out_stream <<
"$EndPostFormat\n";
1129 unsigned int n_points=0, n_lines=0, n_triangles=0, n_quadrangles=0,
1130 n_tetrahedra=0, n_hexahedra=0, n_prisms=0, n_pyramids=0;
1131 unsigned int n_scalar=0, n_vector=0, n_tensor=0;
1132 unsigned int nb_text2d=0, nb_text2d_chars=0, nb_text3d=0, nb_text3d_chars=0;
1135 for (
const auto & elem :
mesh.active_element_ptr_range())
1137 const ElemType elemtype = elem->type();
1193 for (
unsigned int ivar=0; ivar <
n_vars; ivar++)
1195 std::string varname = (*solution_names)[ivar];
1203 out_stream <<
"$View\n" << varname <<
" " << 1 <<
"\n";
1206 out_stream << n_points * n_scalar <<
" "
1207 << n_points * n_vector <<
" "
1208 << n_points * n_tensor <<
" "
1209 << n_lines * n_scalar <<
" "
1210 << n_lines * n_vector <<
" "
1211 << n_lines * n_tensor <<
" "
1212 << n_triangles * n_scalar <<
" "
1213 << n_triangles * n_vector <<
" "
1214 << n_triangles * n_tensor <<
" "
1215 << n_quadrangles * n_scalar <<
" "
1216 << n_quadrangles * n_vector <<
" "
1217 << n_quadrangles * n_tensor <<
" "
1218 << n_tetrahedra * n_scalar <<
" "
1219 << n_tetrahedra * n_vector <<
" "
1220 << n_tetrahedra * n_tensor <<
" "
1221 << n_hexahedra * n_scalar <<
" "
1222 << n_hexahedra * n_vector <<
" "
1223 << n_hexahedra * n_tensor <<
" "
1224 << n_prisms * n_scalar <<
" "
1225 << n_prisms * n_vector <<
" "
1226 << n_prisms * n_tensor <<
" "
1227 << n_pyramids * n_scalar <<
" "
1228 << n_pyramids * n_vector <<
" "
1229 << n_pyramids * n_tensor <<
" "
1231 << nb_text2d_chars <<
" "
1233 << nb_text3d_chars <<
"\n";
1239 std::memcpy(buf, &one,
sizeof(
int));
1240 out_stream.write(buf,
sizeof(
int));
1247 std::memcpy(buf, &one,
sizeof(
double));
1248 out_stream.write(buf,
sizeof(
double));
1251 out_stream <<
"1\n";
1254 for (
const auto & elem :
mesh.active_element_ptr_range())
1256 const unsigned int nv = elem->n_vertices();
1258 for (
unsigned int d=0; d<3; d++)
1260 for (
unsigned int n=0; n < nv; n++)
1262 const Point & vertex = elem->point(n);
1265#if defined(LIBMESH_DEFAULT_TRIPLE_PRECISION) || defined(LIBMESH_DEFAULT_QUADRUPLE_PRECISION)
1266 libmesh_warning(
"Gmsh binary writes use only double precision!");
1268 double tmp = double(vertex(d));
1269 std::memcpy(buf, &tmp,
sizeof(
double));
1270 out_stream.write(
reinterpret_cast<char *
>(buf),
sizeof(
double));
1273 out_stream << vertex(d) <<
" ";
1280 for (
unsigned int i=0; i < nv; i++)
1283#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1284 libMesh::out <<
"WARNING: Gmsh::write_post does not fully support "
1285 <<
"complex numbers. Will only write the real part of "
1286 <<
"variable " << varname << std::endl;
1289 std::memcpy(buf, &tmp,
sizeof(
double));
1290 out_stream.write(
reinterpret_cast<char *
>(buf),
sizeof(
double));
1294#ifdef LIBMESH_USE_COMPLEX_NUMBERS
1295 libMesh::out <<
"WARNING: Gmsh::write_post does not fully support "
1296 <<
"complex numbers. Will only write the real part of "
1297 <<
"variable " << varname << std::endl;
1304 out_stream <<
"$EndView\n";