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);