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"
40 #define REINIT_ERROR(_dim, _type, _func) \
42 void FE<_dim,_type>::_func(const Elem *, \
45 const std::vector<Point> * const, \
46 const std::vector<Real> * const)
48 #define SIDEMAP_ERROR(_dim, _type, _func) \
50 void FE<_dim,_type>::_func(const Elem *, \
53 const std::vector<Point> &, \
56 #define FACE_EDGE_SHAPE_ERROR(_dim, _func) \
58 void FEMap::_func<_dim>(const std::vector<Point> &, \
61 libmesh_error_msg("ERROR: This method makes no sense for low-D elements!"); \
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!"); }
83 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
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!"); }
94 REINIT_ERROR(1,
LAGRANGE, edge_reinit) { libmesh_error_msg(
"ERROR: Cannot edge_reinit 1D 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!"); }
100 REINIT_ERROR(1,
SCALAR, edge_reinit) { libmesh_error_msg(
"ERROR: Cannot edge_reinit 1D SCALAR elements!"); }
104 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
106 REINIT_ERROR(1,
SZABAB, edge_reinit) { libmesh_error_msg(
"ERROR: Cannot edge_reinit 1D SZABAB elements!"); }
113 template <
unsigned int Dim, FEFamily T>
115 const unsigned int s,
117 const std::vector<Point> *
const pts,
118 const std::vector<Real> *
const weights)
128 this->_fe_map->calculations_started =
false;
129 this->_fe_map->get_JxW();
130 this->_fe_map->get_xyz();
131 this->determine_calculations();
138 unsigned int side_p_level = elem->
p_level();
147 this->shapes_on_quadrature =
false;
150 this->_fe_map->template init_face_shape_functions<Dim>(*pts, side.get());
153 if (weights !=
nullptr)
155 this->_fe_map->compute_face_map (Dim, *weights, side.get());
159 std::vector<Real> dummy_weights (pts->size(), 1.);
160 this->_fe_map->compute_face_map (Dim, dummy_weights, side.get());
168 this->qrule->init(side->type(), side_p_level);
170 if (this->qrule->shapes_need_reinit())
171 this->shapes_on_quadrature =
false;
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)
183 this->elem_type = elem->
type();
186 last_side = side->type();
189 this->_p_level = side_p_level;
192 this->_fe_map->template init_face_shape_functions<Dim>(this->qrule->get_points(), side.get());
196 this->_fe_map->compute_face_map (Dim, this->qrule->get_weights(), side.get());
199 this->shapes_on_quadrature =
true;
203 const std::vector<Real> JxW_int(this->_fe_map->get_JxW());
206 bool shapes_on_quadrature_side = this->shapes_on_quadrature;
210 const std::vector<Point> * ref_qp;
214 ref_qp = &this->qrule->get_points();
216 std::vector<Point> qp;
217 this->side_map(elem, side.get(), s, *ref_qp, qp);
221 this->reinit (elem, &qp);
223 this->shapes_on_quadrature = shapes_on_quadrature_side;
226 this->_fe_map->get_JxW() = JxW_int;
231 template <
unsigned int Dim, FEFamily T>
233 const unsigned int e,
234 const Real tolerance,
235 const std::vector<Point> *
const pts,
236 const std::vector<Real> *
const weights)
241 libmesh_assert_not_equal_to (Dim, 1);
246 this->_fe_map->calculations_started =
false;
247 this->_fe_map->get_JxW();
248 this->_fe_map->get_xyz();
249 this->determine_calculations();
259 this->shapes_on_quadrature =
false;
262 this->_fe_map->template init_edge_shape_functions<Dim> (*pts, edge.get());
265 if (weights !=
nullptr)
267 this->_fe_map->compute_edge_map (Dim, *weights, edge.get());
271 std::vector<Real> dummy_weights (pts->size(), 1.);
272 this->_fe_map->compute_edge_map (Dim, dummy_weights, edge.get());
280 this->qrule->init(edge->type(), elem->
p_level());
282 if (this->qrule->shapes_need_reinit())
283 this->shapes_on_quadrature =
false;
286 if ((this->get_type() != elem->
type()) ||
287 (edge->type() != static_cast<int>(last_edge)) ||
288 this->shapes_need_reinit() ||
289 !this->shapes_on_quadrature)
292 this->elem_type = elem->
type();
295 last_edge = edge->type();
298 this->_fe_map->template init_edge_shape_functions<Dim> (this->qrule->get_points(), edge.get());
302 this->_fe_map->compute_edge_map (Dim, this->qrule->get_weights(), edge.get());
305 this->shapes_on_quadrature =
true;
309 const std::vector<Real> JxW_int(this->_fe_map->get_JxW());
313 std::vector<Point> qp;
318 this->reinit (elem, &qp);
321 this->_fe_map->get_JxW() = JxW_int;
324 template <
unsigned int Dim, FEFamily T>
327 const unsigned int s,
328 const std::vector<Point> & reference_side_points,
329 std::vector<Point> & reference_points)
332 this->calculate_phi =
true;
333 this->determine_calculations();
335 unsigned int side_p_level = elem->
p_level();
339 if (side->
type() != last_side ||
340 side_p_level != this->_p_level ||
341 !this->shapes_on_quadrature)
344 this->elem_type = elem->
type();
345 this->_p_level = side_p_level;
348 last_side = side->
type();
351 this->_fe_map->template init_face_shape_functions<Dim>(reference_side_points, side);
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();
360 std::vector<unsigned int> elem_nodes_map;
361 elem_nodes_map.resize(side->
n_nodes());
365 elem_nodes_map[j] = i;
366 std::vector<Point> refspace_nodes;
367 this->get_refspace_nodes(elem->
type(), refspace_nodes);
369 const std::vector<std::vector<Real>> & psi_map = this->_fe_map->get_psi();
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]);
380 template<
unsigned int Dim>
385 LOG_SCOPE(
"init_face_shape_functions()",
"FEMap");
400 const unsigned int n_qp = cast_int<unsigned int>(qp.size());
402 const unsigned int n_mapping_shape_functions =
408 this->
psi_map.resize (n_mapping_shape_functions);
413 this->
dpsidxi_map.resize (n_mapping_shape_functions);
414 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
424 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
439 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
444 for (
unsigned int i=0; i<n_mapping_shape_functions; i++)
449 this->
psi_map[i].resize (n_qp);
454 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
463 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
475 for (
unsigned int p=0; p<n_qp; p++)
478 this->
psi_map[i][p] = shape_ptr (side, mapping_order, i, qp[p],
false);
482 this->
dpsidxi_map[i][p] = shape_deriv_ptr (side, mapping_order, i, 0, qp[p],
false);
483 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
485 this->
d2psidxi2_map[i][p] = shape_second_deriv_ptr(side, mapping_order, i, 0, qp[p],
false);
496 this->
dpsideta_map[i][p] = shape_deriv_ptr (side, mapping_order, i, 1, qp[p],
false);
497 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
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);
509 template<
unsigned int Dim>
514 LOG_SCOPE(
"init_edge_shape_functions()",
"FEMap");
529 const unsigned int n_qp = cast_int<unsigned int>(qp.size());
531 const unsigned int n_mapping_shape_functions =
537 this->
psi_map.resize (n_mapping_shape_functions);
539 this->
dpsidxi_map.resize (n_mapping_shape_functions);
540 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
551 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
554 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
556 for (
unsigned int i=0; i<n_mapping_shape_functions; i++)
561 this->
psi_map[i].resize (n_qp);
564 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
571 for (
unsigned int p=0; p<n_qp; p++)
574 this->
psi_map[i][p] = shape_ptr (edge, mapping_order, i, qp[p],
false);
576 this->
dpsidxi_map[i][p] = shape_deriv_ptr (edge, mapping_order, i, 0, qp[p],
false);
577 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
579 this->
d2psidxi2_map[i][p] = shape_second_deriv_ptr(edge, mapping_order, i, 0, qp[p],
false);
595 LOG_SCOPE(
"compute_face_map()",
"FEMap");
598 const unsigned int n_qp = cast_int<unsigned int>(qw.size());
604 const unsigned int n_mapping_shape_functions =
618 this->
xyz.resize(n_qp);
623 this->
JxW.resize(n_qp);
640 libmesh_assert_equal_to (side->
node_id(0),
648 libmesh_assert_equal_to (this->
psi_map.size(), 1);
651 for (
unsigned int p=0; p<n_qp; p++)
661 this->
JxW[p] = 1.0*qw[p];
677 this->
xyz.resize(n_qp);
684 this->
JxW.resize(n_qp);
687 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
698 for (
unsigned int p=0; p<n_qp; p++)
704 this->
tangents[p].resize(LIBMESH_DIM-1);
707 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
714 for (
unsigned int i=0; i<n_mapping_shape_functions; i++)
718 for (
unsigned int p=0; p<n_qp; p++)
721 this->
xyz[p].add_scaled (side_point, this->
psi_map[i][p]);
724 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
734 for (
unsigned int p=0; p<n_qp; p++)
744 #elif LIBMESH_DIM == 3
767 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
781 libmesh_assert_not_equal_to (denominator, 0);
788 for (
unsigned int p=0; p<n_qp; p++)
792 libmesh_assert_greater (the_jac, 0.);
794 this->
JxW[p] = the_jac*qw[p];
810 this->
xyz.resize(n_qp);
817 this->
JxW.resize(n_qp);
819 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
831 for (
unsigned int p=0; p<n_qp; p++)
837 this->
tangents[p].resize(LIBMESH_DIM-1);
841 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
852 for (
unsigned int i=0; i<n_mapping_shape_functions; i++)
856 for (
unsigned int p=0; p<n_qp; p++)
859 this->
xyz[p].add_scaled (side_point, this->
psi_map[i][p]);
865 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
879 for (
unsigned int p=0; p<n_qp; p++)
886 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
900 const Real G = this->dxyzdeta_map[p].norm_sq();
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.);
912 for (
unsigned int p=0; p<n_qp; p++)
922 const Real g21 = g12;
931 libmesh_assert_greater (the_jac, 0.);
933 this->
JxW[p] = the_jac*qw[p];
943 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
951 const std::vector<Real> & qw,
965 libmesh_assert_equal_to (
dim, 3);
967 LOG_SCOPE(
"compute_edge_map()",
"FEMap");
973 const unsigned int n_qp = cast_int<unsigned int>(qw.size());
977 this->
xyz.resize(n_qp);
984 this->
JxW.resize(n_qp);
986 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
997 for (
unsigned int p=0; p<n_qp; p++)
1000 this->
xyz[p].zero();
1007 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
1018 for (
unsigned int i=0,
1019 psi_map_size=cast_int<unsigned int>(
psi_map.size());
1020 i != psi_map_size; i++)
1024 for (
unsigned int p=0; p<n_qp; p++)
1027 this->
xyz[p].add_scaled (edge_point, this->
psi_map[i][p]);
1030 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
1040 for (
unsigned int p=0; p<n_qp; p++)
1050 libmesh_assert_greater (the_jac, 0.);
1052 this->
JxW[p] = the_jac*qw[p];
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 *);
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 *);
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)
1085 REINIT_AND_SIDE_MAPS(
CLOUGH);
1086 REINIT_AND_SIDE_MAPS(
HERMITE);
1089 REINIT_AND_SIDE_MAPS(
SCALAR);
1090 REINIT_AND_SIDE_MAPS(
XYZ);
1092 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
1094 REINIT_AND_SIDE_MAPS(
SZABAB);