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