1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 
18 
19 
20 #ifndef LIBMESH_CELL_INF_HEX_H
21 #define LIBMESH_CELL_INF_HEX_H
22 
23 #include "libmesh/libmesh_config.h"
24 
25 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
26 
27 // Local includes
28 #include "libmesh/cell_inf.h"
29 
30 namespace libMesh
31 {
32 
33 /**
34  * The \p InfHex is an element in 3D with 5 sides.
35  * The \f$ 6^{th} \f$ side is theoretically located at infinity,
36  * and therefore not accounted for.
37  * However, one could say that the \f$ 6^{th} \f$ side actually
38  * does exist in the mesh, since the outer nodes are located
39  * at a specific distance from the mesh origin (and therefore
40  * define a side).  Still, this face is not to be used!
41  *
42  * \author Daniel Dreyer
43  * \date 2003
44  * \brief The base class for all 3D infinite hexahedral element types.
45  */
46 class InfHex : public InfCell
47 {
48 public:
49 
50   /**
51    * Default infinite brick element, takes number of nodes and
52    * parent. Derived classes implement 'true' elements.
53    */
InfHex(const unsigned int nn,Elem * p,Node ** nodelinkdata)54   InfHex(const unsigned int nn, Elem * p, Node ** nodelinkdata) :
55     InfCell(nn, InfHex::n_sides(), p, _elemlinks_data, nodelinkdata)
56   {
57     // Make sure the interior parent isn't undefined
58     if (LIBMESH_DIM > 3)
59       this->set_interior_parent(nullptr);
60   }
61 
62   InfHex (InfHex &&) = delete;
63   InfHex (const InfHex &) = delete;
64   InfHex & operator= (const InfHex &) = delete;
65   InfHex & operator= (InfHex &&) = delete;
66   virtual ~InfHex() = default;
67 
68   /**
69    * \returns The \p Point associated with local \p Node \p i,
70    * in master element rather than physical coordinates.
71    */
master_point(const unsigned int i)72   virtual Point master_point (const unsigned int i) const override final
73   {
74     libmesh_assert_less(i, this->n_nodes());
75     return Point(_master_points[i][0],
76                  _master_points[i][1],
77                  _master_points[i][2]);
78   }
79 
80   /**
81    * \returns 5.  Infinite elements have one side less
82    * than their conventional counterparts, since one
83    * side is supposed to be located at infinity.
84    */
n_sides()85   virtual unsigned int n_sides() const override final { return 5; }
86 
87   /**
88    * \returns 8.  All infinite hexahedra (in our
89    * setting) have 8 vertices.
90    */
n_vertices()91   virtual unsigned int n_vertices() const override final { return 8; }
92 
93   /**
94    * \returns \p true if the specified (local) node number is a
95    * "mid-edge" node on an infinite element edge.
96    */
is_mid_infinite_edge_node(const unsigned int i)97   virtual bool is_mid_infinite_edge_node(const unsigned int i) const
98     override final { return (i > 3 && i < 8); }
99 
100   /**
101    * \returns 8.  All infinite hexahedra have 8 edges,
102    * 4 lying in the base, and 4 perpendicular to the base.
103    */
n_edges()104   virtual unsigned int n_edges() const override final { return 8; }
105 
106   /**
107    * \returns 5.  All infinite hexahedra have 5 faces.
108    */
n_faces()109   virtual unsigned int n_faces() const override final { return 5; }
110 
111   /**
112    * \returns 4.
113    */
n_children()114   virtual unsigned int n_children() const override final { return 4; }
115 
116   /**
117    * \returns \p true if the specified child is on the
118    * specified side.
119    */
120   virtual bool is_child_on_side(const unsigned int c,
121                                 const unsigned int s) const override final;
122 
123   /**
124    * \returns \p true if the specified edge is on the specified side.
125    */
126   virtual bool is_edge_on_side(const unsigned int e,
127                                const unsigned int s) const override final;
128 
129   virtual std::vector<unsigned int> sides_on_edge(const unsigned int e) const override final;
130 
131   /**
132    * Don't hide Elem::key() defined in the base class.
133    */
134   using Elem::key;
135 
136   /**
137    * \returns An id associated with the \p s side of this element.
138    * The id is not necessarily unique, but should be close.  This is
139    * particularly useful in the \p MeshBase::find_neighbors() routine.
140    */
141   virtual dof_id_type key (const unsigned int s) const override;
142 
143   /**
144    * \returns \p InfHex8::side_nodes_map[side][side_node] after doing some range checking.
145    */
146   virtual unsigned int local_side_node(unsigned int side,
147                                        unsigned int side_node) const override;
148 
149   /**
150    * \returns \p InfHex8::edge_nodes_map[edge][edge_node] after doing some range checking.
151    */
152   virtual unsigned int local_edge_node(unsigned int edge,
153                                        unsigned int edge_node) const override;
154 
155   /**
156    * \returns A primitive (4-noded) quad or infquad for face i.
157    */
158   virtual std::unique_ptr<Elem> side_ptr (const unsigned int i) override final;
159 
160   /**
161    * Rebuilds a primitive (4-noded) quad or infquad for face i.
162    */
163   virtual void side_ptr (std::unique_ptr<Elem> & side, const unsigned int i) override final;
164 
165   /**
166    * \returns A quantitative assessment of element quality based on
167    * the metric \p q specified by the user.
168    */
169   virtual Real quality (const ElemQuality q) const override;
170 
171   /**
172    * \returns The suggested quality bounds for the hex based on
173    * quality measure \p q.  These are the values suggested by the
174    * CUBIT User's Manual.
175    */
176   virtual std::pair<Real, Real> qual_bounds (const ElemQuality q) const override;
177 
178   /**
179    * \returns \p true when this element contains the point
180    * \p p.  Customized for infinite elements, since knowledge
181    * about the envelope can be helpful.
182    */
183   virtual bool contains_point (const Point & p, Real tol=TOLERANCE) const override;
184 
185 protected:
186 
187   /**
188    * Data for links to parent/neighbor/interior_parent elements.
189    */
190   Elem * _elemlinks_data[6+(LIBMESH_DIM>3)];
191 
192 
193 
194   /**
195    * For higher-order elements, namely \p InfHex16 and
196    * \p InfHex18, the matrices for adjacent vertices
197    * of second order nodes are quite similar (apart from
198    * the face nodes, which are directly handled by \p InfHex18).
199    * Therefore hold this matrix here, so that both can re-use
200    * this.  Matrix that tells which vertices define the location
201    * of mid-side (or second-order) nodes.
202    */
203   static const unsigned short int _second_order_adjacent_vertices[8][2];
204 
205   /**
206    * Vector that names a child sharing each second order node.
207    */
208   static const unsigned short int _second_order_vertex_child_number[18];
209 
210   /**
211    * Vector that names the child vertex index for each second order node.
212    */
213   static const unsigned short int _second_order_vertex_child_index[18];
214 
215   /**
216    * Master element node locations
217    */
218   static const Real _master_points[18][3];
219 };
220 
221 
222 } // namespace libMesh
223 
224 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
225 
226 #endif // LIBMESH_CELL_INF_HEX_H
227