21 #include "libmesh/elem.h"    22 #include "libmesh/fe.h"    23 #include "libmesh/fe_interface.h"    24 #include "libmesh/fe_macro.h"    25 #include "libmesh/libmesh_logging.h"    26 #include "libmesh/quadrature.h"    27 #include "libmesh/tensor_value.h"    28 #include "libmesh/enum_elem_type.h"    29 #include "libmesh/quadrature_gauss.h"    30 #include "libmesh/libmesh_singleton.h"    36   void nonlagrange_dual_warning () {
    37     libmesh_warning(
"dual calculations have only been verified for the LAGRANGE family");
    61 template <
unsigned int Dim, FEFamily T>
    70   libmesh_assert_equal_to (T, this->get_family());
    74 template <
unsigned int Dim, FEFamily T>
    78     return this->n_dofs (this->_elem,
    79                          this->fe_type.order + this->_p_level);
    81   return this->n_dofs (this->get_type(),
    82                        this->fe_type.order + this->_p_level);
    86 template <
unsigned int Dim, FEFamily T>
    92   this->_elem = 
nullptr;
    98 template <
unsigned int Dim, FEFamily T>
   102                              std::vector<unsigned int> & di,
   103                              const bool add_p_level)
   106   libmesh_assert_less (s, elem->
n_sides());
   109   unsigned int nodenum = 0;
   111   for (
unsigned int n = 0; n != 
n_nodes; ++n)
   113       const unsigned int n_dofs =
   114           n_dofs_at_node(*elem, static_cast<Order>(o + add_p_level*elem->
p_level()), n);
   116         for (
unsigned int i = 0; i != n_dofs; ++i)
   117           di.push_back(nodenum++);
   125 template <
unsigned int Dim, FEFamily T>
   129                              std::vector<unsigned int> & di,
   130                              const bool add_p_level)
   133   libmesh_assert_less (e, elem->
n_edges());
   136   unsigned int nodenum = 0;
   138   for (
unsigned int n = 0; n != 
n_nodes; ++n)
   140       const unsigned int n_dofs =
   141           n_dofs_at_node(*elem, static_cast<Order>(o + add_p_level*elem->
p_level()), n);
   143         for (
unsigned int i = 0; i != n_dofs; ++i)
   144           di.push_back(nodenum++);
   152 template <
unsigned int Dim, FEFamily T>
   155   cached_nodes.resize(elem->
n_nodes());
   157     cached_nodes[n] = elem->
point(n);
   159   if (FEInterface::orientation_dependent(T))
   161       cached_edges.resize(elem->
n_edges());
   165       cached_faces.resize(elem->
n_faces());
   173 template <
unsigned int Dim, FEFamily T>
   176   bool m = cached_nodes.size() == elem->
n_nodes();
   177   for (
unsigned n = 1; m && n < elem->
n_nodes(); n++)
   180   if (FEInterface::orientation_dependent(T))
   182       m &= cached_edges.size() == elem->
n_edges();
   183       for (
unsigned n = 0; m && n < elem->
n_edges(); n++)
   186       m &= cached_faces.size() == elem->
n_faces();
   187       for (
unsigned n = 0; m && n < elem->
n_faces(); n++)
   196 template <
unsigned int Dim, FEFamily T>
   198                        const std::vector<Point> * 
const pts,
   199                        const std::vector<Real> * 
const weights)
   206   this->determine_calculations();
   210   bool cached_elem_still_fits = 
false;
   221           this->_elem_type = elem->
type();
   222           this->_elem_p_level = elem->
p_level();
   223           this->_p_level = this->_add_p_level_in_reinit * elem->
p_level();
   226           this->_fe_map->template init_reference_to_physical_map<Dim>
   228           this->init_shape_functions (*pts, elem);
   231           this->shapes_on_quadrature = 
false;
   244           this->qrule->init(*elem);
   246           if (this->qrule->shapes_need_reinit())
   247             this->shapes_on_quadrature = 
false;
   251           if (this->get_type() != elem->
type()       ||
   253                this->_elem != elem)                  ||
   254               this->_elem_p_level != elem->
p_level() ||
   255               !this->shapes_on_quadrature            ||
   260               this->_elem_type = elem->
type();
   261               this->_elem_p_level = elem->
p_level();
   262               this->_p_level = this->_add_p_level_in_reinit * elem->
