libMesh
Static Public Member Functions | List of all members
libMesh::InfFEMap Class Reference

Class that encapsulates mapping (i.e. More...

#include <inf_fe_map.h>

Static Public Member Functions

static Point map (const unsigned int dim, const Elem *inf_elem, const Point &reference_point)
 
static Point inverse_map (const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
 
static void inverse_map (const unsigned int dim, const Elem *elem, const std::vector< Point > &physical_points, std::vector< Point > &reference_points, const Real tolerance=TOLERANCE, const bool secure=true)
 Takes a number points in physical space (in the physical_points vector) and finds their location on the reference element for the input element elem. More...
 
static Real eval (Real v, Order o, unsigned int i)
 
static Real eval_deriv (Real v, Order o, unsigned int i)
 

Detailed Description

Class that encapsulates mapping (i.e.

from physical space to reference space and vice-versa) operations on infinite elements.

Definition at line 47 of file inf_fe_map.h.

Member Function Documentation

◆ eval()

Real libMesh::InfFEMap::eval ( Real  v,
Order  o,
unsigned int  i 
)
static
Returns
The value of the \( i^{th} \) polynomial evaluated at v. This method provides the approximation in radial direction for the overall shape functions, which is defined in InfFE::shape(). This method is allowed to be static, since it is independent of dimension and base_family. It is templated, though, w.r.t. to radial FEFamily.
The value of the \( i^{th} \) mapping shape function in radial direction evaluated at v when T_radial == INFINITE_MAP. Currently, only one specific mapping shape is used. Namely the one by Marques JMMC, Owen DRJ: Infinite elements in quasi-static materially nonlinear problems, Computers and Structures, 1984.

Definition at line 27 of file inf_fe_map_eval.C.

References libMesh::libmesh_assert().

Referenced by libMesh::InfFE< Dim, T_radial, T_map >::eval(), and map().

28 {
29  libmesh_assert (-1.-1.e-5 <= v && v < 1.);
30 
31  switch (i)
32  {
33  case 0:
34  return -2.*v/(1.-v);
35  case 1:
36  return (1.+v)/(1.-v);
37 
38  default:
39  libmesh_error_msg("bad index i = " << i);
40  }
41 }
libmesh_assert(ctx)

◆ eval_deriv()

Real libMesh::InfFEMap::eval_deriv ( Real  v,
Order  o,
unsigned int  i 
)
static
Returns
The value of the first derivative of the \( i^{th} \) polynomial at coordinate v. See eval for details.

Definition at line 45 of file inf_fe_map_eval.C.

References libMesh::libmesh_assert().

Referenced by libMesh::InfFE< Dim, T_radial, T_map >::eval_deriv().

46 {
47  libmesh_assert (-1.-1.e-5 <= v && v < 1.);
48 
49  switch (i)
50  {
51  case 0:
52  return -2./((1.-v)*(1.-v));
53  case 1:
54  return 2./((1.-v)*(1.-v));
55 
56  default:
57  libmesh_error_msg("bad index i = " << i);
58  }
59 }
libmesh_assert(ctx)

◆ inverse_map() [1/2]

Point libMesh::InfFEMap::inverse_map ( const unsigned int  dim,
const Elem elem,
const Point p,
const Real  tolerance = TOLERANCE,
const bool  secure = true 
)
static
Returns
The location (on the reference element) of the point p located in physical space. First, the location in the base face is computed. This requires inverting the (possibly nonlinear) transformation map in the base, so it is not trivial. The optional parameter tolerance defines how close is "good enough." The map inversion iteration computes the sequence \( \{ p_n \} \), and the iteration is terminated when \( \|p - p_n\| < \mbox{\texttt{tolerance}} \). Once the base face point is determined, the radial local coordinate is directly evaluated. If interpolated is true, the interpolated distance from the base element to the infinite element origin is used for the map in radial direction.

Definition at line 96 of file inf_fe_map.C.

References libMesh::TypeVector< T >::add_scaled(), libMesh::InfFEBase::build_elem(), dim, libMesh::FEMap::inverse_map(), libMesh::libmesh_assert(), libMesh::libmesh_isinf(), map(), libMesh::FE< Dim, T >::n_shape_functions(), libMesh::TypeVector< T >::norm(), libMesh::Elem::origin(), libMesh::Real, libMesh::FE< Dim, T >::shape(), libMesh::FE< Dim, T >::shape_deriv(), libMesh::TypeTensor< T >::solve(), and libMesh::TOLERANCE.

Referenced by libMesh::InfQuad4::contains_point(), libMesh::InfPrism::contains_point(), libMesh::InfHex::contains_point(), inverse_map(), libMesh::FEMap::inverse_map(), and libMesh::InfFE< Dim, T_radial, T_map >::inverse_map().

101 {
102  libmesh_assert(inf_elem);
103  libmesh_assert_greater_equal (tolerance, 0.);
104  libmesh_assert(dim > 0);
105 
106  // Start logging the map inversion.
107  LOG_SCOPE("inverse_map()", "InfFEMap");
108 
109  // The strategy is:
110  // compute the intersection of the line
111  // physical_point - origin with the base element,
112  // find its internal coordinatels using FEMap::inverse_map():
113  // The radial part can then be computed directly later on.
114 
115  // 1.)
116  // build a base element to do the map inversion in the base face
117  std::unique_ptr<const Elem> base_elem = InfFEBase::build_elem (inf_elem);
118 
119  // The point on the reference element (which we are looking for).
120  // start with an invalid guess:
121  Point p;
122  p(dim-1)=-2.;
123 
124  // 2.)
125  // Now find the intersection of a plane represented by the base
126  // element nodes and the line given by the origin of the infinite
127  // element and the physical point.
128  Point intersection;
129 
130  // the origin of the infinite element
131  const Point o = inf_elem->origin();
132 
133  switch (dim)
134  {
135  // unnecessary for 1D
136  case 1:
137  break;
138 
139  case 2:
140  libmesh_error_msg("ERROR: InfFE::inverse_map is not yet implemented in 2d");
141 
142  case 3:
143  {
144  const Point xi ( base_elem->point(1) - base_elem->point(0));
145  const Point eta( base_elem->point(2) - base_elem->point(0));
146  const Point zeta( physical_point - o);
147 
148  // normal vector of the base elements plane
149  Point n(xi.cross(eta));
150  Real c_factor = (base_elem->point(0) - o)*n/(zeta*n) - 1.;
151 
152  // Check whether the above system is ill-posed. It should
153  // only happen when \p physical_point is not in \p
154  // inf_elem. In this case, any point that is not in the
155  // element is a valid answer.
156  if (libmesh_isinf(c_factor))
157  return p;
158 
159  // Compute the intersection with
160  // {intersection} = {physical_point} + c*({physical_point}-{o}).
161  intersection.add_scaled(physical_point,1.+c_factor);
162  intersection.add_scaled(o,-c_factor);
163 
164  // For non-planar elements, the intersecting point is obtained via Newton-iteration
165  if (!base_elem->has_affine_map())
166  {
167  unsigned int iter_max = 20;
168 
169  // the number of shape functions needed for the base_elem
170  unsigned int n_sf = FE<2,LAGRANGE>::n_shape_functions(base_elem->type(),base_elem->default_order());
171 
172  // guess base element coordinates: p=xi,eta,0
173  // in first iteration, never run with 'secure' to avoid false warnings.
174  Point ref_point= FEMap::inverse_map(dim-1, base_elem.get(), intersection,
175  tolerance, false);
176 
177  // Newton iteration
178  for(unsigned int it=0; it<iter_max; ++it)
179  {
180  // Get the shape function and derivative values at the reference coordinate
181  // phi.size() == dphi.size()
182  Point dxyz_dxi;
183  Point dxyz_deta;
184 
185  Point intersection_guess;
186  for(unsigned int i=0; i<n_sf; ++i)
187  {
188 
189  intersection_guess += base_elem->node_ref(i) * FE<2,LAGRANGE>::shape(base_elem->type(),
190  base_elem->default_order(),
191  i,
192  ref_point);
193 
194  dxyz_dxi += base_elem->node_ref(i) * FE<2,LAGRANGE>::shape_deriv(base_elem->type(),
195  base_elem->default_order(),
196  i,
197  0, // d()/dxi
198  ref_point);
199 
200  dxyz_deta+= base_elem->node_ref(i) * FE<2,LAGRANGE>::shape_deriv(base_elem->type(),
201  base_elem->default_order(),
202  i,
203  1, // d()/deta
204  ref_point);
205  } // for i
206 
207  TypeVector<Real> F(physical_point + c_factor*(physical_point-o) - intersection_guess);
208 
210  J(0,0) = (physical_point-o)(0);
211  J(0,1) = -dxyz_dxi(0);
212  J(0,2) = -dxyz_deta(0);
213  J(1,0) = (physical_point-o)(1);
214  J(1,1) = -dxyz_dxi(1);
215  J(1,2) = -dxyz_deta(1);
216  J(2,0) = (physical_point-o)(2);
217  J(2,1) = -dxyz_dxi(2);
218  J(2,2) = -dxyz_deta(2);
219 
220  // delta will be the newton step
221  TypeVector<Real> delta;
222  J.solve(F,delta);
223 
224  // check for convergence
225  Real tol = std::min( TOLERANCE*0.01, TOLERANCE*base_elem->hmax() );
226  if ( delta.norm() < tol )
227  {
228  // newton solver converged, now make sure it converged to a point on the base_elem
229  if (base_elem->contains_point(intersection_guess,TOLERANCE*0.1))
230  {
231  intersection = intersection_guess;
232  }
233  //else
234  // {
235  // err<<" Error: inverse_map failed!"<<std::endl;
236  // }
237  break; // break out of 'for it'
238  }
239  else
240  {
241  c_factor -= delta(0);
242  ref_point(0) -= delta(1);
243  ref_point(1) -= delta(2);
244  }
245 
246  }
247 
248  }
249  break;
250  }
251 
252  default:
253  libmesh_error_msg("Invalid dim = " << dim);
254  }
255 
256  // 3.)
257  // Now we have the intersection-point (projection of physical point onto base-element).
258  // Lets compute its internal coordinates (being p(0) and p(1)):
259  p= FEMap::inverse_map(dim-1, base_elem.get(), intersection,
260  tolerance, secure, secure);
261 
262  // 4.
263  // Now that we have the local coordinates in the base,
264  // we compute the radial distance with Newton iteration.
265 
266  // distance from the physical point to the ifem origin
267  const Real fp_o_dist = Point(o-physical_point).norm();
268 
269  // the distance from the intersection on the
270  // base to the origin
271  const Real a_dist = Point(o-intersection).norm();
272 
273  // element coordinate in radial direction
274 
275  // fp_o_dist is at infinity.
276  if (libmesh_isinf(fp_o_dist))
277  {
278  p(dim-1)=1;
279  return p;
280  }
281 
282  // when we are somewhere in this element:
283  Real v = 0;
284 
285  // For now we're sticking with T_map == CARTESIAN
286  // if (T_map == CARTESIAN)
287  v = 1.-2.*a_dist/fp_o_dist;
288  // else
289  // libmesh_not_implemented();
290 
291 
292  p(dim-1)=v;
293 #ifdef DEBUG
294  // first check whether we are in the reference-element:
295  if ((-1.-1.e-5 < v && v < 1.) || secure)
296  {
297  const Point check = map (dim, inf_elem, p);
298  const Point diff = physical_point - check;
299 
300  if (diff.norm() > tolerance)
301  libmesh_warning("WARNING: diff is " << diff.norm());
302  }
303 #endif
304 
305  return p;
306 }
static OutputShape shape(const ElemType t, const Order o, const unsigned int i, const Point &p)
static Point map(const unsigned int dim, const Elem *inf_elem, const Point &reference_point)
Definition: inf_fe_map.C:40
static constexpr Real TOLERANCE
unsigned int dim
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition: fe_map.C:1626
template class LIBMESH_EXPORT TypeTensor< Real >
Definition: type_tensor.C:191
static OutputShape shape_deriv(const ElemType t, const Order o, const unsigned int i, const unsigned int j, const Point &p)
static std::unique_ptr< const Elem > build_elem(const Elem *inf_elem)
Build the base element of an infinite element.
bool libmesh_isinf(T x)
virtual unsigned int n_shape_functions() const override
Definition: fe.C:61
template class LIBMESH_EXPORT TypeVector< Real >
Definition: type_vector.C:227
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ inverse_map() [2/2]

void libMesh::InfFEMap::inverse_map ( const unsigned int  dim,
const Elem elem,
const std::vector< Point > &  physical_points,
std::vector< Point > &  reference_points,
const Real  tolerance = TOLERANCE,
const bool  secure = true 
)
static

Takes a number points in physical space (in the physical_points vector) and finds their location on the reference element for the input element elem.

The values on the reference element are returned in the vector reference_points

Definition at line 310 of file inf_fe_map.C.

References dim, and inverse_map().

316 {
317  // The number of points to find the
318  // inverse map of
319  const std::size_t n_points = physical_points.size();
320 
321  // Resize the vector to hold the points
322  // on the reference element
323  reference_points.resize(n_points);
324 
325  // Find the coordinates on the reference
326  // element of each point in physical space
327  for (unsigned int p=0; p<n_points; p++)
328  reference_points[p] =
329  inverse_map (dim, elem, physical_points[p], tolerance, secure);
330 }
unsigned int dim
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
Definition: inf_fe_map.C:96

◆ map()

Point libMesh::InfFEMap::map ( const unsigned int  dim,
const Elem inf_elem,
const Point reference_point 
)
static
Returns
The location (in physical space) of the point p located on the reference element.

Definition at line 40 of file inf_fe_map.C.

References libMesh::TypeVector< T >::add_scaled(), libMesh::InfFEBase::build_elem(), dim, eval(), libMesh::libmesh_assert(), libMesh::FEMap::map(), libMesh::InfFERadial::mapping_order(), libMesh::Elem::origin(), libMesh::Elem::point(), and libMesh::Real.

Referenced by libMesh::InfFE< Dim, T_radial, T_map >::compute_shape_functions(), inverse_map(), libMesh::FEMap::map(), and libMesh::InfFE< Dim, T_radial, T_map >::map().

43 {
44  libmesh_assert(inf_elem);
45  libmesh_assert_not_equal_to (dim, 0);
46 
47  std::unique_ptr<const Elem> base_elem = InfFEBase::build_elem (inf_elem);
48 
49  const Real v (reference_point(dim-1));
50 
51  // map in the base face
52  Point base_point;
53  switch (dim)
54  {
55  case 1:
56  base_point = inf_elem->point(0);
57  break;
58  case 2:
59  case 3:
60  base_point = FEMap::map (dim-1, base_elem.get(), reference_point);
61  break;
62  default:
63 #ifdef DEBUG
64  libmesh_error_msg("Unknown dim = " << dim);
65 #endif
66  break;
67  }
68 
69  // This is the same as the algorithm used below,
70  // but is more explicit in the actual form in the end.
71  //
72  // NOTE: the form used below can be implemented to yield
73  // more general/flexible mappings, but the current form is
74  // used e.g. for \p inverse_map() and \p reinit() explicitly.
75  return (base_point-inf_elem->origin())*2/(1-v)+inf_elem->origin();
76 
77 #if 0 // Leave this documented, but w/o unreachable-code warnings
78  const Order radial_mapping_order (InfFERadial::mapping_order());
79 
80  // map in the outer node face not necessary. Simply
81  // compute the outer_point = base_point + (base_point-origin)
82  const Point outer_point (base_point * 2. - inf_elem->origin());
83 
84  Point p;
85 
86  // there are only two mapping shapes in radial direction
87  p.add_scaled (base_point, eval (v, radial_mapping_order, 0));
88  p.add_scaled (outer_point, eval (v, radial_mapping_order, 1));
89 
90  return p;
91 #endif
92 }
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
unsigned int dim
static Real eval(Real v, Order o, unsigned int i)
static std::unique_ptr< const Elem > build_elem(const Elem *inf_elem)
Build the base element of an infinite element.
static Order mapping_order()
Definition: inf_fe.h:97
libmesh_assert(ctx)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition: fe_map.C:2067

The documentation for this class was generated from the following files: