libMesh
Loading...
Searching...
No Matches
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.
 
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.

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)

References libMesh::libmesh_assert().

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

◆ 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.

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}

References libMesh::libmesh_assert().

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

◆ 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.

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}
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:1512
virtual unsigned int n_shape_functions() const override
Definition fe.C:75
static OutputShape shape(const ElemType t, const Order o, const unsigned int i, const Point &p)
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.
static Point map(const unsigned int dim, const Elem *inf_elem, const Point &reference_point)
Definition inf_fe_map.C:40
bool libmesh_isinf(T x)
template class LIBMESH_EXPORT TypeTensor< Real >
template class LIBMESH_EXPORT TypeVector< Real >
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

References libMesh::TypeVector< T >::add_scaled(), libMesh::InfFEBase::build_elem(), libMesh::TypeVector< T >::cross(), 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::InfHex::contains_point(), libMesh::InfPrism::contains_point(), libMesh::InfQuad4::contains_point(), libMesh::InfFE< Dim, T_radial, T_map >::inverse_map(), libMesh::InfFE< Dim, T_radial, T_map >::inverse_map(), libMesh::FEMap::inverse_map(), inverse_map(), and libMesh::FEMap::inverse_map().

◆ 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.

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}
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

References dim, and inverse_map().

◆ 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.

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}
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition fe_map.C:1954
static Real eval(Real v, Order o, unsigned int i)
static Order mapping_order()
Definition inf_fe.h:97

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::InfFE< Dim, T_radial, T_map >::map(), and libMesh::FEMap::map().


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