p_level();
   265               this->_fe_map->template init_reference_to_physical_map<Dim>
   266                 (this->qrule->get_points(), elem);
   267               this->init_shape_functions (this->qrule->get_points(), elem);
   274               cached_elem_still_fits = this->matches_cache(elem);
   277               if (this->shapes_need_reinit() && !cached_elem_still_fits)
   279                   this->_fe_map->template init_reference_to_physical_map<Dim>
   280                     (this->qrule->get_points(), elem);
   281                   this->init_shape_functions (this->qrule->get_points(), elem);
   286           if (this->shapes_need_reinit() && !cached_elem_still_fits && *
caching)
   290           this->shapes_on_quadrature = 
true;
   297       this->_elem = 
nullptr;
   299       this->_elem_p_level = 0;
   306               this->qrule->get_points() =
   307                 std::vector<Point>(1,
Point(0));
   309               this->qrule->get_weights() =
   310                 std::vector<Real>(1,1);
   314               this->qrule->get_points().clear();
   315               this->qrule->get_weights().clear();
   318           this->init_shape_functions (this->qrule->get_points(), elem);
   321         this->init_shape_functions (*pts, elem);
   327       if (weights != 
nullptr)
   329           this->_fe_map->compute_map (this->
dim, *weights, elem, this->calculate_d2phi);
   333           std::vector<Real> dummy_weights (pts->size(), 1.);
   334           this->_fe_map->compute_map (this->
dim, dummy_weights, elem, this->calculate_d2phi);
   339       this->_fe_map->compute_map (this->
dim, this->qrule->get_weights(), elem, this->calculate_d2phi);
   344   if (!cached_elem_still_fits)
   347         this->compute_shape_functions (elem,*pts);
   349         this->compute_shape_functions(elem,this->qrule->get_points());
   350       if (this->calculate_dual)
   353           nonlagrange_dual_warning();
   361         if (elem && this->calculate_default_dual_coeff)
   362           this->reinit_default_dual_shape_coeffs(elem);
   365         this->compute_dual_shape_functions();
   370 template <
unsigned int Dim, FEFamily T>
   372                                          const std::vector<Point> & pts,
   373                                          const std::vector<Real> & JxW)
   377   this->_elem_type = elem->
type();
   378   this->_elem_p_level = elem->
p_level();
   379   this->_p_level = this->_add_p_level_in_reinit * elem->
p_level();
   381   const unsigned int n_shapes =
   382     this->n_dofs(elem, this->get_order());
   384   std::vector<std::vector<OutputShape>> phi_vals;
   385   phi_vals.resize(n_shapes);
   386   for (
const auto i : 
make_range(phi_vals.size()))
   387     phi_vals[i].resize(pts.size());
   389   all_shapes(elem, this->get_order(), pts, phi_vals);
   390   this->compute_dual_shape_coeffs(JxW, phi_vals);
   393 template <
unsigned int Dim, FEFamily T>
   398   FEType default_fe_type(this->get_order(), T);
   400   default_qrule.
init(*elem);
   404   this->reinit_dual_shape_coeffs(elem, default_qrule.get_points(), default_qrule.get_weights());
   406   this->set_calculate_default_dual_coeff(
false);
   410 template <
unsigned int Dim, FEFamily T>
   413   if (!this->calculate_dual)
   416   libmesh_assert_msg(this->calculate_phi,
   417                      "dual shape function calculation relies on "   418                      "primal shape functions being calculated");
   420   this->dual_phi.resize(n_shapes);
   421   if (this->calculate_dphi)
   422     this->dual_dphi.resize(n_shapes);
   423 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   424   if (this->calculate_d2phi)
   425     this->dual_d2phi.resize(n_shapes);
   430     this->dual_phi[i].resize(n_qp);
   431     if (this->calculate_dphi)
   432       this->dual_dphi[i].resize(n_qp);
   433 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   434   if (this->calculate_d2phi)
   435     this->dual_d2phi[i].resize(n_qp);
   440 template <
