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