19 #include "libmesh/libmesh_config.h" 20 #include "libmesh/libmesh_logging.h" 21 #include "libmesh/boundary_info.h" 22 #include "libmesh/bounding_box.h" 23 #include "libmesh/elem.h" 24 #include "libmesh/gmsh_io.h" 25 #include "libmesh/mesh_base.h" 26 #include "libmesh/int_range.h" 27 #include "libmesh/utility.h" 28 #include "libmesh/enum_to_string.h" 35 #include <unordered_map> 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);
119 _write_lower_dimensional_elements(true)
129 _write_lower_dimensional_elements(true)
151 std::ifstream in (
name.c_str());
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(cast_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++)
594 static_cast<boundary_id_type>(physical));
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);
745 static_cast<boundary_id_type>(entity_to_physical_id[
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)
878 boundary_id_type bid = cast_int<boundary_id_type>(lower_dim_elem->subdomain_id());
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?");
914 std::ofstream out_stream (
name.c_str());
917 if (!out_stream.good())
918 libmesh_file_error(
name.c_str());
927 const std::vector<Number> & soln,
928 const std::vector<std::string> & names)
930 LOG_SCOPE(
"write_nodal_data()",
"GmshIO");
948 std::size_t n_boundary_faces = 0;
955 out_stream <<
"$MeshFormat\n";
956 out_stream <<
"2.0 0 " <<
sizeof(
Real) <<
'\n';
957 out_stream <<
"$EndMeshFormat\n";
960 out_stream <<
"$Nodes\n";
968 out_stream <<
"$EndNodes\n";
972 out_stream <<
"$Elements\n";
976 for (
const auto & elem :
mesh.active_element_ptr_range())
984 libmesh_assert_less_equal (eletype.
nodes.size(), elem->n_nodes());
987 out_stream << elem->id()+1 <<
" ";
996 <<
static_cast<unsigned int>(elem->subdomain_id())
998 << elem->processor_id()+1
1002 if (eletype.
nodes.size() > 0)
1003 for (
auto i : elem->node_index_range())
1004 out_stream << elem->node_id(eletype.
nodes[i])+1 <<
" ";
1007 for (
auto i : elem->node_index_range())
1008 out_stream << elem->node_id(i)+1 <<
" ";
1024 if (n_boundary_faces)
1030 for (
const auto & t : bc_triples)
1034 std::unique_ptr<const Elem> side = elem.
build_side_ptr(std::get<1>(t));
1042 libmesh_assert_less_equal (eletype.
nodes.size(), side->n_nodes());
1045 out_stream << e_id+1 <<
" ";
1061 if (eletype.
nodes.size() > 0)
1062 for (
auto i : side->node_index_range())
1063 out_stream << side->node_id(eletype.
nodes[i])+1 <<
" ";
1067 for (
auto i : side->node_index_range())
1068 out_stream << side->node_id(i)+1 <<
" ";
1078 out_stream <<
"$EndElements\n";
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";
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
std::size_t n_boundary_conds() const
ElemType
Defines an enum for geometric element types.
virtual void reserve_nodes(const dof_id_type nn)=0
Reserves space for a known number of nodes.
bool _binary
Flag to write binary data.
virtual void write(const std::string &name) override
This method implements writing a mesh to a specified file in the Gmsh *.msh format.
virtual dof_id_type n_active_elem() const =0
virtual Node *& set_node(const unsigned int i)
A Node is like a Point, but with more information.
std::string & nodeset_name(boundary_id_type id)
bool contains_point(const Point &) const
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
static constexpr Real TOLERANCE
bool & write_lower_dimensional_elements()
Access to the flag which controls whether boundary elements are written to the Mesh file...
This is the base class from which all geometric element types are derived.
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) override
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
This class defines an abstract interface for Mesh output.
bool & binary()
Flag indicating whether or not to write a binary file.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
std::map< unsigned int, ElementDefinition > in
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.
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
Creates a list of element numbers, sides, and ids for those sides.
std::map< ElemType, ElementDefinition > out
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
virtual unsigned int n_nodes() const =0
const Point & min() const
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
virtual dof_id_type max_elem_id() const =0
PetscErrorCode PetscInt const PetscInt IS * is
void write_mesh(std::ostream &out)
This method implements writing a mesh to a specified file.
std::string & subdomain_name(subdomain_id_type id)
void set_mesh_dimension(unsigned char d)
Resets the logical dimension of the mesh.
bool _write_lower_dimensional_elements
If true, lower-dimensional elements based on the boundary conditions get written to the output file...
virtual void clear()
Deletes all the element and node data that is currently stored.
Defines mapping from libMesh element types to Gmsh element types or vice-versa.
std::string & sideset_name(boundary_id_type id)
std::string enum_to_string(const T e)
static ElementMaps build_element_maps()
A static function used to construct the _element_maps struct, statically.
Defines a Cartesian bounding box by the two corner extremum.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
static std::unique_ptr< Elem > build_with_id(const ElemType type, dof_id_type id)
Calls the build() method above with a nullptr parent, and additionally sets the newly-created Elem's ...
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...
virtual const Elem & elem_ref(const dof_id_type i) const
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...
static ElementMaps _element_maps
A static ElementMaps object that is built statically and used by all instances of this class...
virtual const Node & node_ref(const dof_id_type i) const
GmshIO(MeshBase &mesh)
Constructor.
const Point & max() const
void add_def(const ElementDefinition &eledef)
virtual void read(const std::string &name) override
Reads in a mesh in the Gmsh *.msh format from the ASCII file given by name.
virtual const Node * node_ptr(const dof_id_type i) const =0
void write_post(const std::string &, const std::vector< Number > *=nullptr, const std::vector< std::string > *=nullptr)
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
processor_id_type processor_id() const
A Point defines a location in LIBMESH_DIM dimensional Real space.
virtual void reserve_elem(const dof_id_type ne)=0
Reserves space for a known number of elements.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
struct which holds a map from Gmsh to libMesh element numberings and vice-versa.
virtual dof_id_type n_nodes() const =0
void read_mesh(std::istream &in)
Implementation of the read() function.
std::vector< unsigned int > nodes