unsigned int Dim, FEFamily T>
   445   LOG_SCOPE(
"init_shape_functions()", 
"FE");
   448   const unsigned int n_qp = cast_int<unsigned int>(qp.size());
   449   this->_n_total_qp = n_qp;
   453   const unsigned int n_approx_shape_functions =
   454     this->n_dofs(elem, this->get_order());
   459   unsigned int old_n_qp = 0;
   465       if (this->calculate_phi)
   467           if (this->phi.size() == n_approx_shape_functions)
   469               old_n_qp = n_approx_shape_functions ? this->phi[0].size() : 0;
   472           this->phi.resize     (n_approx_shape_functions);
   474       if (this->calculate_dphi)
   476           if (this->dphi.size() == n_approx_shape_functions)
   478               old_n_qp = n_approx_shape_functions ? this->dphi[0].size() : 0;
   481           this->dphi.resize    (n_approx_shape_functions);
   482           this->dphidx.resize  (n_approx_shape_functions);
   483           this->dphidy.resize  (n_approx_shape_functions);
   484           this->dphidz.resize  (n_approx_shape_functions);
   487       if (this->calculate_dphiref)
   491               if (this->dphidxi.size() == n_approx_shape_functions)
   493                   old_n_qp = n_approx_shape_functions ? this->dphidxi[0].size() : 0;
   496               this->dphidxi.resize (n_approx_shape_functions);
   500             this->dphideta.resize      (n_approx_shape_functions);
   503             this->dphidzeta.resize     (n_approx_shape_functions);
   506       if (this->calculate_curl_phi && (FEInterface::field_type(T) == 
TYPE_VECTOR))
   507         this->curl_phi.resize(n_approx_shape_functions);
   509       if (this->calculate_div_phi && (FEInterface::field_type(T) == 
TYPE_VECTOR))
   510         this->div_phi.resize(n_approx_shape_functions);
   512 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   513       if (this->calculate_d2phi)
   515           if (this->d2phi.size() == n_approx_shape_functions)
   517               old_n_qp = n_approx_shape_functions ? this->d2phi[0].size() : 0;
   521           this->d2phi.resize     (n_approx_shape_functions);
   522           this->d2phidx2.resize  (n_approx_shape_functions);
   523           this->d2phidxdy.resize (n_approx_shape_functions);
   524           this->d2phidxdz.resize (n_approx_shape_functions);
   525           this->d2phidy2.resize  (n_approx_shape_functions);
   526           this->d2phidydz.resize (n_approx_shape_functions);
   527           this->d2phidz2.resize  (n_approx_shape_functions);
   530             this->d2phidxi2.resize (n_approx_shape_functions);
   534               this->d2phidxideta.resize (n_approx_shape_functions);
   535               this->d2phideta2.resize   (n_approx_shape_functions);
   539               this->d2phidxidzeta.resize  (n_approx_shape_functions);
   540               this->d2phidetadzeta.resize (n_approx_shape_functions);
   541               this->d2phidzeta2.resize    (n_approx_shape_functions);
   544 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   548   if (old_n_qp != n_qp)
   549     for (
unsigned int i=0; i<n_approx_shape_functions; i++)
   551         if (this->calculate_phi)
   552           this->phi[i].resize         (n_qp);
   554         if (this->calculate_dphi)
   556             this->dphi[i].resize        (n_qp);
   557             this->dphidx[i].resize      (n_qp);
   558             this->dphidy[i].resize      (n_qp);
   559             this->dphidz[i].resize      (n_qp);
   562         if (this->calculate_dphiref)
   565               this->dphidxi[i].resize(n_qp);
   568               this->dphideta[i].resize(n_qp);
   571               this->dphidzeta[i].resize(n_qp);
   574         if (this->calculate_curl_phi && (FEInterface::field_type(T) == 
TYPE_VECTOR))
   575           this->curl_phi[i].resize(n_qp);
   577         if (this->calculate_div_phi && (FEInterface::field_type(T) == 
TYPE_VECTOR))
   578           this->div_phi[i].resize(n_qp);
   580 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   581         if (this->calculate_d2phi)
   583             this->d2phi[i].resize     (n_qp);
   584             this->d2phidx2[i].resize  (n_qp);
   585             this->d2phidxdy[i].resize (n_qp);
   586             this->d2phidxdz[i].resize (n_qp);
   587             this->d2phidy2[i].resize  (n_qp);
   588             this->d2phidydz[i].resize (n_qp);
   589             this->d2phidz2[i].resize  (n_qp);
   591               this->d2phidxi2[i].resize (n_qp);
   594                 this->d2phidxideta[i].resize (n_qp);
   595                 this->d2phideta2[i].resize   (n_qp);
   599                 this->d2phidxidzeta[i].resize  (n_qp);
   600                 this->d2phidetadzeta[i].resize (n_qp);
   601                 this->d2phidzeta2[i].resize    (n_qp);
   604 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   608 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS   616     if (this->calculate_phi || this->calculate_dphi)
   618         this->
