libMesh
fe_boundary.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 // C++ includes
21 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
22 #include <cmath> // for std::sqrt
23 
24 
25 // Local includes
26 #include "libmesh/libmesh_common.h"
27 #include "libmesh/fe.h"
28 #include "libmesh/fe_interface.h"
29 #include "libmesh/quadrature.h"
30 #include "libmesh/elem.h"
31 #include "libmesh/libmesh_logging.h"
32 #include "libmesh/tensor_value.h" // May be necessary if destructors
33 // get instantiated here
34 
35 namespace libMesh
36 {
37 
38 //-------------------------------------------------------
39 // Full specializations for useless methods in 0D, 1D
40 #define REINIT_ERROR(_dim, _type, _func) \
41  template <> \
42  void FE<_dim,_type>::_func(const Elem *, \
43  const unsigned int, \
44  const Real, \
45  const std::vector<Point> * const, \
46  const std::vector<Real> * const)
47 
48 #define SIDEMAP_ERROR(_dim, _type, _func) \
49  template <> \
50  void FE<_dim,_type>::_func(const Elem *, \
51  const Elem *, \
52  const unsigned int, \
53  const std::vector<Point> &, \
54  std::vector<Point> &)
55 
56 #define FACE_EDGE_SHAPE_ERROR(_dim, _func) \
57  template <> \
58  void FEMap::_func<_dim>(const std::vector<Point> &, \
59  const Elem *) \
60  { \
61  libmesh_error_msg("ERROR: This method makes no sense for low-D elements!"); \
62  }
63 
64 // 0D error instantiations
65 #define ERRORS_IN_0D(_type) \
66 REINIT_ERROR(0, _type, reinit) { libmesh_error_msg("ERROR: Cannot reinit 0D " #_type " elements!"); } \
67 REINIT_ERROR(0, _type, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 0D " #_type " elements!"); } \
68 SIDEMAP_ERROR(0, _type, side_map) { libmesh_error_msg("ERROR: Cannot side_map 0D " #_type " elements!"); }
69 
82 
83 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
87 #endif
88 
89 // 1D error instantiations
90 REINIT_ERROR(1, CLOUGH, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D CLOUGH elements!"); }
91 REINIT_ERROR(1, HERMITE, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D HERMITE elements!"); }
92 REINIT_ERROR(1, HIERARCHIC, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D HIERARCHIC elements!"); }
93 REINIT_ERROR(1, L2_HIERARCHIC, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D L2_HIERARCHIC elements!"); }
94 REINIT_ERROR(1, LAGRANGE, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D LAGRANGE elements!"); }
95 REINIT_ERROR(1, LAGRANGE_VEC, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D LAGRANGE_VEC elements!"); }
96 REINIT_ERROR(1, L2_LAGRANGE, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D L2_LAGRANGE elements!"); }
97 REINIT_ERROR(1, XYZ, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D XYZ elements!"); }
98 REINIT_ERROR(1, MONOMIAL, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D MONOMIAL elements!"); }
99 REINIT_ERROR(1, MONOMIAL_VEC, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D MONOMIAL_VEC elements!"); }
100 REINIT_ERROR(1, SCALAR, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D SCALAR elements!"); }
101 REINIT_ERROR(1, NEDELEC_ONE, reinit) { libmesh_error_msg("ERROR: Cannot reinit 1D NEDELEC_ONE elements!"); }
102 REINIT_ERROR(1, NEDELEC_ONE, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D NEDELEC_ONE elements!"); }
103 SIDEMAP_ERROR(1, NEDELEC_ONE, side_map) { libmesh_error_msg("ERROR: Cannot side_map 1D NEDELEC_ONE elements!"); }
104 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
105 REINIT_ERROR(1, BERNSTEIN, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D BERNSTEIN elements!"); }
106 REINIT_ERROR(1, SZABAB, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D SZABAB elements!"); }
107 REINIT_ERROR(1, RATIONAL_BERNSTEIN, edge_reinit) { libmesh_error_msg("ERROR: Cannot edge_reinit 1D RATIONAL_BERNSTEIN elements!"); }
108 #endif
109 
110 
111 //-------------------------------------------------------
112 // Methods for 2D, 3D
113 template <unsigned int Dim, FEFamily T>
114 void FE<Dim,T>::reinit(const Elem * elem,
115  const unsigned int s,
116  const Real /* tolerance */,
117  const std::vector<Point> * const pts,
118  const std::vector<Real> * const weights)
119 {
120  libmesh_assert(elem);
121  libmesh_assert (this->qrule != nullptr || pts != nullptr);
122  // We now do this for 1D elements!
123  // libmesh_assert_not_equal_to (Dim, 1);
124 
125  // We're (possibly re-) calculating now! FIXME - we currently
126  // expect to be able to use side_map and JxW later, but we could
127  // optimize further here.
128  this->_fe_map->calculations_started = false;
129  this->_fe_map->get_JxW();
130  this->_fe_map->get_xyz();
131  this->determine_calculations();
132 
133  // Build the side of interest
134  const std::unique_ptr<const Elem> side(elem->build_side_ptr(s));
135 
136  // Find the max p_level to select
137  // the right quadrature rule for side integration
138  unsigned int side_p_level = elem->p_level();
139  if (elem->neighbor_ptr(s) != nullptr)
140  side_p_level = std::max(side_p_level, elem->neighbor_ptr(s)->p_level());
141 
142  // Initialize the shape functions at the user-specified
143  // points
144  if (pts != nullptr)
145  {
146  // The shape functions do not correspond to the qrule
147  this->shapes_on_quadrature = false;
148 
149  // Initialize the face shape functions
150  this->_fe_map->template init_face_shape_functions<Dim>(*pts, side.get());
151 
152  // Compute the Jacobian*Weight on the face for integration
153  if (weights != nullptr)
154  {
155  this->_fe_map->compute_face_map (Dim, *weights, side.get());
156  }
157  else
158  {
159  std::vector<Real> dummy_weights (pts->size(), 1.);
160  this->_fe_map->compute_face_map (Dim, dummy_weights, side.get());
161  }
162  }
163  // If there are no user specified points, we use the
164  // quadrature rule
165  else
166  {
167  // initialize quadrature rule
168  this->qrule->init(side->type(), side_p_level);
169 
170  if (this->qrule->shapes_need_reinit())
171  this->shapes_on_quadrature = false;
172 
173  // FIXME - could this break if the same FE object was used
174  // for both volume and face integrals? - RHS
175  // We might not need to reinitialize the shape functions
176  if ((this->get_type() != elem->type()) ||
177  (side->type() != last_side) ||
178  (this->get_p_level() != side_p_level) ||
179  this->shapes_need_reinit() ||
180  !this->shapes_on_quadrature)
181  {
182  // Set the element type and p_level
183  this->elem_type = elem->type();
184 
185  // Set the last_side
186  last_side = side->type();
187 
188  // Set the last p level
189  this->_p_level = side_p_level;
190 
191  // Initialize the face shape functions
192  this->_fe_map->template init_face_shape_functions<Dim>(this->qrule->get_points(), side.get());
193  }
194 
195  // Compute the Jacobian*Weight on the face for integration
196  this->_fe_map->compute_face_map (Dim, this->qrule->get_weights(), side.get());
197 
198  // The shape functions correspond to the qrule
199  this->shapes_on_quadrature = true;
200  }
201 
202  // make a copy of the Jacobian for integration
203  const std::vector<Real> JxW_int(this->_fe_map->get_JxW());
204 
205  // make a copy of shape on quadrature info
206  bool shapes_on_quadrature_side = this->shapes_on_quadrature;
207 
208  // Find where the integration points are located on the
209  // full element.
210  const std::vector<Point> * ref_qp;
211  if (pts != nullptr)
212  ref_qp = pts;
213  else
214  ref_qp = &this->qrule->get_points();
215 
216  std::vector<Point> qp;
217  this->side_map(elem, side.get(), s, *ref_qp, qp);
218 
219  // compute the shape function and derivative values
220  // at the points qp
221  this->reinit (elem, &qp);
222 
223  this->shapes_on_quadrature = shapes_on_quadrature_side;
224 
225  // copy back old data
226  this->_fe_map->get_JxW() = JxW_int;
227 }
228 
229 
230 
231 template <unsigned int Dim, FEFamily T>
232 void FE<Dim,T>::edge_reinit(const Elem * elem,
233  const unsigned int e,
234  const Real tolerance,
235  const std::vector<Point> * const pts,
236  const std::vector<Real> * const weights)
237 {
238  libmesh_assert(elem);
239  libmesh_assert (this->qrule != nullptr || pts != nullptr);
240  // We don't do this for 1D elements!
241  libmesh_assert_not_equal_to (Dim, 1);
242 
243  // We're (possibly re-) calculating now! Time to determine what.
244  // FIXME - we currently just assume that we're using JxW and calling
245  // edge_map later.
246  this->_fe_map->calculations_started = false;
247  this->_fe_map->get_JxW();
248  this->_fe_map->get_xyz();
249  this->determine_calculations();
250 
251  // Build the side of interest
252  const std::unique_ptr<const Elem> edge(elem->build_edge_ptr(e));
253 
254  // Initialize the shape functions at the user-specified
255  // points
256  if (pts != nullptr)
257  {
258  // The shape functions do not correspond to the qrule
259  this->shapes_on_quadrature = false;
260 
261  // Initialize the edge shape functions
262  this->_fe_map->template init_edge_shape_functions<Dim> (*pts, edge.get());
263 
264  // Compute the Jacobian*Weight on the face for integration
265  if (weights != nullptr)
266  {
267  this->_fe_map->compute_edge_map (Dim, *weights, edge.get());
268  }
269  else
270  {
271  std::vector<Real> dummy_weights (pts->size(), 1.);
272  this->_fe_map->compute_edge_map (Dim, dummy_weights, edge.get());
273  }
274  }
275  // If there are no user specified points, we use the
276  // quadrature rule
277  else
278  {
279  // initialize quadrature rule
280  this->qrule->init(edge->type(), elem->p_level());
281 
282  if (this->qrule->shapes_need_reinit())
283  this->shapes_on_quadrature = false;
284 
285  // We might not need to reinitialize the shape functions
286  if ((this->get_type() != elem->type()) ||
287  (edge->type() != static_cast<int>(last_edge)) || // Comparison between enum and unsigned, cast the unsigned to int
288  this->shapes_need_reinit() ||
289  !this->shapes_on_quadrature)
290  {
291  // Set the element type
292  this->elem_type = elem->type();
293 
294  // Set the last_edge
295  last_edge = edge->type();
296 
297  // Initialize the edge shape functions
298  this->_fe_map->template init_edge_shape_functions<Dim> (this->qrule->get_points(), edge.get());
299  }
300 
301  // Compute the Jacobian*Weight on the face for integration
302  this->_fe_map->compute_edge_map (Dim, this->qrule->get_weights(), edge.get());
303 
304  // The shape functions correspond to the qrule
305  this->shapes_on_quadrature = true;
306  }
307 
308  // make a copy of the Jacobian for integration
309  const std::vector<Real> JxW_int(this->_fe_map->get_JxW());
310 
311  // Find where the integration points are located on the
312  // full element.
313  std::vector<Point> qp;
314  FEMap::inverse_map (Dim, elem, this->_fe_map->get_xyz(), qp, tolerance);
315 
316  // compute the shape function and derivative values
317  // at the points qp
318  this->reinit (elem, &qp);
319 
320  // copy back old data
321  this->_fe_map->get_JxW() = JxW_int;
322 }
323 
324 template <unsigned int Dim, FEFamily T>
325 void FE<Dim,T>::side_map (const Elem * elem,
326  const Elem * side,
327  const unsigned int s,
328  const std::vector<Point> & reference_side_points,
329  std::vector<Point> & reference_points)
330 {
331  // We're calculating mappings - we need at least first order info
332  this->calculate_phi = true;
333  this->determine_calculations();
334 
335  unsigned int side_p_level = elem->p_level();
336  if (elem->neighbor_ptr(s) != nullptr)
337  side_p_level = std::max(side_p_level, elem->neighbor_ptr(s)->p_level());
338 
339  if (side->type() != last_side ||
340  side_p_level != this->_p_level ||
341  !this->shapes_on_quadrature)
342  {
343  // Set the element type
344  this->elem_type = elem->type();
345  this->_p_level = side_p_level;
346 
347  // Set the last_side
348  last_side = side->type();
349 
350  // Initialize the face shape functions
351  this->_fe_map->template init_face_shape_functions<Dim>(reference_side_points, side);
352  }
353 
354  const unsigned int n_points =
355  cast_int<unsigned int>(reference_side_points.size());
356  reference_points.resize(n_points);
357  for (unsigned int i = 0; i < n_points; i++)
358  reference_points[i].zero();
359 
360  std::vector<unsigned int> elem_nodes_map;
361  elem_nodes_map.resize(side->n_nodes());
362  for (auto j : side->node_index_range())
363  for (auto i : elem->node_index_range())
364  if (side->node_id(j) == elem->node_id(i))
365  elem_nodes_map[j] = i;
366  std::vector<Point> refspace_nodes;
367  this->get_refspace_nodes(elem->type(), refspace_nodes);
368 
369  const std::vector<std::vector<Real>> & psi_map = this->_fe_map->get_psi();
370 
371  // sum over the nodes
372  for (auto i : index_range(psi_map))
373  {
374  const Point & side_node = refspace_nodes[elem_nodes_map[i]];
375  for (unsigned int p=0; p<n_points; p++)
376  reference_points[p].add_scaled (side_node, psi_map[i][p]);
377  }
378 }
379 
380 template<unsigned int Dim>
381 void FEMap::init_face_shape_functions(const std::vector<Point> & qp,
382  const Elem * side)
383 {
384  // Start logging the shape function initialization
385  LOG_SCOPE("init_face_shape_functions()", "FEMap");
386 
387  libmesh_assert(side);
388 
389  // We're calculating now!
390  this->determine_calculations();
391 
392  // The element type and order to use in
393  // the map
394  const FEFamily mapping_family = FEMap::map_fe_type(*side);
395  const Order mapping_order (side->default_order());
396  const ElemType mapping_elem_type (side->type());
397  const FEType map_fe_type(mapping_order, mapping_family);
398 
399  // The number of quadrature points.
400  const unsigned int n_qp = cast_int<unsigned int>(qp.size());
401 
402  const unsigned int n_mapping_shape_functions =
403  FEInterface::n_shape_functions(Dim, map_fe_type, mapping_elem_type);
404 
405  // resize the vectors to hold current data
406  // Psi are the shape functions used for the FE mapping
407  if (calculate_xyz)
408  this->psi_map.resize (n_mapping_shape_functions);
409 
410  if (Dim > 1)
411  {
412  if (calculate_dxyz)
413  this->dpsidxi_map.resize (n_mapping_shape_functions);
414 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
415  if (calculate_d2xyz)
416  this->d2psidxi2_map.resize (n_mapping_shape_functions);
417 #endif
418  }
419 
420  if (Dim == 3)
421  {
422  if (calculate_dxyz)
423  this->dpsideta_map.resize (n_mapping_shape_functions);
424 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
425  if (calculate_d2xyz)
426  {
427  this->d2psidxideta_map.resize (n_mapping_shape_functions);
428  this->d2psideta2_map.resize (n_mapping_shape_functions);
429  }
430 #endif
431  }
432 
433  FEInterface::shape_ptr shape_ptr =
435 
436  FEInterface::shape_deriv_ptr shape_deriv_ptr =
438 
439 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
440  FEInterface::shape_second_deriv_ptr shape_second_deriv_ptr =
442 #endif
443 
444  for (unsigned int i=0; i<n_mapping_shape_functions; i++)
445  {
446  // Allocate space to store the values of the shape functions
447  // and their first and second derivatives at the quadrature points.
448  if (calculate_xyz)
449  this->psi_map[i].resize (n_qp);
450  if (Dim > 1)
451  {
452  if (calculate_dxyz)
453  this->dpsidxi_map[i].resize (n_qp);
454 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
455  if (calculate_d2xyz)
456  this->d2psidxi2_map[i].resize (n_qp);
457 #endif
458  }
459  if (Dim == 3)
460  {
461  if (calculate_dxyz)
462  this->dpsideta_map[i].resize (n_qp);
463 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
464  if (calculate_d2xyz)
465  {
466  this->d2psidxideta_map[i].resize (n_qp);
467  this->d2psideta2_map[i].resize (n_qp);
468  }
469 #endif
470  }
471 
472 
473  // Compute the value of mapping shape function i, and its first
474  // and second derivatives at quadrature point p
475  for (unsigned int p=0; p<n_qp; p++)
476  {
477  if (calculate_xyz)
478  this->psi_map[i][p] = shape_ptr (side, mapping_order, i, qp[p], false);
479  if (Dim > 1)
480  {
481  if (calculate_dxyz)
482  this->dpsidxi_map[i][p] = shape_deriv_ptr (side, mapping_order, i, 0, qp[p], false);
483 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
484  if (calculate_d2xyz)
485  this->d2psidxi2_map[i][p] = shape_second_deriv_ptr(side, mapping_order, i, 0, qp[p], false);
486 #endif
487  }
488  // libMesh::out << "this->d2psidxi2_map["<<i<<"][p]=" << d2psidxi2_map[i][p] << std::endl;
489 
490  // If we are in 3D, then our sides are 2D faces.
491  // For the second derivatives, we must also compute the cross
492  // derivative d^2() / dxi deta
493  if (Dim == 3)
494  {
495  if (calculate_dxyz)
496  this->dpsideta_map[i][p] = shape_deriv_ptr (side, mapping_order, i, 1, qp[p], false);
497 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
498  if (calculate_d2xyz)
499  {
500  this->d2psidxideta_map[i][p] = shape_second_deriv_ptr(side, mapping_order, i, 1, qp[p], false);
501  this->d2psideta2_map[i][p] = shape_second_deriv_ptr(side, mapping_order, i, 2, qp[p], false);
502  }
503 #endif
504  }
505  }
506  }
507 }
508 
509 template<unsigned int Dim>
510 void FEMap::init_edge_shape_functions(const std::vector<Point> & qp,
511  const Elem * edge)
512 {
513  // Start logging the shape function initialization
514  LOG_SCOPE("init_edge_shape_functions()", "FEMap");
515 
516  libmesh_assert(edge);
517 
518  // We're calculating now!
519  this->determine_calculations();
520 
521  // The element type and order to use in
522  // the map
523  const FEFamily mapping_family = FEMap::map_fe_type(*edge);
524  const Order mapping_order (edge->default_order());
525  const ElemType mapping_elem_type (edge->type());
526  const FEType map_fe_type(mapping_order, mapping_family);
527 
528  // The number of quadrature points.
529  const unsigned int n_qp = cast_int<unsigned int>(qp.size());
530 
531  const unsigned int n_mapping_shape_functions =
532  FEInterface::n_shape_functions(Dim, map_fe_type, mapping_elem_type);
533 
534  // resize the vectors to hold current data
535  // Psi are the shape functions used for the FE mapping
536  if (calculate_xyz)
537  this->psi_map.resize (n_mapping_shape_functions);
538  if (calculate_dxyz)
539  this->dpsidxi_map.resize (n_mapping_shape_functions);
540 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
541  if (calculate_d2xyz)
542  this->d2psidxi2_map.resize (n_mapping_shape_functions);
543 #endif
544 
545  FEInterface::shape_ptr shape_ptr =
547 
548  FEInterface::shape_deriv_ptr shape_deriv_ptr =
550 
551 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
552  FEInterface::shape_second_deriv_ptr shape_second_deriv_ptr =
554 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
555 
556  for (unsigned int i=0; i<n_mapping_shape_functions; i++)
557  {
558  // Allocate space to store the values of the shape functions
559  // and their first and second derivatives at the quadrature points.
560  if (calculate_xyz)
561  this->psi_map[i].resize (n_qp);
562  if (calculate_dxyz)
563  this->dpsidxi_map[i].resize (n_qp);
564 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
565  if (calculate_d2xyz)
566  this->d2psidxi2_map[i].resize (n_qp);
567 #endif
568 
569  // Compute the value of mapping shape function i, and its first
570  // and second derivatives at quadrature point p
571  for (unsigned int p=0; p<n_qp; p++)
572  {
573  if (calculate_xyz)
574  this->psi_map[i][p] = shape_ptr (edge, mapping_order, i, qp[p], false);
575  if (calculate_dxyz)
576  this->dpsidxi_map[i][p] = shape_deriv_ptr (edge, mapping_order, i, 0, qp[p], false);
577 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
578  if (calculate_d2xyz)
579  this->d2psidxi2_map[i][p] = shape_second_deriv_ptr(edge, mapping_order, i, 0, qp[p], false);
580 #endif
581  }
582  }
583 }
584 
585 
586 
587 void FEMap::compute_face_map(int dim, const std::vector<Real> & qw,
588  const Elem * side)
589 {
590  libmesh_assert(side);
591 
592  // We're calculating now!
593  this->determine_calculations();
594 
595  LOG_SCOPE("compute_face_map()", "FEMap");
596 
597  // The number of quadrature points.
598  const unsigned int n_qp = cast_int<unsigned int>(qw.size());
599 
600  const FEFamily mapping_family = FEMap::map_fe_type(*side);
601  const Order mapping_order (side->default_order());
602  const FEType map_fe_type(mapping_order, mapping_family);
603  const ElemType mapping_elem_type (side->type());
604  const unsigned int n_mapping_shape_functions =
605  FEInterface::n_shape_functions(dim, map_fe_type, mapping_elem_type);
606 
607  switch (dim)
608  {
609  case 1:
610  {
611  // A 1D finite element, currently assumed to be in 1D space
612  // This means the boundary is a "0D finite element", a
613  // NODEELEM.
614 
615  // Resize the vectors to hold data at the quadrature points
616  {
617  if (calculate_xyz)
618  this->xyz.resize(n_qp);
619  if (calculate_dxyz)
620  normals.resize(n_qp);
621 
622  if (calculate_dxyz)
623  this->JxW.resize(n_qp);
624  }
625 
626  // If we have no quadrature points, there's nothing else to do
627  if (!n_qp)
628  break;
629 
630  // We need to look back at the full edge to figure out the normal
631  // vector
632  const Elem * elem = side->parent();
633  libmesh_assert (elem);
634  if (calculate_dxyz)
635  {
636  if (side->node_id(0) == elem->node_id(0))
637  normals[0] = Point(-1.);
638  else
639  {
640  libmesh_assert_equal_to (side->node_id(0),
641  elem->node_id(1));
642  normals[0] = Point(1.);
643  }
644  }
645 
646  // Calculate x at the point
647  if (calculate_xyz)
648  libmesh_assert_equal_to (this->psi_map.size(), 1);
649  // In the unlikely event we have multiple quadrature
650  // points, they'll be in the same place
651  for (unsigned int p=0; p<n_qp; p++)
652  {
653  if (calculate_xyz)
654  {
655  this->xyz[p].zero();
656  this->xyz[p].add_scaled (side->point(0), this->psi_map[0][p]);
657  }
658  if (calculate_dxyz)
659  {
660  normals[p] = normals[0];
661  this->JxW[p] = 1.0*qw[p];
662  }
663  }
664 
665  // done computing the map
666  break;
667  }
668 
669  case 2:
670  {
671  // A 2D finite element living in either 2D or 3D space.
672  // This means the boundary is a 1D finite element, i.e.
673  // and EDGE2 or EDGE3.
674  // Resize the vectors to hold data at the quadrature points
675  {
676  if (calculate_xyz)
677  this->xyz.resize(n_qp);
678  if (calculate_dxyz)
679  {
680  this->dxyzdxi_map.resize(n_qp);
681  this->tangents.resize(n_qp);
682  this->normals.resize(n_qp);
683 
684  this->JxW.resize(n_qp);
685  }
686 
687 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
688  if (calculate_d2xyz)
689  {
690  this->d2xyzdxi2_map.resize(n_qp);
691  this->curvatures.resize(n_qp);
692  }
693 #endif
694  }
695 
696  // Clear the entities that will be summed
697  // Compute the tangent & normal at the quadrature point
698  for (unsigned int p=0; p<n_qp; p++)
699  {
700  if (calculate_xyz)
701  this->xyz[p].zero();
702  if (calculate_dxyz)
703  {
704  this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
705  this->dxyzdxi_map[p].zero();
706  }
707 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
708  if (calculate_d2xyz)
709  this->d2xyzdxi2_map[p].zero();
710 #endif
711  }
712 
713  // compute x, dxdxi at the quadrature points
714  for (unsigned int i=0; i<n_mapping_shape_functions; i++) // sum over the nodes
715  {
716  const Point & side_point = side->point(i);
717 
718  for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
719  {
720  if (calculate_xyz)
721  this->xyz[p].add_scaled (side_point, this->psi_map[i][p]);
722  if (calculate_dxyz)
723  this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]);
724 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
725  if (calculate_d2xyz)
726  this->d2xyzdxi2_map[p].add_scaled(side_point, this->d2psidxi2_map[i][p]);
727 #endif
728  }
729  }
730 
731  // Compute the tangent & normal at the quadrature point
732  if (calculate_dxyz)
733  {
734  for (unsigned int p=0; p<n_qp; p++)
735  {
736  // The first tangent comes from just the edge's Jacobian
737  this->tangents[p][0] = this->dxyzdxi_map[p].unit();
738 
739 #if LIBMESH_DIM == 2
740  // For a 2D element living in 2D, the normal is given directly
741  // from the entries in the edge Jacobian.
742  this->normals[p] = (Point(this->dxyzdxi_map[p](1), -this->dxyzdxi_map[p](0), 0.)).unit();
743 
744 #elif LIBMESH_DIM == 3
745  // For a 2D element living in 3D, there is a second tangent.
746  // For the second tangent, we need to refer to the full
747  // element's (not just the edge's) Jacobian.
748  const Elem * elem = side->parent();
749  libmesh_assert(elem);
750 
751  // Inverse map xyz[p] to a reference point on the parent...
752  Point reference_point = FEMap::inverse_map(2, elem, this->xyz[p]);
753 
754  // Get dxyz/dxi and dxyz/deta from the parent map.
755  Point dx_dxi = FEMap::map_deriv (2, elem, 0, reference_point);
756  Point dx_deta = FEMap::map_deriv (2, elem, 1, reference_point);
757 
758  // The second tangent vector is formed by crossing these vectors.
759  tangents[p][1] = dx_dxi.cross(dx_deta).unit();
760 
761  // Finally, the normal in this case is given by crossing these
762  // two tangents.
763  normals[p] = tangents[p][0].cross(tangents[p][1]).unit();
764 #endif
765 
766 
767 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
768  // The curvature is computed via the familiar Frenet formula:
769  // curvature = [d^2(x) / d (xi)^2] dot [normal]
770  // For a reference, see:
771  // F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill, p. 310
772  //
773  // Note: The sign convention here is different from the
774  // 3D case. Concave-upward curves (smiles) have a positive
775  // curvature. Concave-downward curves (frowns) have a
776  // negative curvature. Be sure to take that into account!
777  if (calculate_d2xyz)
778  {
779  const Real numerator = this->d2xyzdxi2_map[p] * this->normals[p];
780  const Real denominator = this->dxyzdxi_map[p].norm_sq();
781  libmesh_assert_not_equal_to (denominator, 0);
782  curvatures[p] = numerator / denominator;
783  }
784 #endif
785  }
786 
787  // compute the jacobian at the quadrature points
788  for (unsigned int p=0; p<n_qp; p++)
789  {
790  const Real the_jac = this->dxyzdxi_map[p].norm();
791 
792  libmesh_assert_greater (the_jac, 0.);
793 
794  this->JxW[p] = the_jac*qw[p];
795  }
796  }
797 
798  // done computing the map
799  break;
800  }
801 
802 
803 
804  case 3:
805  {
806  // A 3D finite element living in 3D space.
807  // Resize the vectors to hold data at the quadrature points
808  {
809  if (calculate_xyz)
810  this->xyz.resize(n_qp);
811  if (calculate_dxyz)
812  {
813  this->dxyzdxi_map.resize(n_qp);
814  this->dxyzdeta_map.resize(n_qp);
815  this->tangents.resize(n_qp);
816  this->normals.resize(n_qp);
817  this->JxW.resize(n_qp);
818  }
819 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
820  if (calculate_d2xyz)
821  {
822  this->d2xyzdxi2_map.resize(n_qp);
823  this->d2xyzdxideta_map.resize(n_qp);
824  this->d2xyzdeta2_map.resize(n_qp);
825  this->curvatures.resize(n_qp);
826  }
827 #endif
828  }
829 
830  // Clear the entities that will be summed
831  for (unsigned int p=0; p<n_qp; p++)
832  {
833  if (calculate_xyz)
834  this->xyz[p].zero();
835  if (calculate_dxyz)
836  {
837  this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D
838  this->dxyzdxi_map[p].zero();
839  this->dxyzdeta_map[p].zero();
840  }
841 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
842  if (calculate_d2xyz)
843  {
844  this->d2xyzdxi2_map[p].zero();
845  this->d2xyzdxideta_map[p].zero();
846  this->d2xyzdeta2_map[p].zero();
847  }
848 #endif
849  }
850 
851  // compute x, dxdxi at the quadrature points
852  for (unsigned int i=0; i<n_mapping_shape_functions; i++) // sum over the nodes
853  {
854  const Point & side_point = side->point(i);
855 
856  for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
857  {
858  if (calculate_xyz)
859  this->xyz[p].add_scaled (side_point, this->psi_map[i][p]);
860  if (calculate_dxyz)
861  {
862  this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]);
863  this->dxyzdeta_map[p].add_scaled(side_point, this->dpsideta_map[i][p]);
864  }
865 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
866  if (calculate_d2xyz)
867  {
868  this->d2xyzdxi2_map[p].add_scaled (side_point, this->d2psidxi2_map[i][p]);
869  this->d2xyzdxideta_map[p].add_scaled(side_point, this->d2psidxideta_map[i][p]);
870  this->d2xyzdeta2_map[p].add_scaled (side_point, this->d2psideta2_map[i][p]);
871  }
872 #endif
873  }
874  }
875 
876  // Compute the tangents, normal, and curvature at the quadrature point
877  if (calculate_dxyz)
878  {
879  for (unsigned int p=0; p<n_qp; p++)
880  {
881  const Point n = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]);
882  this->normals[p] = n.unit();
883  this->tangents[p][0] = this->dxyzdxi_map[p].unit();
884  this->tangents[p][1] = n.cross(this->dxyzdxi_map[p]).unit();
885 
886 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
887  if (calculate_d2xyz)
888  {
889  // Compute curvature using the typical nomenclature
890  // of the first and second fundamental forms.
891  // For reference, see:
892  // 1) http://mathworld.wolfram.com/MeanCurvature.html
893  // (note -- they are using inward normal)
894  // 2) F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill
895  const Real L = -this->d2xyzdxi2_map[p] * this->normals[p];
896  const Real M = -this->d2xyzdxideta_map[p] * this->normals[p];
897  const Real N = -this->d2xyzdeta2_map[p] * this->normals[p];
898  const Real E = this->dxyzdxi_map[p].norm_sq();
899  const Real F = this->dxyzdxi_map[p] * this->dxyzdeta_map[p];
900  const Real G = this->dxyzdeta_map[p].norm_sq();
901 
902  const Real numerator = E*N -2.*F*M + G*L;
903  const Real denominator = E*G - F*F;
904  libmesh_assert_not_equal_to (denominator, 0.);
905  curvatures[p] = 0.5*numerator/denominator;
906  }
907 #endif
908  }
909 
910  // compute the jacobian at the quadrature points, see
911  // http://sp81.msi.umn.edu:999/fluent/fidap/help/theory/thtoc.htm
912  for (unsigned int p=0; p<n_qp; p++)
913  {
914  const Real g11 = (dxdxi_map(p)*dxdxi_map(p) +
915  dydxi_map(p)*dydxi_map(p) +
916  dzdxi_map(p)*dzdxi_map(p));
917 
918  const Real g12 = (dxdxi_map(p)*dxdeta_map(p) +
919  dydxi_map(p)*dydeta_map(p) +
920  dzdxi_map(p)*dzdeta_map(p));
921 
922  const Real g21 = g12;
923 
924  const Real g22 = (dxdeta_map(p)*dxdeta_map(p) +
925  dydeta_map(p)*dydeta_map(p) +
926  dzdeta_map(p)*dzdeta_map(p));
927 
928 
929  const Real the_jac = std::sqrt(g11*g22 - g12*g21);
930 
931  libmesh_assert_greater (the_jac, 0.);
932 
933  this->JxW[p] = the_jac*qw[p];
934  }
935  }
936 
937  // done computing the map
938  break;
939  }
940 
941 
942  default:
943  libmesh_error_msg("Invalid dimension dim = " << dim);
944  }
945 }
946 
947 
948 
949 
951  const std::vector<Real> & qw,
952  const Elem * edge)
953 {
954  libmesh_assert(edge);
955 
956  if (dim == 2)
957  {
958  // A 2D finite element living in either 2D or 3D space.
959  // The edges here are the sides of the element, so the
960  // (misnamed) compute_face_map function does what we want
961  this->compute_face_map(dim, qw, edge);
962  return;
963  }
964 
965  libmesh_assert_equal_to (dim, 3); // 1D is unnecessary and currently unsupported
966 
967  LOG_SCOPE("compute_edge_map()", "FEMap");
968 
969  // We're calculating now!
970  this->determine_calculations();
971 
972  // The number of quadrature points.
973  const unsigned int n_qp = cast_int<unsigned int>(qw.size());
974 
975  // Resize the vectors to hold data at the quadrature points
976  if (calculate_xyz)
977  this->xyz.resize(n_qp);
978  if (calculate_dxyz)
979  {
980  this->dxyzdxi_map.resize(n_qp);
981  this->dxyzdeta_map.resize(n_qp);
982  this->tangents.resize(n_qp);
983  this->normals.resize(n_qp);
984  this->JxW.resize(n_qp);
985  }
986 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
987  if (calculate_d2xyz)
988  {
989  this->d2xyzdxi2_map.resize(n_qp);
990  this->d2xyzdxideta_map.resize(n_qp);
991  this->d2xyzdeta2_map.resize(n_qp);
992  this->curvatures.resize(n_qp);
993  }
994 #endif
995 
996  // Clear the entities that will be summed
997  for (unsigned int p=0; p<n_qp; p++)
998  {
999  if (calculate_xyz)
1000  this->xyz[p].zero();
1001  if (calculate_dxyz)
1002  {
1003  this->tangents[p].resize(1);
1004  this->dxyzdxi_map[p].zero();
1005  this->dxyzdeta_map[p].zero();
1006  }
1007 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
1008  if (calculate_d2xyz)
1009  {
1010  this->d2xyzdxi2_map[p].zero();
1011  this->d2xyzdxideta_map[p].zero();
1012  this->d2xyzdeta2_map[p].zero();
1013  }
1014 #endif
1015  }
1016 
1017  // compute x, dxdxi at the quadrature points
1018  for (unsigned int i=0,
1019  psi_map_size=cast_int<unsigned int>(psi_map.size());
1020  i != psi_map_size; i++) // sum over the nodes
1021  {
1022  const Point & edge_point = edge->point(i);
1023 
1024  for (unsigned int p=0; p<n_qp; p++) // for each quadrature point...
1025  {
1026  if (calculate_xyz)
1027  this->xyz[p].add_scaled (edge_point, this->psi_map[i][p]);
1028  if (calculate_dxyz)
1029  this->dxyzdxi_map[p].add_scaled (edge_point, this->dpsidxi_map[i][p]);
1030 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
1031  if (calculate_d2xyz)
1032  this->d2xyzdxi2_map[p].add_scaled (edge_point, this->d2psidxi2_map[i][p]);
1033 #endif
1034  }
1035  }
1036 
1037  // Compute the tangents at the quadrature point
1038  // FIXME: normals (plural!) and curvatures are uncalculated
1039  if (calculate_dxyz)
1040  for (unsigned int p=0; p<n_qp; p++)
1041  {
1042  const Point n = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]);
1043  this->tangents[p][0] = this->dxyzdxi_map[p].unit();
1044 
1045  // compute the jacobian at the quadrature points
1046  const Real the_jac = std::sqrt(this->dxdxi_map(p)*this->dxdxi_map(p) +
1047  this->dydxi_map(p)*this->dydxi_map(p) +
1048  this->dzdxi_map(p)*this->dzdxi_map(p));
1049 
1050  libmesh_assert_greater (the_jac, 0.);
1051 
1052  this->JxW[p] = the_jac*qw[p];
1053  }
1054 }
1055 
1056 
1057 // Explicit FEMap Instantiations
1058 FACE_EDGE_SHAPE_ERROR(0,init_face_shape_functions)
1059 template void FEMap::init_face_shape_functions<1>(const std::vector<Point> &, const Elem *);
1060 template void FEMap::init_face_shape_functions<2>(const std::vector<Point> &, const Elem *);
1061 template void FEMap::init_face_shape_functions<3>(const std::vector<Point> &, const Elem *);
1062 
1063 FACE_EDGE_SHAPE_ERROR(0,init_edge_shape_functions)
1064 template void FEMap::init_edge_shape_functions<1>(const std::vector<Point> &, const Elem *);
1065 template void FEMap::init_edge_shape_functions<2>(const std::vector<Point> &, const Elem *);
1066 template void FEMap::init_edge_shape_functions<3>(const std::vector<Point> &, const Elem *);
1067 
1068 //--------------------------------------------------------------
1069 // Explicit FE instantiations
1070 #define REINIT_AND_SIDE_MAPS(_type) \
1071 template void FE<1,_type>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const); \
1072 template void FE<1,_type>::side_map(Elem const *, Elem const *, const unsigned int, const std::vector<Point> &, std::vector<Point> &); \
1073 template void FE<2,_type>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const); \
1074 template void FE<2,_type>::side_map(Elem const *, Elem const *, const unsigned int, const std::vector<Point> &, std::vector<Point> &); \
1075 template void FE<2,_type>::edge_reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const); \
1076 template void FE<3,_type>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const); \
1077 template void FE<3,_type>::side_map(Elem const *, Elem const *, const unsigned int, const std::vector<Point> &, std::vector<Point> &); \
1078 template void FE<3,_type>::edge_reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const)
1079 
1080 REINIT_AND_SIDE_MAPS(LAGRANGE);
1081 REINIT_AND_SIDE_MAPS(LAGRANGE_VEC);
1082 REINIT_AND_SIDE_MAPS(L2_LAGRANGE);
1083 REINIT_AND_SIDE_MAPS(HIERARCHIC);
1084 REINIT_AND_SIDE_MAPS(L2_HIERARCHIC);
1085 REINIT_AND_SIDE_MAPS(CLOUGH);
1086 REINIT_AND_SIDE_MAPS(HERMITE);
1087 REINIT_AND_SIDE_MAPS(MONOMIAL);
1088 REINIT_AND_SIDE_MAPS(MONOMIAL_VEC);
1089 REINIT_AND_SIDE_MAPS(SCALAR);
1090 REINIT_AND_SIDE_MAPS(XYZ);
1091 
1092 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
1093 REINIT_AND_SIDE_MAPS(BERNSTEIN);
1094 REINIT_AND_SIDE_MAPS(SZABAB);
1095 REINIT_AND_SIDE_MAPS(RATIONAL_BERNSTEIN);
1096 #endif
1097 
1098 template void FE<2,SUBDIVISION>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const);
1099 template void FE<2,NEDELEC_ONE>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const);
1100 template void FE<2,NEDELEC_ONE>::side_map(Elem const *, Elem const *, const unsigned int, const std::vector<Point> &, std::vector<Point> &);
1101 template void FE<2,NEDELEC_ONE>::edge_reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const);
1102 
1103 template void FE<3,NEDELEC_ONE>::reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const);
1104 template void FE<3,NEDELEC_ONE>::side_map(Elem const *, Elem const *, const unsigned int, const std::vector<Point> &, std::vector<Point> &);
1105 template void FE<3,NEDELEC_ONE>::edge_reinit(Elem const *, unsigned int, Real, const std::vector<Point> * const, const std::vector<Real> * const);
1106 
1107 // Intel 9.1 complained it needed this in devel mode.
1108 //template void FE<2,XYZ>::init_face_shape_functions(const std::vector<Point> &, const Elem *);
1109 //template void FE<3,XYZ>::init_face_shape_functions(const std::vector<Point> &, const Elem *);
1110 
1111 } // namespace libMesh
libMesh::FEMap::d2psidxi2_map
std::vector< std::vector< Real > > d2psidxi2_map
Map for the second derivatives (in xi) of the side shape functions.
Definition: fe_map.h:926
libMesh::FEInterface::shape_function
static shape_ptr shape_function(const unsigned int dim, const FEType &fe_t)
Definition: fe_interface.C:838
libMesh::FEMap::calculate_d2xyz
bool calculate_d2xyz
Should we calculate mapping hessians?
Definition: fe_map.h:995
libMesh::FEMap::dydeta_map
Real dydeta_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:675
libMesh::FEInterface::n_shape_functions
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:446
libMesh::REINIT_ERROR
REINIT_ERROR(1, HERMITE, edge_reinit)
Definition: fe_boundary.C:91
libMesh::CLOUGH
Definition: enum_fe_family.h:53
libMesh::Elem::build_side_ptr
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
libMesh::L2_HIERARCHIC
Definition: enum_fe_family.h:40
libMesh::Elem::n_nodes
virtual unsigned int n_nodes() const =0
libMesh::FEMap::dpsidxi_map
std::vector< std::vector< Real > > dpsidxi_map
Map for the derivative of the side functions, d(psi)/d(xi).
Definition: fe_map.h:911
libMesh::FEMap::map_deriv
static Point map_deriv(const unsigned int dim, const Elem *elem, const unsigned int j, const Point &reference_point)
Definition: fe_map.C:2076
libMesh::HERMITE
Definition: enum_fe_family.h:54
libMesh::FEMap::calculate_xyz
bool calculate_xyz
Should we calculate physical point locations?
Definition: fe_map.h:983
libMesh::FEMap::d2xyzdxi2_map
std::vector< RealGradient > d2xyzdxi2_map
Vector of second partial derivatives in xi: d^2(x)/d(xi)^2, d^2(y)/d(xi)^2, d^2(z)/d(xi)^2.
Definition: fe_map.h:738
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::XYZ
Definition: enum_fe_family.h:46
libMesh::ERRORS_IN_0D
ERRORS_IN_0D(ERRORS_IN_0D(HERMITE) ERRORS_IN_0D(HIERARCHIC) ERRORS_IN_0D(L2_HIERARCHIC) ERRORS_IN_0D(LAGRANGE) ERRORS_IN_0D(L2_LAGRANGE) ERRORS_IN_0D(LAGRANGE_VEC) ERRORS_IN_0D(MONOMIAL) ERRORS_IN_0D(MONOMIAL_VEC) ERRORS_IN_0D(NEDELEC_ONE) ERRORS_IN_0D(SCALAR) ERRORS_IN_0D(XYZ)#ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPESERRORS_IN_0D(BERNSTEIN) ERRORS_IN_0D() ERRORS_IN_0D(RATIONAL_BERNSTEIN)#endifREINIT_ERROR(1 CLOUGH)
Definition: fe_boundary.C:70
libMesh::Order
Order
Definition: enum_order.h:40
libMesh::FEMap::JxW
std::vector< Real > JxW
Jacobian*Weight values at quadrature points.
Definition: fe_map.h:972
libMesh::FEMap::dxdxi_map
Real dxdxi_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:643
libMesh::FEInterface::shape_deriv_function
static shape_deriv_ptr shape_deriv_function(const unsigned int dim, const FEType &fe_t)
Definition: fe_interface.C:916
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::MONOMIAL_VEC
Definition: enum_fe_family.h:62
libMesh::Elem::p_level
unsigned int p_level() const
Definition: elem.h:2512
libMesh::Elem::node_index_range
IntRange< unsigned short > node_index_range() const
Definition: elem.h:2170
libMesh::FE::reinit
virtual void reinit(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr) override
This is at the core of this class.
Definition: fe.C:129
libMesh::FEMap::dxyzdeta_map
std::vector< RealGradient > dxyzdeta_map
Vector of partial derivatives: d(x)/d(eta), d(y)/d(eta), d(z)/d(eta)
Definition: fe_map.h:724
libMesh::FEMap::dydxi_map
Real dydxi_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:651
libMesh::FEInterface::shape_ptr
Real(* shape_ptr)(const Elem *elem, const Order o, const unsigned int i, const Point &p, const bool add_p_level)
Definition: fe_interface.h:296
libMesh::FEMap::normals
std::vector< Point > normals
Normal vectors on boundary at quadrature points.
Definition: fe_map.h:952
libMesh::FEMap::xyz
std::vector< Point > xyz
The spatial locations of the quadrature points.
Definition: fe_map.h:712
libMesh::FEMap::init_face_shape_functions
void init_face_shape_functions(const std::vector< Point > &qp, const Elem *side)
Initializes the reference to physical element map for a side.
Definition: fe_boundary.C:381
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::Elem::point
const Point & point(const unsigned int i) const
Definition: elem.h:1955
libMesh::zero
const Number zero
.
Definition: libmesh.h:243
libMesh::SZABAB
Definition: enum_fe_family.h:44
libMesh::FEMap::compute_face_map
virtual void compute_face_map(int dim, const std::vector< Real > &qw, const Elem *side)
Same as compute_map, but for a side.
Definition: fe_boundary.C:587
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::FEMap::determine_calculations
void determine_calculations()
Determine which values are to be calculated.
Definition: fe_map.h:621
libMesh::SIDEMAP_ERROR
SIDEMAP_ERROR(1, NEDELEC_ONE, side_map)
Definition: fe_boundary.C:103
libMesh::FEMap::inverse_map
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
Definition: fe_map.C:1622
libMesh::FEMap::dpsideta_map
std::vector< std::vector< Real > > dpsideta_map
Map for the derivative of the side function, d(psi)/d(eta).
Definition: fe_map.h:917
libMesh::FEMap::tangents
std::vector< std::vector< Point > > tangents
Tangent vectors on boundary at quadrature points.
Definition: fe_map.h:947
libMesh::FEMap::psi_map
std::vector< std::vector< Real > > psi_map
Map for the side shape functions, psi.
Definition: fe_map.h:905
libMesh::FE::edge_reinit
virtual void edge_reinit(const Elem *elem, const unsigned int edge, const Real tolerance=TOLERANCE, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr) override
Reinitializes all the physical element-dependent data based on the edge.
Definition: fe_boundary.C:232
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::FEMap::calculate_dxyz
bool calculate_dxyz
Should we calculate mapping gradients?
Definition: fe_map.h:988
libMesh::Elem::default_order
virtual Order default_order() const =0
libMesh::FEMap::d2psideta2_map
std::vector< std::vector< Real > > d2psideta2_map
Map for the second derivatives (in eta) of the side shape functions.
Definition: fe_map.h:940
libMesh::FEMap::compute_edge_map
void compute_edge_map(int dim, const std::vector< Real > &qw, const Elem *side)
Same as before, but for an edge.
Definition: fe_boundary.C:950
libMesh::FEMap::dzdeta_map
Real dzdeta_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:683
libMesh::FEMap::map_fe_type
static FEFamily map_fe_type(const Elem &elem)
Definition: fe_map.C:47
libMesh::RATIONAL_BERNSTEIN
Definition: enum_fe_family.h:64
libMesh::BERNSTEIN
Definition: enum_fe_family.h:43
libMesh::FEInterface::shape_deriv_ptr
Real(* shape_deriv_ptr)(const Elem *elem, const Order o, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level)
Definition: fe_interface.h:345
libMesh::HIERARCHIC
Definition: enum_fe_family.h:37
libMesh::MONOMIAL
Definition: enum_fe_family.h:39
libMesh::Elem::parent
const Elem * parent() const
Definition: elem.h:2434
libMesh::FEMap::init_edge_shape_functions
void init_edge_shape_functions(const std::vector< Point > &qp, const Elem *edge)
Same as before, but for an edge.
Definition: fe_boundary.C:510
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::TypeVector::unit
TypeVector< T > unit() const
Definition: type_vector.h:1158
libMesh::FEFamily
FEFamily
Definition: enum_fe_family.h:34
libMesh::NEDELEC_ONE
Definition: enum_fe_family.h:61
libMesh::FEInterface::shape_second_deriv_ptr
Real(* shape_second_deriv_ptr)(const Elem *elem, const Order o, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level)
Definition: fe_interface.h:409
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
libMesh::L2_LAGRANGE
Definition: enum_fe_family.h:41
libMesh::LAGRANGE_VEC
Definition: enum_fe_family.h:60
libMesh::LAGRANGE
Definition: enum_fe_family.h:36
libMesh::FEMap::dzdxi_map
Real dzdxi_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:659
libMesh::SCALAR
Definition: enum_fe_family.h:58
libMesh::Elem::neighbor_ptr
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2085
libMesh::TypeVector::cross
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
Definition: type_vector.h:920
libMesh::Elem::node_id
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1977
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::FEMap::dxdeta_map
Real dxdeta_map(const unsigned int p) const
Used in FEMap::compute_map(), which should be be usable in derived classes, and therefore protected.
Definition: fe_map.h:667
libMesh::FEMap::dxyzdxi_map
std::vector< RealGradient > dxyzdxi_map
Vector of partial derivatives: d(x)/d(xi), d(y)/d(xi), d(z)/d(xi)
Definition: fe_map.h:718
libMesh::Elem::build_edge_ptr
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i)=0
libMesh::FEInterface::shape_second_deriv_function
static shape_second_deriv_ptr shape_second_deriv_function(const unsigned int dim, const FEType &fe_t)
Definition: fe_interface.C:989
libMesh::FE::side_map
virtual void side_map(const Elem *elem, const Elem *side, const unsigned int s, const std::vector< Point > &reference_side_points, std::vector< Point > &reference_points) override
Computes the reference space quadrature points on the side of an element based on the side quadrature...
Definition: fe_boundary.C:325
libMesh::Elem::type
virtual ElemType type() const =0
libMesh::FEMap::d2xyzdxideta_map
std::vector< RealGradient > d2xyzdxideta_map
Vector of mixed second partial derivatives in xi-eta: d^2(x)/d(xi)d(eta) d^2(y)/d(xi)d(eta) d^2(z)/d(...
Definition: fe_map.h:744
libMesh::FEMap::d2xyzdeta2_map
std::vector< RealGradient > d2xyzdeta2_map
Vector of second partial derivatives in eta: d^2(x)/d(eta)^2.
Definition: fe_map.h:750
libMesh::ElemType
ElemType
Defines an enum for geometric element types.
Definition: enum_elem_type.h:33
libMesh::FEMap::d2psidxideta_map
std::vector< std::vector< Real > > d2psidxideta_map
Map for the second (cross) derivatives in xi, eta of the side shape functions.
Definition: fe_map.h:933
libMesh::FEMap::curvatures
std::vector< Real > curvatures
The mean curvature (= one half the sum of the principal curvatures) on the boundary at the quadrature...
Definition: fe_map.h:960