cell_inf_prism.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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 #include "libmesh/libmesh_config.h"
19 
20 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
21 
22 // Local includes
23 #include "libmesh/cell_inf_prism.h"
25 #include "libmesh/face_tri3.h"
26 #include "libmesh/face_inf_quad4.h"
27 #include "libmesh/fe_type.h"
28 #include "libmesh/fe_interface.h"
29 #include "libmesh/enum_order.h"
30 
31 namespace libMesh
32 {
33 
34 
35 // ------------------------------------------------------------
36 // InfPrism class static member initializations
37 
38 
39 // We need to require C++11...
40 const Real InfPrism::_master_points[12][3] =
41  {
42  {0, 0, 0},
43  {1, 0, 0},
44  {0, 1, 0},
45  {0, 0, 1},
46  {1, 0, 1},
47  {0, 1, 1},
48  {.5, 0, 0},
49  {.5, .5, 0},
50  {0, .5, 0},
51  {.5, 0, 1},
52  {.5, .5, 1},
53  {0, .5, 1}
54  };
55 
56 
57 
58 // ------------------------------------------------------------
59 // InfPrism class member functions
60 dof_id_type InfPrism::key (const unsigned int s) const
61 {
62  libmesh_assert_less (s, this->n_sides());
63 
64  switch (s)
65  {
66  case 0: // the triangular face at z=-1, base face
67  return this->compute_key (this->node_id(InfPrism6::side_nodes_map[s][0]),
69  this->node_id(InfPrism6::side_nodes_map[s][2]));
70 
71  case 1: // the quad face at y=0
72  case 2: // the other quad face
73  case 3: // the quad face at x=0
74  return this->compute_key (this->node_id(InfPrism6::side_nodes_map[s][0]),
77  this->node_id(InfPrism6::side_nodes_map[s][3]));
78 
79  default:
80  libmesh_error_msg("Invalid side s = " << s);
81  }
82 }
83 
84 
85 
86 unsigned int InfPrism::which_node_am_i(unsigned int side,
87  unsigned int side_node) const
88 {
89  libmesh_assert_less (side, this->n_sides());
90 
91  // Never more than 4 nodes per side.
92  libmesh_assert_less(side_node, 4);
93 
94  // Some sides have 3 nodes.
95  libmesh_assert(side != 0 || side_node < 3);
96 
97  return InfPrism6::side_nodes_map[side][side_node];
98 }
99 
100 
101 
102 std::unique_ptr<Elem> InfPrism::side_ptr (const unsigned int i)
103 {
104  libmesh_assert_less (i, this->n_sides());
105 
106  std::unique_ptr<Elem> face;
107 
108  switch (i)
109  {
110  case 0: // the triangular face at z=-1, base face
111  {
112  face = libmesh_make_unique<Tri3>();
113  break;
114  }
115 
116  case 1: // the quad face at y=0
117  case 2: // the other quad face
118  case 3: // the quad face at x=0
119  {
120  face = libmesh_make_unique<InfQuad4>();
121  break;
122  }
123 
124  default:
125  libmesh_error_msg("Invalid side i = " << i);
126  }
127 
128  // Set the nodes
129  for (unsigned n=0; n<face->n_nodes(); ++n)
130  face->set_node(n) = this->node_ptr(InfPrism6::side_nodes_map[i][n]);
131 
132  return face;
133 }
134 
135 
136 
137 void InfPrism::side_ptr (std::unique_ptr<Elem> & side,
138  const unsigned int i)
139 {
140  libmesh_assert_less (i, this->n_sides());
141 
142  switch (i)
143  {
144  // the base face
145  case 0:
146  {
147  if (!side.get() || side->type() != TRI3)
148  {
149  side = this->side_ptr(i);
150  return;
151  }
152  break;
153  }
154 
155  // connecting to another infinite element
156  case 1:
157  case 2:
158  case 3:
159  case 4:
160  {
161  if (!side.get() || side->type() != INFQUAD4)
162  {
163  side = this->side_ptr(i);
164  return;
165  }
166  break;
167  }
168 
169  default:
170  libmesh_error_msg("Invalid side i = " << i);
171  }
172 
173  side->subdomain_id() = this->subdomain_id();
174 
175  // Set the nodes
176  for (auto n : side->node_index_range())
177  side->set_node(n) = this->node_ptr(InfPrism6::side_nodes_map[i][n]);
178 }
179 
180 
181 
182 bool InfPrism::is_child_on_side(const unsigned int c,
183  const unsigned int s) const
184 {
185  libmesh_assert_less (c, this->n_children());
186  libmesh_assert_less (s, this->n_sides());
187 
188  return (s == 0 || c+1 == s || c == s%3);
189 }
190 
191 
192 
193 bool InfPrism::is_edge_on_side (const unsigned int e,
194  const unsigned int s) const
195 {
196  libmesh_assert_less (e, this->n_edges());
197  libmesh_assert_less (s, this->n_sides());
198 
199  return (is_node_on_side(InfPrism6::edge_nodes_map[e][0],s) &&
201 }
202 
203 bool InfPrism::contains_point (const Point & p, Real tol) const
204 {
205  // For infinite elements with linear base interpolation:
206  // make use of the fact that infinite elements do not
207  // live inside the envelope. Use a fast scheme to
208  // check whether point \p p is inside or outside
209  // our relevant part of the envelope. Note that
210  // this is not exclusive: only when the distance is less,
211  // we are safe. Otherwise, we cannot say anything. The
212  // envelope may be non-spherical, the physical point may lie
213  // inside the envelope, outside the envelope, or even inside
214  // this infinite element. Therefore if this fails,
215  // fall back to the FEInterface::inverse_map()
216  const Point my_origin (this->origin());
217 
218  // determine the minimal distance of the base from the origin
219  // use norm_sq(), it is faster than norm() and produces
220  // the same behavior. Shift my_origin to center first:
221  Point pt0_o(this->point(0) - my_origin);
222  Point pt1_o(this->point(1) - my_origin);
223  Point pt2_o(this->point(2) - my_origin);
224  const Real min_distance_sq = std::min(pt0_o.norm_sq(),
225  std::min(pt1_o.norm_sq(),
226  pt2_o.norm_sq()));
227 
228  // work with 1% allowable deviation. We can still fall
229  // back to the InfFE::inverse_map()
230  const Real conservative_p_dist_sq = 1.01 * (Point(p - my_origin).norm_sq());
231 
232  if (conservative_p_dist_sq < min_distance_sq)
233  {
234  // the physical point is definitely not contained in the element:
235  return false;
236  }
237 
238  // this captures the case that the point is not (almost) in the direction of the element.:
239  // first, project the problem onto the unit sphere:
240  Point p_o(p - my_origin);
241  pt0_o /= pt0_o.norm();
242  pt1_o /= pt1_o.norm();
243  pt2_o /= pt2_o.norm();
244  p_o /= p_o.norm();
245 
246  // now, check if it is in the projected face; by comparing the distance of
247  // any point in the element to \p p with the largest distance between this point
248  // to any other point in the element.
249  if ((p_o - pt0_o).norm_sq() > std::max((pt0_o - pt1_o).norm_sq(), (pt0_o - pt2_o).norm_sq()) ||
250  (p_o - pt1_o).norm_sq() > std::max((pt1_o - pt2_o).norm_sq(), (pt1_o - pt0_o).norm_sq()) ||
251  (p_o - pt2_o).norm_sq() > std::max((pt2_o - pt0_o).norm_sq(), (pt2_o - pt1_o).norm_sq()) )
252  {
253  // the physical point is definitely not contained in the element
254  return false;
255  }
256 
257 
258  // It seems that \p p is at least close to this element.
259  //
260  // Declare a basic FEType. Will use default in the base,
261  // and something else (not important) in radial direction.
262  FEType fe_type(default_order());
263 
264  const Point mapped_point = FEInterface::inverse_map(dim(),
265  fe_type,
266  this,
267  p,
268  tol,
269  false);
270 
271  return FEInterface::on_reference_element(mapped_point, this->type(), tol);
272 }
273 
274 
275 } // namespace libMesh
276 
277 
278 
279 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
Real norm() const
Definition: type_vector.h:912
static const Real _master_points[12][3]
virtual dof_id_type key() const
Definition: elem.C:401
virtual unsigned int n_edges() const override final
unsigned short int side
Definition: xdr_io.C:50
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
long double max(long double a, double b)
virtual unsigned int n_children() const override final
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
static Point inverse_map(const unsigned int dim, const FEType &fe_t, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
Definition: fe_interface.C:590
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override final
static bool on_reference_element(const Point &p, const ElemType t, const Real eps=TOLERANCE)
Definition: fe_interface.C:647
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
static const unsigned int edge_nodes_map[num_edges][nodes_per_edge]
virtual Point origin() const override
Definition: cell_inf.h:77
Real norm_sq() const
Definition: type_vector.h:943
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
Definition: elem.h:2034
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1957
virtual unsigned short dim() const override
Definition: cell_inf.h:66
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const override
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:2754
virtual Order default_order() const =0
virtual unsigned int n_sides() const override final
virtual ElemType type() const =0
long double min(long double a, double b)
A geometric point in (x,y,z) space.
Definition: point.h:38
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1914
const Point & point(const unsigned int i) const
Definition: elem.h:1892
std::unique_ptr< Elem > side(const unsigned int i) const
Definition: elem.h:2202
virtual unsigned int which_node_am_i(unsigned int side, unsigned int side_node) const override
uint8_t dof_id_type
Definition: id_types.h:64