weight.resize  (n_qp);
   619         for (
unsigned int p=0; p<n_qp; p++)
   623     if (this->calculate_dphi)
   625         this->dweight.resize (n_qp);
   626         this->dphase.resize  (n_qp);
   627         for (
unsigned int p=0; p<n_qp; p++)
   629             this->dweight[p].zero();
   630             this->dphase[p].zero();
   634 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS   637   if (this->calculate_dphiref && Dim > 0)
   639       std::vector<std::vector<OutputShape>> * comps[3]
   640         { &this->dphidxi, &this->dphideta, &this->dphidzeta };
   658 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   660         if (this->calculate_d2phi)
   661           for (
unsigned int i=0; i<n_approx_shape_functions; i++)
   662             for (
unsigned int p=0; p<n_qp; p++)
   664                   elem, this->fe_type.order, i, 0, qp[p], this->_add_p_level_in_reinit);
   665 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   676 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   678         if (this->calculate_d2phi)
   679           for (
unsigned int i=0; i<n_approx_shape_functions; i++)
   680             for (
unsigned int p=0; p<n_qp; p++)
   683                     elem, this->fe_type.order, i, 0, qp[p], this->_add_p_level_in_reinit);
   685                     elem, this->fe_type.order, i, 1, qp[p], this->_add_p_level_in_reinit);
   687                     elem, this->fe_type.order, i, 2, qp[p], this->_add_p_level_in_reinit);
   689 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   701 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   703         if (this->calculate_d2phi)
   704           for (
unsigned int i=0; i<n_approx_shape_functions; i++)
   705             for (
unsigned int p=0; p<n_qp; p++)
   708                     elem, this->fe_type.order, i, 0, qp[p], this->_add_p_level_in_reinit);
   710                     elem, this->fe_type.order, i, 1, qp[p], this->_add_p_level_in_reinit);
   712                     elem, this->fe_type.order, i, 2, qp[p], this->_add_p_level_in_reinit);
   714                     elem, this->fe_type.order, i, 3, qp[p], this->_add_p_level_in_reinit);
   716                     elem, this->fe_type.order, i, 4, qp[p], this->_add_p_level_in_reinit);
   718                     elem, this->fe_type.order, i, 5, qp[p], this->_add_p_level_in_reinit);
   720 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   727       libmesh_error_msg(
"Invalid dimension Dim = " << Dim);
   730   if (this->calculate_dual)
   731     this->init_dual_shape_functions(n_approx_shape_functions, n_qp);
   734 template <
unsigned int Dim, FEFamily T>
   738                                      const std::vector<Point> & p,
   739                                      std::vector<std::vector<OutputShape>> * comps[3],
   740                                      const bool add_p_level)
   742   for (
unsigned int d=0; d != Dim; ++d)
   744       auto & comps_d = *comps[d];
   747           (elem,o,i,d,p,comps_d[i],add_p_level);
   752 template <
unsigned int Dim, FEFamily T>
   755                                    const unsigned int side,
   756                                    const std::vector<Number> & elem_soln,
   757                                    std::vector<Number> & nodal_soln_on_side,
   758                                    const bool add_p_level,
   761   std::vector<Number> full_nodal_soln;
   762   nodal_soln(elem, o, elem_soln, full_nodal_soln, add_p_level, vdim);
   763   const std::vector<unsigned int> side_nodes =
   766   std::size_t n_side_nodes = side_nodes.size();
   767   nodal_soln_on_side.resize(n_side_nodes);
   769     nodal_soln_on_side[n] = full_nodal_soln[side_nodes[n]];
   775 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS   777 template <
unsigned int Dim, FEFamily T>
   782   this->_elem_type = e->
type();
   783   this->_fe_map->template init_reference_to_physical_map<Dim>(qp, e);
   784   init_shape_functions(qp, e);
   787 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS   794 std::tuple<Point, Point, Real>
   795 fdm_points(
const unsigned int j, 
const Point & p)
   797   libmesh_assert_less (j, LIBMESH_DIM);
   800   const Real eps = 1.e-6;
   801   Point pp = p, pm = p;
   830       libmesh_error_msg(
"Invalid derivative index j = " << j);
   833   return std::make_tuple(pp, pm, eps);
   836 std::tuple<Point, Point, Real, unsigned int>
   837 fdm_second_points(
const unsigned int j, 
const Point & p)
   840   const Real eps = 1.e-5;
   841   Point pp = p, pm = p;
   842   unsigned int deriv_j = 0;
   901       libmesh_error_msg(
"Invalid shape function derivative j = " << j);
   904   return std::make_tuple(pp, pm, eps, deriv_j);
   910 template <
typename OutputShape>
   913                          const unsigned int i,
   914                          const unsigned int j,
   916                          const bool add_p_level,
   917                          OutputShape(*shape_func)
   919                             const unsigned int, 
const Point &,
   924   auto [pp, pm, eps] = fdm_points(j, p);
   926   return (shape_func(elem, order, i, pp, add_p_level) -
   927           shape_func(elem, order, i, pm, add_p_level))/2./eps;
   931 template <
