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");
61template <
unsigned int Dim, FEFamily T>
70 libmesh_assert_equal_to (T, this->
get_family());
74template <
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);
86template <
unsigned int Dim, FEFamily T>
92 this->_elem =
nullptr;
98template <
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++);
125template <
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++);
152template <
unsigned int Dim, FEFamily T>
155 cached_nodes.resize(elem->
n_nodes());
157 cached_nodes[n] = elem->
point(n);
161 cached_edges.resize(elem->
n_edges());
165 cached_faces.resize(elem->
n_faces());
173template <
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++)
178 m = (elem->
point(n) - elem->
point(0)).relative_fuzzy_equals(cached_nodes[n] - cached_nodes[0]);
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++)
196template <
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();
370template <
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);
393template <
unsigned int Dim, FEFamily T>
398 FEType default_fe_type(this->get_order(), T);
400 default_qrule.
init(*elem);
406 this->set_calculate_default_dual_coeff(
false);
410template <
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);
440template <
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);
507 this->curl_phi.resize(n_approx_shape_functions);
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);
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);
575 this->curl_phi[i].resize(n_qp);
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);
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++)
620 this->weight[p] = 1.;
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();
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);
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);
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);
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);
734template <
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);
752template <
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
777template <
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);
794std::tuple<Point, Point, Real>
795fdm_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);
836std::tuple<Point, Point, Real, unsigned int>
837fdm_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);
910template <
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;
931template <
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;
948template <
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;
967template <
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;
987template <
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;
1006template <
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 =
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);
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 =
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);
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);
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 =
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 *
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 =
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] *
1184 Real weighted_grad = node_weights[sf] *
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 =
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] *
1269 Real weighted_grada = node_weights[sf] *
1272 Real weighted_hess = node_weights[sf] *
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 :
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;
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];
1337template <
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,
1392 (
const Elem *,
const Order,
const unsigned int,
1393 const Point &,
const bool));
1397 const unsigned int,
const Point &,
1404 const unsigned int,
const unsigned int,
const Point &,
1407 const unsigned int,
const Point &));
1412 const unsigned int,
const Point &,
const bool,
1414 (
const Elem *,
const Order,
const unsigned int,
1415 const Point &,
const bool));
1420 const unsigned int,
const Point &,
1423 const unsigned int,
const Point &));
1428 const unsigned int,
const Point &,
const bool,
1430 (
const Elem *,
const Order,
const unsigned int,
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,
1446 (
const Elem *,
const Order,
const unsigned int,
1447 const unsigned int,
const Point &,
const bool));
void setup()
Setup method.
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...
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
unsigned char mapping_data() const
const Point & point(const unsigned int i) const
const Node & node_ref(const unsigned int i) const
virtual unsigned int n_nodes() const =0
bool positive_edge_orientation(const unsigned int i) const
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
bool positive_face_orientation(const unsigned int i) const
virtual unsigned short dim() const =0
ElemMappingType mapping_type() const
virtual bool runtime_topology() const
virtual unsigned int n_faces() const =0
IntRange< unsigned short > edge_index_range() const
virtual ElemType type() const =0
IntRange< unsigned short > node_index_range() const
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const =0
virtual unsigned int n_edges() const =0
virtual unsigned int n_sides() const =0
unsigned int p_level() const
IntRange< unsigned short > face_index_range() const
FEFamily get_family() const
This class forms the foundation from which generic finite elements may be derived.
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static Real shape_second_deriv(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const unsigned int j, const Point &p)
static Real shape_deriv(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const unsigned int j, const Point &p)
static FEFieldType field_type(const FEType &fe_type)
static void shape_derivs(const FEType &fe_t, const Elem *elem, const unsigned int i, const unsigned int j, const std::vector< Point > &p, std::vector< OutputType > &dphi, const bool add_p_level=true)
Fills dphi with the derivatives of the shape function at point p in direction j.
static void all_shapes(const unsigned int dim, const FEType &fe_t, const Elem *elem, const std::vector< Point > &p, std::vector< std::vector< OutputType > > &phi, const bool add_p_level=true)
static void shapes(const unsigned int dim, const FEType &fe_t, const Elem *elem, const unsigned int i, const std::vector< Point > &p, std::vector< OutputType > &phi, const bool add_p_level=true)
Fills phi with the values of the shape function at point p.
static bool orientation_dependent(const FEFamily &fe_family)
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Order default_quadrature_order() const
A specific instantiation of the FEBase class.
virtual unsigned int n_shape_functions() const override
virtual void init_shape_functions(const std::vector< Point > &qp, const Elem *e)
Update the various member data fields phi, dphidxi, dphideta, dphidzeta, etc.
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.
FE(const FEType &fet)
Constructor.
void init_dual_shape_functions(unsigned int n_shapes, unsigned int n_qp)
Init dual_phi and potentially dual_dphi, dual_d2phi.
bool matches_cache(const Elem *elem)
Check if the node locations, edge and face orientations held in the element cache match those of elem...
static void dofs_on_edge(const Elem *const elem, const Order o, unsigned int e, std::vector< unsigned int > &di, bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with edge e of element elem.
virtual void attach_quadrature_rule(QBase *q) override
Provides the class with the quadrature rule, which provides the locations (on a reference element) wh...
void cache(const Elem *elem)
Repopulate the element cache with the node locations, edge and face orientations of the element elem.
static void default_side_nodal_soln(const Elem *elem, const Order o, const unsigned int side, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln_on_side, bool add_p_level=true, const unsigned vdim=1)
A default implementation for side_nodal_soln.
virtual void reinit_default_dual_shape_coeffs(const Elem *elem) override
This computes the default dual shape function coefficients.
static void all_shape_derivs(const Elem *elem, const Order o, const std::vector< Point > &p, std::vector< std::vector< OutputShape > > *comps[3], const bool add_p_level=true)
Fills comps with dphidxi (and in higher dimensions, eta/zeta) derivative component values for all sha...
static OutputShape shape_second_deriv(const ElemType t, const Order o, const unsigned int i, const unsigned int j, const Point &p)
virtual void init_base_shape_functions(const std::vector< Point > &qp, const Elem *e) override
Initialize the data fields for the base of an an infinite element.
virtual void reinit_dual_shape_coeffs(const Elem *elem, const std::vector< Point > &pts, const std::vector< Real > &JxW) override
This re-computes the dual shape function coefficients.
static void default_all_shape_derivs(const Elem *elem, const Order o, const std::vector< Point > &p, std::vector< std::vector< OutputShape > > *comps[3], const bool add_p_level=true)
A default implementation for all_shape_derivs.
static void dofs_on_side(const Elem *const elem, const Order o, unsigned int s, std::vector< unsigned int > &di, bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with side s of element elem.
A Point defines a location in LIBMESH_DIM dimensional Real space.
The QBase class provides the basic functionality from which various quadrature rules can be derived.
const std::vector< Point > & get_points() const
const std::vector< Real > & get_weights() const
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
Initializes the data structures for a quadrature rule for the element e.
This class implements specific orders of Gauss quadrature.
Abstract base class for runtime singleton setup.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
OutputShape fe_fdm_deriv(const Elem *elem, const Order order, const unsigned int i, const unsigned int j, const Point &p, const bool add_p_level, OutputShape(*shape_func)(const Elem *, const Order, const unsigned int, const Point &, const bool))
Helper functions for finite differenced derivatives in cases where analytical calculations haven't be...
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)
ElemType
Defines an enum for geometric element types.
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)
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))
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)
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)
Real rational_fe_shape(const Elem &elem, const FEType underlying_fe_type, const unsigned int i, const Point &p, const bool add_p_level)
libMesh::CachingSetup caching_setup
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.
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)
INSTANTIATE_SUBDIVISION_FE
static const bool * caching
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))
template Real fe_fdm_second_deriv< Real >(const ElemType, const Order, const unsigned int, const unsigned int, const Point &, Real(*shape_func)(const ElemType, const Order, const unsigned int, const unsigned int, const Point &))
template Real fe_fdm_deriv< Real >(const Elem *, const Order, const unsigned int, const unsigned int, const Point &, const bool, Real(*shape_func)(const Elem *, const Order, const unsigned int, const Point &, const bool))
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)
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))
RealVectorValue RealGradient
bool on_command_line(std::string arg)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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...
Most finite element types in libMesh are scalar-valued.
const dof_id_type n_nodes