typename OutputShape>
   934                          const unsigned int i,
   935                          const unsigned int j,
   937                          OutputShape(*shape_func)
   939                             const unsigned int, 
const Point &))
   941   auto [pp, pm, eps] = fdm_points(j, p);
   943   return (shape_func(type, order, i, pp) -
   944           shape_func(type, order, i, pm))/2./eps;
   948 template <
typename OutputShape>
   952                          const unsigned int i,
   953                          const unsigned int j,
   955                          OutputShape(*shape_func)
   958                             const unsigned int, 
const Point &))
   960   auto [pp, pm, eps] = fdm_points(j, p);
   962   return (shape_func(type, order, elem, i, pp) -
   963           shape_func(type, order, elem, i, pm))/2./eps;
   967 template <
typename OutputShape>
   971                     const unsigned int i,
   972                     const unsigned int j,
   974                     const bool add_p_level,
   975                     OutputShape(*deriv_func)
   977                        const unsigned int, 
const unsigned int,
   978                        const Point &, 
const bool))
   980   auto [pp, pm, eps, deriv_j] = fdm_second_points(j, p);
   982   return (deriv_func(elem, order, i, deriv_j, pp, add_p_level) -
   983           deriv_func(elem, order, i, deriv_j, pm, add_p_level))/2./eps;
   987 template <
typename OutputShape>
   991                     const unsigned int i,
   992                     const unsigned int j,
   994                     OutputShape(*deriv_func)
   996                        const unsigned int, 
const unsigned int,
   999   auto [pp, pm, eps, deriv_j] = fdm_second_points(j, p);
  1001   return (deriv_func(type, order, i, deriv_j, pp) -
  1002           deriv_func(type, order, i, deriv_j, pm))/2./eps;
  1006 template <
typename OutputShape>
  1011                     const unsigned int i,
  1012                     const unsigned int j,
  1014                     OutputShape(*deriv_func)
  1017                        const unsigned int, 
const unsigned int,
  1020   auto [pp, pm, eps, deriv_j] = fdm_second_points(j, p);
  1022   return (deriv_func(type, order, elem, i, deriv_j, pp) -
  1023           deriv_func(type, order, elem, i, deriv_j, pm))/2./eps;
  1028                                  const FEType underlying_fe_type,
  1029                                  std::vector<std::vector<Real>> & shapes,
  1030                                  const std::vector<Point> & p,
  1031                                  const bool add_p_level)
  1033   const int extra_order = add_p_level * elem->
p_level();
  1035   const int dim = elem->
dim();
  1037   const unsigned int n_sf =
  1038     FEInterface::n_shape_functions(underlying_fe_type, extra_order,
  1041   libmesh_assert_equal_to (n_sf, elem->
n_nodes());
  1043   std::vector<Real> node_weights(n_sf);
  1045   const unsigned char datum_index = elem->
mapping_data();
  1046   for (
unsigned int n=0; n<n_sf; n++)
  1050   const std::size_t n_p = p.size();
  1052   shapes.resize(n_sf);
  1053   for (
unsigned int i=0; i != n_sf; ++i)
  1055       auto & shapes_i = shapes[i];
  1056       shapes_i.resize(n_p, 0);
  1057       FEInterface::shapes(
dim, underlying_fe_type, elem, i, p,
  1058                           shapes_i, add_p_level);
  1059       for (
auto & s : shapes_i)
  1060         s *= node_weights[i];
  1067                                         std::vector<std::vector<Real>> & shapes,
  1068                                         std::vector<std::vector<std::vector<Real>>> & derivs,
  1069                                         const std::vector<Point> & p,
  1070                                         const bool add_p_level)
  1072   const int extra_order = add_p_level * elem->
p_level();
  1073   const unsigned int dim = elem->
dim();
  1075   const unsigned int n_sf =
  1076     FEInterface::n_shape_functions(fe_type, extra_order, elem);
  1078   libmesh_assert_equal_to (n_sf, elem->
n_nodes());
  1080   libmesh_assert_equal_to (
dim, derivs.size());
  1081   for (
unsigned int d = 0; d != 
dim; ++d)
  1082     derivs[d].resize(n_sf);
  1084   std::vector<Real> node_weights(n_sf);
  1086   const unsigned char datum_index = elem->
mapping_data();
  1087   for (
unsigned int n=0; n<n_sf; n++)
  1091   const std::size_t n_p = p.size();
  1093   shapes.resize(n_sf);
  1094   for (
unsigned int i=0; i != n_sf; ++i)
  1095     shapes[i].resize(n_p, 0);
  1097   FEInterface::all_shapes(
dim, fe_type, elem, p, shapes, add_p_level);
  1099   for (
unsigned int i=0; i != n_sf; ++i)
  1101       auto & shapes_i = shapes[i];
  1103       for (
auto & s : shapes_i)
  1104         s *= node_weights[i];
  1106       for (
unsigned int d = 0; d != 
dim; ++d)
  1108           auto & derivs_di = derivs[d][i];
  1109           derivs_di.resize(n_p);
  1110           FEInterface::shape_derivs(fe_type, elem, i, d, p,
  1111                                     derivs_di, add_p_level);
  1112           for (
auto & dip : derivs_di)
  1113             dip *= node_weights[i];
  1120                        const FEType underlying_fe_type,
  1121                        const unsigned int i,
  1123                        const bool add_p_level)
  1125   int extra_order = add_p_level * elem.
p_level();
  1127   const unsigned int n_sf =
  1128     FEInterface::n_shape_functions(underlying_fe_type, extra_order, &elem);
  1130   libmesh_assert_equal_to (n_sf, elem.
n_nodes());
  1132   std::vector<Real> node_weights(n_sf);
  1136   Real weighted_shape_i = 0, weighted_sum = 0;
  1138   for (
unsigned int sf=0; sf<n_sf; sf++)
  1142       Real weighted_shape = node_weight *
  1143         FEInterface::shape(underlying_fe_type, extra_order, &elem, sf, p);
  1144       weighted_sum += weighted_shape;
  1146         weighted_shape_i = weighted_shape;
  1149   return weighted_shape_i / weighted_sum;
  1154                              const FEType underlying_fe_type,
  1155                              const unsigned int i,
  1156                              const unsigned int j,
  1158                              const bool add_p_level)
  1160   libmesh_assert_less(j, elem.
dim());
  1162   int extra_order = add_p_level * elem.
p_level();
  1164   const unsigned int n_sf =
  1165     FEInterface::n_shape_functions(underlying_fe_type, extra_order, &elem);
  1168   libmesh_assert_equal_to (n_sf, 
n_nodes);
  1170   std::vector<Real> node_weights(
n_nodes);
  1173   for (
unsigned int n=0; n<
n_nodes; n++)
  1177   Real weighted_shape_i = 0, weighted_sum = 0,
  1178        weighted_grad_i = 0, weighted_grad_sum = 0;
  1180   for (
unsigned int sf=0; sf<n_sf; sf++)
  1182       Real weighted_shape = node_weights[sf] *
  1183         FEInterface::shape(underlying_fe_type, extra_order, &elem, sf, p);
  1184       Real weighted_grad = node_weights[sf] *
  1185         FEInterface::shape_deriv(underlying_fe_type, extra_order, &elem, sf, j, p);
  1186       weighted_sum += weighted_shape;
  1187       weighted_grad_sum += weighted_grad;
  1190           weighted_shape_i = weighted_shape;
  1191           weighted_grad_i = weighted_grad;
  1195   return (weighted_sum * weighted_grad_i - weighted_shape_i * weighted_grad_sum) /
  1196          weighted_sum / weighted_sum;
  1200 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES  1203                                     const FEType underlying_fe_type,
  1204                                     const unsigned int i,
  1205                                     const unsigned int j,
  1207                                     const bool add_p_level)
  1209   unsigned int j1, j2;
  1243   int extra_order = add_p_level * elem.
p_level();
  1245   const unsigned int n_sf =
  1246     FEInterface::n_shape_functions(underlying_fe_type, extra_order,
  1250   libmesh_assert_equal_to (n_sf, 
n_nodes);
  1252   std::vector<Real> node_weights(
n_nodes);
  1255   for (
unsigned int n=0; n<
n_nodes; n++)
  1259   Real weighted_shape_i = 0, weighted_sum = 0,
  1260        weighted_grada_i = 0, weighted_grada_sum = 0,
  1261        weighted_gradb_i = 0, weighted_gradb_sum = 0,
  1262        weighted_hess_i = 0, weighted_hess_sum = 0;
  1264   for (
unsigned int sf=0; sf<n_sf; sf++)
  1266       Real weighted_shape = node_weights[sf] *
  1267         FEInterface::shape(underlying_fe_type, extra_order, &elem, sf,
  1269       Real weighted_grada = node_weights[sf] *
  1270         FEInterface::shape_deriv(underlying_fe_type, extra_order,
  1272       Real weighted_hess = node_weights[sf] *
  1273         FEInterface::shape_second_deriv(underlying_fe_type,
  1274                                         extra_order, &elem, sf, j, p);
  1275       weighted_sum += weighted_shape;
  1276       weighted_grada_sum += weighted_grada;
  1277       Real weighted_gradb = weighted_grada;
  1280           weighted_gradb = (j1 == j2) ? weighted_grada :
  1282             FEInterface::shape_deriv(underlying_fe_type, extra_order,
  1284           weighted_grada_sum += weighted_grada;
  1286       weighted_hess_sum += weighted_hess;
  1289           weighted_shape_i = weighted_shape;
  1290           weighted_grada_i = weighted_grada;
  1291           weighted_gradb_i = weighted_gradb;
  1292           weighted_hess_i = weighted_hess;
  1297     weighted_gradb_sum = weighted_grada_sum;
  1299   return (weighted_sum * weighted_hess_i - weighted_grada_i * weighted_gradb_sum -
  1300           weighted_shape_i * weighted_hess_sum - weighted_gradb_i * weighted_grada_sum +
  1301           2 * weighted_grada_sum * weighted_shape_i * weighted_gradb_sum / weighted_sum) /
  1302          weighted_sum / weighted_sum;
  1305 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES  1309                           const FEType underlying_fe_type,
  1310                           const std::vector<Point> & p,
  1311                           std::vector<std::vector<Real>> & v,
  1312                           const bool add_p_level)
  1314   std::vector<std::vector<Real>> shapes;
  1319   std::vector<Real> shape_sums(p.size(), 0);
  1323       libmesh_assert_equal_to ( p.size(), shapes[i].size() );
  1325         shape_sums[j] += shapes[i][j];
  1330       libmesh_assert_equal_to ( p.size(), v[i].size() );
  1332         v[i][j] = shapes[i][j] / shape_sums[j];
  1337 template <
typename OutputShape>
  1339                                 const FEType underlying_fe_type,
  1340                                 const std::vector<Point> & p,
  1341                                 std::vector<std::vector<OutputShape>> * comps[3],
  1342                                 const bool add_p_level)
  1344   const int my_dim = elem.
dim();
  1346   std::vector<std::vector<Real>> shapes;
  1347   std::vector<std::vector<std::vector<Real>>> derivs(my_dim);
  1350                                      shapes, derivs, p, add_p_level);
  1352   std::vector<Real> shape_sums(p.size(), 0);
  1353   std::vector<std::vector<Real>> shape_deriv_sums(my_dim);
  1354   for (
int d=0; d != my_dim; ++d)
  1355     shape_deriv_sums[d].resize(p.size());
  1359       libmesh_assert_equal_to ( p.size(), shapes[i].size() );
  1361         shape_sums[j] += shapes[i][j];
  1363       for (
int d=0; d != my_dim; ++d)
  1365           shape_deriv_sums[d][j] += derivs[d][i][j];
  1368   for (
int d=0; d != my_dim; ++d)
  1370       auto & comps_d = *comps[d];
  1371       libmesh_assert_equal_to(comps_d.size(), elem.
n_nodes());
  1375           auto & comps_di = comps_d[i];
  1376           auto & derivs_di = derivs[d][i];
  1379             comps_di[j] = (shape_sums[j] * derivs_di[j] -
  1380               shapes[i][j] * shape_deriv_sums[d][j]) /
  1381               shape_sums[j] / shape_sums[j];
  1390                         const unsigned int, 
const Point &, 
const bool,
  1393                            const Point &, 
const bool));
  1404                         const unsigned int, 
const unsigned int, 
const Point &,
  1407                            const unsigned int, 
const Point &));
  1412                            const unsigned int, 
const Point &, 
const bool,
  1415                               const Point &, 
const bool));
  1423                              const unsigned int, 
const Point &));
  1428                           const unsigned int, 
const Point &, 
const bool,
  1431                              const unsigned int, 
const Point &, 
const bool));
  1436                           const unsigned int, 
const unsigned int, 
const Point &,
  1439                              const unsigned int, 
const unsigned int, 
const Point &));
  1444                            const unsigned int, 
const Point &, 
const bool,
  1447                               const unsigned int, 
const Point &, 
const bool));
  1465 template LIBMESH_EXPORT 
void rational_all_shape_derivs<Real> (
const Elem & elem, 
const FEType underlying_fe_type, 
const std::vector<Point> & p, std::vector<std::vector<Real>> * comps[3], 
const bool add_p_level);
 class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
unsigned char mapping_data() const
ElemType
Defines an enum for geometric element types. 
RealVectorValue RealGradient
Order
defines an enum for polynomial orders. 
void rational_fe_weighted_shapes_derivs(const Elem *elem, const FEType fe_type, std::vector< std::vector< Real >> &shapes, std::vector< std::vector< std::vector< Real >>> &derivs, const std::vector< Point > &p, const bool add_p_level)
INSTANTIATE_SUBDIVISION_FE
virtual bool runtime_topology() const
template LIBMESH_EXPORT void rational_all_shape_derivs< Real >(const Elem &elem, const FEType underlying_fe_type, const std::vector< Point > &p, std::vector< std::vector< Real >> *comps[3], const bool add_p_level)
This is the base class from which all geometric element types are derived. 
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
FE(const FEType &fet)
Constructor. 
Order default_quadrature_order() const
unsigned int p_level() const
The libMesh namespace provides an interface to certain functionality in the library. 
IntRange< unsigned short > edge_index_range() const
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const =0
A specific instantiation of the FEBase class. 
template RealGradient fe_fdm_deriv< RealGradient >(const Elem *, const Order, const unsigned int, const unsigned int, const Point &, const bool, RealGradient(*shape_func)(const Elem *, const Order, const unsigned int, const Point &, const bool))
const dof_id_type n_nodes
IntRange< unsigned short > face_index_range() const
ElemMappingType mapping_type() const
const Node & node_ref(const unsigned int i) const
virtual unsigned int n_nodes() const =0
void rational_all_shape_derivs(const Elem &elem, const FEType underlying_fe_type, const std::vector< Point > &p, std::vector< std::vector< OutputShape >> *comps[3], const bool add_p_level)
virtual unsigned int n_edges() const =0
bool positive_edge_orientation(const unsigned int i) const
OutputShape fe_fdm_second_deriv(const Elem *elem, const Order order, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level, OutputShape(*deriv_func)(const Elem *, const Order, const unsigned int, const unsigned int, const Point &, const bool))
Abstract base class for runtime singleton setup. 
void setup()
Setup method. 
virtual unsigned int n_sides() const =0
Real rational_fe_shape(const Elem &elem, const FEType underlying_fe_type, const unsigned int i, const Point &p, const bool add_p_level)
Real rational_fe_shape_second_deriv(const Elem &elem, const FEType underlying_fe_type, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level)
template RealGradient fe_fdm_second_deriv< RealGradient >(const Elem *, const Order, const unsigned int, const unsigned int, const Point &, const bool, RealGradient(*shape_func)(const Elem *, const Order, const unsigned int, const unsigned int, const Point &, const bool))
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const bool * caching
virtual unsigned short dim() const =0
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
This class implements specific orders of Gauss quadrature. 
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
Initializes the data structures for a quadrature rule for the element e. 
IntRange< unsigned short > node_index_range() const
bool positive_face_orientation(const unsigned int i) const
bool relative_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)
Function to check whether two variables are equal within a relative tolerance. 
virtual unsigned int n_faces() const =0
bool on_command_line(std::string arg)
T get_extra_datum(const unsigned int index) const
Gets the value on this object of the extra datum associated with index, which should have been obtain...
libMesh::CachingSetup caching_setup
void rational_all_shapes(const Elem &elem, const FEType underlying_fe_type, const std::vector< Point > &p, std::vector< std::vector< Real >> &v, const bool add_p_level)
void rational_fe_weighted_shapes(const Elem *elem, const FEType underlying_fe_type, std::vector< std::vector< Real >> &shapes, const std::vector< Point > &p, const bool add_p_level)
Helper functions for rational basis functions. 
OutputShape fe_fdm_deriv(const ElemType type, const Order order, const Elem *elem, const unsigned int i, const unsigned int j, const Point &p, OutputShape(*shape_func)(const ElemType, const Order, const Elem *, const unsigned int, const Point &))
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space. 
const Point & point(const unsigned int i) const
template Real fe_fdm_deriv< Real >(const ElemType, const Order, const Elem *, const unsigned int, const unsigned int, const Point &, Real(*shape_func)(const ElemType, const Order, const Elem *, const unsigned int, const Point &))
The QBase class provides the basic functionality from which various quadrature rules can be derived...
void ErrorVector unsigned int
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
This class forms the foundation from which generic finite elements may be derived. 
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
Most finite element types in libMesh are scalar-valued. 
Real rational_fe_shape_deriv(const Elem &elem, const FEType underlying_fe_type, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level)
template Real fe_fdm_second_deriv< Real >(const ElemType, const Order, const Elem *, const unsigned int, const unsigned int, const Point &, Real(*shape_func)(const ElemType, const Order, const Elem *, const unsigned int, const unsigned int, const Point &))