21 #include "libmesh/fe.h" 22 #include "libmesh/inf_fe.h" 23 #include "libmesh/libmesh_logging.h" 26 #include "libmesh/boundary_info.h" 27 #include "libmesh/mesh_base.h" 28 #include "libmesh/dense_matrix.h" 29 #include "libmesh/dense_vector.h" 30 #include "libmesh/dof_map.h" 31 #include "libmesh/elem.h" 32 #include "libmesh/fe_interface.h" 33 #include "libmesh/int_range.h" 34 #include "libmesh/numeric_vector.h" 35 #include "libmesh/periodic_boundary_base.h" 36 #include "libmesh/periodic_boundaries.h" 37 #include "libmesh/quadrature.h" 38 #include "libmesh/quadrature_gauss.h" 39 #include "libmesh/tensor_value.h" 40 #include "libmesh/threads.h" 41 #include "libmesh/fe_type.h" 42 #include "libmesh/enum_to_string.h" 53 #ifdef LIBMESH_ENABLE_PERIODIC 56 const Elem * primary_boundary_point_neighbor(
const Elem * elem,
59 const std::set<boundary_id_type> & boundary_ids)
63 const Elem * primary = elem;
66 std::vector<boundary_id_type> bc_ids;
69 std::unique_ptr<const Elem> periodic_side;
71 std::set<const Elem *> point_neighbors;
73 for (
const auto & pt_neighbor : point_neighbors)
79 if ((pt_neighbor->level() > primary->
level()) ||
80 (pt_neighbor->level() == primary->
level() &&
81 pt_neighbor->id() < primary->
id()))
87 bool vertex_on_periodic_side =
false;
88 for (
auto ns : pt_neighbor->side_index_range())
92 bool on_relevant_boundary =
false;
93 for (
const auto &
id : boundary_ids)
94 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
95 on_relevant_boundary =
true;
97 if (!on_relevant_boundary)
100 pt_neighbor->build_side_ptr(periodic_side, ns);
101 if (!periodic_side->contains_point(p))
104 vertex_on_periodic_side =
true;
108 if (vertex_on_periodic_side)
109 primary = pt_neighbor;
116 const Elem * primary_boundary_edge_neighbor(
const Elem * elem,
120 const std::set<boundary_id_type> & boundary_ids)
124 const Elem * primary = elem;
126 std::set<const Elem *> edge_neighbors;
130 std::vector<boundary_id_type> bc_ids;
133 std::unique_ptr<const Elem> periodic_side;
135 for (
const auto & e_neighbor : edge_neighbors)
141 if ((e_neighbor->level() > primary->
level()) ||
142 (e_neighbor->level() == primary->
level() &&
143 e_neighbor->id() < primary->
id()))
149 bool vertex_on_periodic_side =
false;
150 for (
auto ns : e_neighbor->side_index_range())
154 bool on_relevant_boundary =
false;
155 for (
const auto &
id : boundary_ids)
156 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
157 on_relevant_boundary =
true;
159 if (!on_relevant_boundary)
162 e_neighbor->build_side_ptr(periodic_side, ns);
163 if (!(periodic_side->contains_point(p1) &&
164 periodic_side->contains_point(p2)))
167 vertex_on_periodic_side =
true;
171 if (vertex_on_periodic_side)
172 primary = e_neighbor;
178 #endif // LIBMESH_ENABLE_PERIODIC 190 std::unique_ptr<FEGenericBase<Real>>
202 return std::make_unique<FE<0,CLOUGH>>(fet);
205 return std::make_unique<FE<0,HERMITE>>(fet);
208 return std::make_unique<FE<0,LAGRANGE>>(fet);
211 return std::make_unique<FE<0,L2_LAGRANGE>>(fet);
214 return std::make_unique<FE<0,HIERARCHIC>>(fet);
217 return std::make_unique<FE<0,L2_HIERARCHIC>>(fet);
220 return std::make_unique<FE<0,SIDE_HIERARCHIC>>(fet);
223 return std::make_unique<FE<0,MONOMIAL>>(fet);
225 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 227 return std::make_unique<FE<0,SZABAB>>(fet);
230 return std::make_unique<FE<0,BERNSTEIN>>(fet);
233 return std::make_unique<FE<0,RATIONAL_BERNSTEIN>>(fet);
237 return std::make_unique<FEXYZ<0>>(fet);
240 return std::make_unique<FEScalar<0>>(fet);
252 return std::make_unique<FE<1,CLOUGH>>(fet);
255 return std::make_unique<FE<1,HERMITE>>(fet);
258 return std::make_unique<FE<1,LAGRANGE>>(fet);
261 return std::make_unique<FE<1,L2_LAGRANGE>>(fet);
264 return std::make_unique<FE<1,HIERARCHIC>>(fet);
267 return std::make_unique<FE<1,L2_HIERARCHIC>>(fet);
270 return std::make_unique<FE<1,SIDE_HIERARCHIC>>(fet);
273 return std::make_unique<FE<1,MONOMIAL>>(fet);
275 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 277 return std::make_unique<FE<1,SZABAB>>(fet);
280 return std::make_unique<FE<1,BERNSTEIN>>(fet);
283 return std::make_unique<FE<1,RATIONAL_BERNSTEIN>>(fet);
287 return std::make_unique<FEXYZ<1>>(fet);
290 return std::make_unique<FEScalar<1>>(fet);
304 return std::make_unique<FE<2,CLOUGH>>(fet);
307 return std::make_unique<FE<2,HERMITE>>(fet);
310 return std::make_unique<FE<2,LAGRANGE>>(fet);
313 return std::make_unique<FE<2,L2_LAGRANGE>>(fet);
316 return std::make_unique<FE<2,HIERARCHIC>>(fet);
319 return std::make_unique<FE<2,L2_HIERARCHIC>>(fet);
322 return std::make_unique<FE<2,SIDE_HIERARCHIC>>(fet);
325 return std::make_unique<FE<2,MONOMIAL>>(fet);
327 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 329 return std::make_unique<FE<2,SZABAB>>(fet);
332 return std::make_unique<FE<2,BERNSTEIN>>(fet);
335 return std::make_unique<FE<2,RATIONAL_BERNSTEIN>>(fet);
339 return std::make_unique<FEXYZ<2>>(fet);
342 return std::make_unique<FEScalar<2>>(fet);
345 return std::make_unique<FESubdivision>(fet);
359 libmesh_error_msg(
"ERROR: Clough-Tocher elements currently only support 1D and 2D");
362 return std::make_unique<FE<3,HERMITE>>(fet);
365 return std::make_unique<FE<3,LAGRANGE>>(fet);
368 return std::make_unique<FE<3,L2_LAGRANGE>>(fet);
371 return std::make_unique<FE<3,HIERARCHIC>>(fet);
374 return std::make_unique<FE<3,L2_HIERARCHIC>>(fet);
377 return std::make_unique<FE<3,SIDE_HIERARCHIC>>(fet);
380 return std::make_unique<FE<3,MONOMIAL>>(fet);
382 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 384 return std::make_unique<FE<3,SZABAB>>(fet);
387 return std::make_unique<FE<3,BERNSTEIN>>(fet);
390 return std::make_unique<FE<3,RATIONAL_BERNSTEIN>>(fet);
394 return std::make_unique<FEXYZ<3>>(fet);
397 return std::make_unique<FEScalar<3>>(fet);
405 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
412 std::unique_ptr<FEGenericBase<RealGradient>>
424 return std::make_unique<FEHierarchicVec<0>>(fet);
427 return std::make_unique<FEL2HierarchicVec<0>>(fet);
430 return std::make_unique<FELagrangeVec<0>>(fet);
433 return std::make_unique<FEL2LagrangeVec<0>>(fet);
436 return std::make_unique<FEMonomialVec<0>>(fet);
447 return std::make_unique<FEHierarchicVec<1>>(fet);
450 return std::make_unique<FEL2HierarchicVec<1>>(fet);
453 return std::make_unique<FELagrangeVec<1>>(fet);
456 return std::make_unique<FEL2LagrangeVec<1>>(fet);
459 return std::make_unique<FEMonomialVec<1>>(fet);
470 return std::make_unique<FEHierarchicVec<2>>(fet);
473 return std::make_unique<FEL2HierarchicVec<2>>(fet);
476 return std::make_unique<FELagrangeVec<2>>(fet);
479 return std::make_unique<FEL2LagrangeVec<2>>(fet);
482 return std::make_unique<FEMonomialVec<2>>(fet);
485 return std::make_unique<FENedelecOne<2>>(fet);
488 return std::make_unique<FERaviartThomas<2>>(fet);
491 return std::make_unique<FEL2RaviartThomas<2>>(fet);
502 return std::make_unique<FEHierarchicVec<3>>(fet);
505 return std::make_unique<FEL2HierarchicVec<3>>(fet);
508 return std::make_unique<FELagrangeVec<3>>(fet);
511 return std::make_unique<FEL2LagrangeVec<3>>(fet);
514 return std::make_unique<FEMonomialVec<3>>(fet);
517 return std::make_unique<FENedelecOne<3>>(fet);
520 return std::make_unique<FERaviartThomas<3>>(fet);
523 return std::make_unique<FEL2RaviartThomas<3>>(fet);
531 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
541 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 545 std::unique_ptr<FEGenericBase<Real>>
565 return std::make_unique<InfFE<1,JACOBI_20_00,CARTESIAN>>(fet);
577 return std::make_unique<InfFE<1,JACOBI_30_00,CARTESIAN>>(fet);
589 return std::make_unique<InfFE<1,LEGENDRE,CARTESIAN>>(fet);
601 return std::make_unique<InfFE<1,LAGRANGE,CARTESIAN>>(fet);
629 return std::make_unique<InfFE<2,JACOBI_20_00,CARTESIAN>>(fet);
641 return std::make_unique<InfFE<2,JACOBI_30_00,CARTESIAN>>(fet);
653 return std::make_unique<InfFE<2,LEGENDRE,CARTESIAN>>(fet);
665 return std::make_unique<InfFE<2,LAGRANGE,CARTESIAN>>(fet);
693 return std::make_unique<InfFE<3,JACOBI_20_00,CARTESIAN>>(fet);
705 return std::make_unique<InfFE<3,JACOBI_30_00,CARTESIAN>>(fet);
717 return std::make_unique<InfFE<3,LEGENDRE,CARTESIAN>>(fet);
729 return std::make_unique<InfFE<3,LAGRANGE,CARTESIAN>>(fet);
742 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
749 std::unique_ptr<FEGenericBase<RealGradient>>
754 libmesh_not_implemented();
755 return std::unique_ptr<FEVectorBase>();
758 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 761 template <
typename OutputType>
763 const std::vector<Point> & qp)
771 LOG_SCOPE(
"compute_shape_functions()",
"FE");
773 this->determine_calculations();
776 this->_fe_trans->map_phi(this->
dim, elem, qp, (*
this), this->phi, this->_add_p_level_in_reinit);
779 this->_fe_trans->map_dphi(this->
dim, elem, qp, (*
this), this->dphi,
780 this->dphidx, this->dphidy, this->dphidz);
782 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 784 this->_fe_trans->map_d2phi(this->
dim, qp, (*
this), this->d2phi,
785 this->d2phidx2, this->d2phidxdy, this->d2phidxdz,
786 this->d2phidy2, this->d2phidydz, this->d2phidz2);
787 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES 791 this->_fe_trans->map_curl(this->
dim, elem, qp, (*
this), this->curl_phi);
795 this->_fe_trans->map_div(this->
dim, elem, qp, (*
this), this->div_phi);
807 LOG_SCOPE(
"compute_dual_shape_coeffs()",
"FE");
809 const unsigned int sz=phi_vals.size();
810 libmesh_error_msg_if(!sz,
"ERROR: cannot compute dual shape coefficients with empty phi values");
813 dual_coeff.resize(sz, sz);
819 D(i,i) += JxW[qp]*phi_vals[i][qp];
821 A(i,j) += JxW[qp]*phi_vals[i][qp]*phi_vals[j][qp];
830 A.cholesky_solve(Dcol, coeffcol);
833 dual_coeff(row, j)=coeffcol(row);
841 LOG_SCOPE(
"compute_dual_shape_functions()",
"FE");
853 dual_dphi[j][qp] = 0;
854 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 856 dual_d2phi[j][qp] = 0;
865 dual_phi[j][qp] += dual_coeff(i, j) * phi[i][qp];
867 dual_dphi[j][qp] += dual_coeff(i, j) * dphi[i][qp];
868 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 870 dual_d2phi[j][qp] += dual_coeff(i, j) * d2phi[i][qp];
875 template <
typename OutputType>
880 os <<
" phi[" << i <<
"][" << j <<
"]=" << phi[i][j] << std::endl;
883 template <
typename OutputType>
888 os <<
" dual_phi[" << i <<
"][" << j <<
"]=" << dual_phi[i][j] << std::endl;
894 template <
typename OutputType>
899 os <<
" dphi[" << i <<
"][" << j <<
"]=" << dphi[i][j];
902 template <
typename OutputType>
907 os <<
" dual_dphi[" << i <<
"][" << j <<
"]=" << dual_dphi[i][j];
912 template <
typename OutputType>
915 this->calculations_started =
true;
920 this->calculate_nothing || this->calculate_phi || this->calculate_dphi ||
921 this->calculate_dphiref || this->calculate_curl_phi || this->calculate_div_phi ||
924 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 925 requested_ok = requested_ok || this->calculate_d2phi;
928 libmesh_error_msg_if(
930 "You must call one or more of the FE accessors " 931 "(e.g. get_phi(), get_dphi(), get_nothing()) " 932 "_before_ calling reinit()!");
935 if (this->calculate_phi)
936 this->_fe_trans->init_map_phi(*
this);
938 if (this->calculate_dphiref)
939 this->_fe_trans->init_map_dphi(*
this);
941 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 942 if (this->calculate_d2phi)
943 this->_fe_trans->init_map_d2phi(*
this);
944 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES 949 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 952 template <
typename OutputType>
957 os <<
" d2phi[" << i <<
"][" << j <<
"]=" << d2phi[i][j];
960 template <
typename OutputType>
965 os <<
" dual_d2phi[" << i <<
"][" << j <<
"]=" << dual_d2phi[i][j];
972 #ifdef LIBMESH_ENABLE_AMR 974 template <
typename OutputType>
980 const unsigned int var,
981 const bool use_old_dof_indices)
984 std::vector<unsigned int> new_side_dofs, old_side_dofs;
987 unsigned int dim = elem->
dim();
990 const unsigned int n_children = elem->
n_children();
995 std::unique_ptr<FEGenericBase<OutputShape>> fe
997 std::unique_ptr<FEGenericBase<OutputShape>> fe_coarse
1003 std::vector<Point> coarse_qpoints;
1007 const std::vector<std::vector<OutputShape>> & phi_values =
1009 const std::vector<std::vector<OutputShape>> & phi_coarse =
1010 fe_coarse->get_phi();
1014 const std::vector<std::vector<OutputGradient>> * dphi_values =
1016 const std::vector<std::vector<OutputGradient>> * dphi_coarse =
1023 const std::vector<std::vector<OutputGradient>> &
1024 ref_dphi_values = fe->get_dphi();
1025 dphi_values = &ref_dphi_values;
1026 const std::vector<std::vector<OutputGradient>> &
1027 ref_dphi_coarse = fe_coarse->get_dphi();
1028 dphi_coarse = &ref_dphi_coarse;
1032 const std::vector<Real> & JxW =
1037 const std::vector<Point> & xyz_values =
1044 const unsigned int new_n_dofs =
1048 std::vector<char> dof_is_fixed(new_n_dofs,
false);
1049 std::vector<int> free_dof(new_n_dofs, 0);
1065 std::vector<dof_id_type> node_dof_indices;
1066 if (use_old_dof_indices)
1069 dof_map.
dof_indices (elem, node_dof_indices, var);
1071 unsigned int current_dof = 0;
1072 for (
unsigned int n=0; n!=
n_nodes; ++n)
1076 const unsigned int my_nc =
1080 current_dof += my_nc;
1089 int extra_order = 0;
1092 const unsigned int nc =
1094 for (
unsigned int i=0; i!= nc; ++i)
1097 old_vector(node_dof_indices[current_dof]);
1098 dof_is_fixed[current_dof] =
true;
1104 FEType fe_type = base_fe_type, temp_fe_type;
1114 const unsigned int n_new_side_dofs =
1115 cast_int<unsigned int>(new_side_dofs.size());
1119 unsigned int free_dofs = 0;
1120 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
1121 if (!dof_is_fixed[new_side_dofs[i]])
1122 free_dof[free_dofs++] = i;
1130 for (
unsigned int c=0; c != n_children; ++c)
1136 std::vector<dof_id_type> child_dof_indices;
1137 if (use_old_dof_indices)
1139 child_dof_indices, var);
1142 child_dof_indices, var);
1143 const unsigned int child_n_dofs =
1144 cast_int<unsigned int>
1145 (child_dof_indices.size());
1147 temp_fe_type = base_fe_type;
1148 temp_fe_type.
order = temp_fe_type.order + child->
p_level();
1151 temp_fe_type, e, old_side_dofs);
1155 fe->attach_quadrature_rule (qedgerule.get());
1156 fe->edge_reinit (child, e);
1157 const unsigned int n_qp = qedgerule->n_points();
1162 fe_coarse->reinit(elem, &coarse_qpoints);
1165 for (
unsigned int qp=0; qp<n_qp; qp++)
1175 for (
unsigned int i=0; i<child_n_dofs;
1179 (old_vector(child_dof_indices[i])*
1182 finegrad += (*dphi_values)[i][qp] *
1183 old_vector(child_dof_indices[i]);
1187 for (
unsigned int sidei=0, freei=0; sidei != n_new_side_dofs; ++sidei)
1189 unsigned int i = new_side_dofs[sidei];
1191 if (dof_is_fixed[i])
1193 for (
unsigned int sidej=0, freej=0; sidej != n_new_side_dofs; ++sidej)
1196 new_side_dofs[sidej];
1197 if (dof_is_fixed[j])
1200 phi_coarse[j][qp]) *
1205 phi_coarse[j][qp]) *
1209 if (dof_is_fixed[j])
1212 (*dphi_coarse)[j][qp]) *
1217 (*dphi_coarse)[j][qp]) *
1220 if (!dof_is_fixed[j])
1235 for (
unsigned int i=0; i != free_dofs; ++i)
1237 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1241 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1252 const unsigned int n_new_side_dofs =
1253 cast_int<unsigned int>(new_side_dofs.size());
1257 unsigned int free_dofs = 0;
1258 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
1259 if (!dof_is_fixed[new_side_dofs[i]])
1260 free_dof[free_dofs++] = i;
1268 for (
unsigned int c=0; c != n_children; ++c)
1274 std::vector<dof_id_type> child_dof_indices;
1275 if (use_old_dof_indices)
1277 child_dof_indices, var);
1280 child_dof_indices, var);
1281 const unsigned int child_n_dofs =
1282 cast_int<unsigned int>
1283 (child_dof_indices.size());
1285 temp_fe_type = base_fe_type;
1286 temp_fe_type.
order = temp_fe_type.order + child->
p_level();
1289 temp_fe_type, s, old_side_dofs);
1293 fe->attach_quadrature_rule (qsiderule.get());
1294 fe->reinit (child, s);
1295 const unsigned int n_qp = qsiderule->n_points();
1300 fe_coarse->reinit(elem, &coarse_qpoints);
1303 for (
unsigned int qp=0; qp<n_qp; qp++)
1313 for (
unsigned int i=0; i<child_n_dofs;
1317 old_vector(child_dof_indices[i]) *
1320 finegrad += (*dphi_values)[i][qp] *
1321 old_vector(child_dof_indices[i]);
1325 for (
unsigned int sidei=0, freei=0; sidei != n_new_side_dofs; ++sidei)
1327 unsigned int i = new_side_dofs[sidei];
1329 if (dof_is_fixed[i])
1331 for (
unsigned int sidej=0, freej=0; sidej != n_new_side_dofs; ++sidej)
1334 new_side_dofs[sidej];
1335 if (dof_is_fixed[j])
1338 phi_coarse[j][qp]) *
1343 phi_coarse[j][qp]) *
1347 if (dof_is_fixed[j])
1350 (*dphi_coarse)[j][qp]) *
1355 (*dphi_coarse)[j][qp]) *
1358 if (!dof_is_fixed[j])
1372 for (
unsigned int i=0; i != free_dofs; ++i)
1374 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1378 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1386 unsigned int free_dofs = 0;
1387 for (
unsigned int i=0; i != new_n_dofs; ++i)
1388 if (!dof_is_fixed[i])
1389 free_dof[free_dofs++] = i;
1398 std::vector<dof_id_type> child_dof_indices;
1399 if (use_old_dof_indices)
1401 child_dof_indices, var);
1404 child_dof_indices, var);
1405 const unsigned int child_n_dofs =
1406 cast_int<unsigned int>
1407 (child_dof_indices.size());
1411 fe->attach_quadrature_rule (qrule.get());
1412 fe->reinit (&child);
1413 const unsigned int n_qp = qrule->n_points();
1417 fe_coarse->reinit(elem, &coarse_qpoints);
1420 for (
unsigned int qp=0; qp<n_qp; qp++)
1430 for (
unsigned int i=0; i<child_n_dofs; i++)
1433 (old_vector(child_dof_indices[i]) *
1436 finegrad += (*dphi_values)[i][qp] *
1437 old_vector(child_dof_indices[i]);
1441 for (
unsigned int i=0, freei=0;
1442 i != new_n_dofs; ++i)
1445 if (dof_is_fixed[i])
1447 for (
unsigned int j=0, freej=0; j !=
1450 if (dof_is_fixed[j])
1453 phi_coarse[j][qp]) *
1458 phi_coarse[j][qp]) *
1462 if (dof_is_fixed[j])
1465 (*dphi_coarse)[j][qp]) *
1470 (*dphi_coarse)[j][qp]) *
1473 if (!dof_is_fixed[j])
1487 for (
unsigned int i=0; i != free_dofs; ++i)
1489 Number & ui = Ue(free_dof[i]);
1496 dof_is_fixed[free_dof[i]] =
true;
1502 for (
unsigned int i=0; i != new_n_dofs; ++i)
1509 template <
typename OutputType>
1515 const bool use_old_dof_indices)
1523 coarsened_dof_values(old_vector, dof_map, elem, Usub,
1524 v, use_old_dof_indices);
1532 template <
typename OutputType>
1536 const unsigned int variable_number,
1541 const unsigned int Dim = elem->
dim();
1556 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1558 my_fe->add_p_level_in_reinit(add_p_level);
1572 libmesh_not_implemented();
1574 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1576 neigh_fe->add_p_level_in_reinit(add_p_level);
1579 my_fe->attach_quadrature_rule (&my_qface);
1580 std::vector<Point> neigh_qface;
1582 const std::vector<Real> & JxW = my_fe->get_JxW();
1583 const std::vector<Point> & q_point = my_fe->get_xyz();
1584 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1585 const std::vector<std::vector<OutputShape>> & neigh_phi =
1586 neigh_fe->get_phi();
1587 const std::vector<Point> * face_normals =
nullptr;
1588 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1589 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1591 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1592 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1596 const std::vector<Point> & ref_face_normals =
1597 my_fe->get_normals();
1598 face_normals = &ref_face_normals;
1599 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1602 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1603 neigh_fe->get_dphi();
1604 neigh_dphi = &ref_neigh_dphi;
1609 std::vector<DenseVector<Real>> Ue;
1631 libmesh_assert_less (s_neigh, neigh->
n_neighbors());
1637 const unsigned int min_p_level = add_p_level *
1641 const unsigned int old_elem_level = add_p_level * elem->
p_level();
1642 if (old_elem_level != min_p_level)
1643 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() + min_p_level - old_elem_level);
1644 const unsigned int old_neigh_level = add_p_level * neigh->
p_level();
1645 if (old_neigh_level != min_p_level)
1646 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + min_p_level - old_neigh_level);
1648 my_fe->reinit(elem, s);
1656 my_dof_indices.reserve (elem->
n_nodes());
1657 neigh_dof_indices.reserve (neigh->
n_nodes());
1666 const unsigned int n_qp = my_qface.n_points();
1670 neigh_fe->reinit(neigh, &neigh_qface);
1674 FEType elem_fe_type = base_fe_type;
1675 if (old_elem_level != min_p_level)
1677 FEType neigh_fe_type = base_fe_type;
1678 if (old_neigh_level != min_p_level)
1683 const unsigned int n_side_dofs =
1684 cast_int<unsigned int>(my_side_dofs.size());
1685 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
1688 for (
auto i : my_side_dofs)
1689 libmesh_assert_less(i, my_dof_indices.size());
1690 for (
auto i : neigh_side_dofs)
1691 libmesh_assert_less(i, neigh_dof_indices.size());
1694 Ke.
resize (n_side_dofs, n_side_dofs);
1695 Ue.resize(n_side_dofs);
1699 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1701 const unsigned int i = my_side_dofs[
is];
1702 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1704 const unsigned int j = my_side_dofs[js];
1705 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1709 Ke(
is,js) += JxW[qp] *
1711 (*face_normals)[qp],
1713 (*face_normals)[qp]);
1720 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1722 const unsigned int i = neigh_side_dofs[
is];
1724 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1726 const unsigned int j = my_side_dofs[js];
1727 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1735 (*face_normals)[qp],
1737 (*face_normals)[qp]);
1743 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1745 const unsigned int j = my_side_dofs[js];
1751 bool self_constraint =
false;
1752 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1754 const unsigned int i = neigh_side_dofs[
is];
1755 const dof_id_type their_dof_g = neigh_dof_indices[i];
1758 if (their_dof_g == my_dof_g)
1761 const Real their_dof_value = Ue[
is](js);
1762 libmesh_assert_less (std::abs(their_dof_value-1.),
1765 for (
unsigned int k = 0; k != n_side_dofs; ++k)
1767 std::abs(Ue[k](js)) <
1771 self_constraint =
true;
1776 if (self_constraint)
1790 constraint_row = &(constraints[my_dof_g]);
1794 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1796 const unsigned int i = neigh_side_dofs[
is];
1797 const dof_id_type their_dof_g = neigh_dof_indices[i];
1799 libmesh_assert_not_equal_to (their_dof_g, my_dof_g);
1801 const Real their_dof_value = Ue[
is](js);
1803 if (std::abs(their_dof_value) < 10*
TOLERANCE)
1806 constraint_row->emplace(their_dof_g, their_dof_value);
1810 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() + old_elem_level - min_p_level);
1811 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + old_neigh_level - min_p_level);
1820 const unsigned int min_p_level =
1822 if (min_p_level < elem->p_level())
1834 #endif // #ifdef LIBMESH_ENABLE_AMR 1838 #ifdef LIBMESH_ENABLE_PERIODIC 1839 template <
typename OutputType>
1847 const unsigned int variable_number,
1851 if (boundaries.empty())
1861 libmesh_not_implemented();
1863 const unsigned int Dim = elem->
dim();
1867 const unsigned int sys_number = dof_map.
sys_number();
1872 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1882 const Real primary_hmin = elem->
hmin();
1884 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1888 my_fe->attach_quadrature_rule (&my_qface);
1889 std::vector<Point> neigh_qface;
1891 const std::vector<Real> & JxW = my_fe->get_JxW();
1892 const std::vector<Point> & q_point = my_fe->get_xyz();
1893 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1894 const std::vector<std::vector<OutputShape>> & neigh_phi =
1895 neigh_fe->get_phi();
1896 const std::vector<Point> * face_normals =
nullptr;
1897 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1898 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1899 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1900 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1904 const std::vector<Point> & ref_face_normals =
1905 my_fe->get_normals();
1906 face_normals = &ref_face_normals;
1907 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1910 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1911 neigh_fe->get_dphi();
1912 neigh_dphi = &ref_neigh_dphi;
1917 std::vector<DenseVector<Real>> Ue;
1920 std::vector<boundary_id_type> bc_ids;
1924 const unsigned short int max_ns = elem->
n_sides();
1925 for (
unsigned short int s = 0; s != max_ns; ++s)
1932 for (
const auto & boundary_id : bc_ids)
1941 unsigned int s_neigh;
1942 const Elem * neigh = boundaries.
neighbor(boundary_id, *point_locator, elem, s, &s_neigh);
1944 libmesh_error_msg_if(neigh ==
nullptr,
1945 "PeriodicBoundaries point locator object returned nullptr!");
1953 #ifdef LIBMESH_ENABLE_AMR 1958 const unsigned int min_p_level =
1966 const unsigned int old_elem_level = elem->
p_level();
1967 if (old_elem_level != min_p_level)
1968 (
const_cast<Elem *
>(elem))->hack_p_level(min_p_level);
1969 const unsigned int old_neigh_level = neigh->
p_level();
1970 if (old_neigh_level != min_p_level)
1971 (
const_cast<Elem *
>(neigh))->hack_p_level(min_p_level);
1972 #endif // #ifdef LIBMESH_ENABLE_AMR 1980 my_fe->reinit(elem, s);
1990 std::vector<std::vector<dof_id_type>> neigh_dof_indices_all_variables;
1993 const std::set<unsigned int> & variables = periodic->
get_variables();
1994 neigh_dof_indices_all_variables.resize(variables.size());
1995 unsigned int index = 0;
1996 for(
unsigned int var : variables)
1998 dof_map.
dof_indices (neigh, neigh_dof_indices_all_variables[index],
2004 const unsigned int n_qp = my_qface.n_points();
2008 std::vector<Point> neigh_point(q_point.size());
2015 neigh_fe->reinit(neigh, &neigh_qface);
2024 #ifdef LIBMESH_ENABLE_AMR 2025 if (elem->
p_level() != old_elem_level)
2026 (const_cast<Elem *>(elem))->hack_p_level(old_elem_level);
2027 if (neigh->
p_level() != old_neigh_level)
2028 (const_cast<Elem *>(neigh))->hack_p_level(old_neigh_level);
2029 #endif // #ifdef LIBMESH_ENABLE_AMR 2031 const unsigned int n_side_dofs =
2032 cast_int<unsigned int>
2033 (my_side_dofs.size());
2034 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
2036 Ke.
resize (n_side_dofs, n_side_dofs);
2037 Ue.resize(n_side_dofs);
2041 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
2043 const unsigned int i = my_side_dofs[
is];
2044 for (
unsigned int js = 0; js != n_side_dofs; ++js)
2046 const unsigned int j = my_side_dofs[js];
2047 for (
unsigned int qp = 0; qp != n_qp; ++qp)
2049 Ke(
is,js) += JxW[qp] *
2053 Ke(
is,js) += JxW[qp] *
2055 (*face_normals)[qp],
2057 (*face_normals)[qp]);
2064 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
2066 const unsigned int i = neigh_side_dofs[
is];
2068 for (
unsigned int js = 0; js != n_side_dofs; ++js)
2070 const unsigned int j = my_side_dofs[js];
2071 for (
unsigned int qp = 0; qp != n_qp; ++qp)
2079 (*face_normals)[qp],
2081 (*face_normals)[qp]);
2135 std::set<dof_id_type> my_constrained_dofs;
2138 std::vector<boundary_id_type> new_bc_ids;
2152 std::set<boundary_id_type> point_bcids;
2154 for (
unsigned int new_s = 0;
2155 new_s != max_ns; ++new_s)
2162 for (
const auto & new_boundary_id : new_bc_ids)
2165 if (new_periodic && new_periodic->
is_my_variable(variable_number))
2166 point_bcids.insert(new_boundary_id);
2172 if (primary_boundary_point_neighbor
2178 std::set<boundary_id_type> point_pairedids;
2179 for (
const auto & new_boundary_id : point_bcids)
2186 const Elem * primary_elem =
nullptr;
2187 const Elem * main_neigh =
nullptr;
2188 Point main_pt = my_node,
2189 primary_pt = my_node;
2191 for (
const auto & new_boundary_id : point_bcids)
2197 const Point neigh_pt =
2210 primary_elem = elem;
2212 const Elem * primary_neigh =
2213 primary_boundary_point_neighbor(neigh, neigh_pt,
2219 if (new_boundary_id == boundary_id)
2221 main_neigh = primary_neigh;
2228 if ((primary_neigh->
level() > primary_elem->
level()) ||
2233 (primary_neigh->
level() == primary_elem->
level() &&
2234 primary_neigh->
id() > primary_elem->
id()) ||
2238 (primary_neigh == primary_elem &&
2239 (neigh_pt > primary_pt)))
2242 primary_elem = primary_neigh;
2243 primary_pt = neigh_pt;
2246 if (!primary_elem ||
2247 primary_elem != main_neigh ||
2248 primary_pt != main_pt)
2254 unsigned int e=0, ne = elem->
n_edges();
2255 for (; e != ne; ++e)
2260 libmesh_assert_less (e, elem->
n_edges());
2289 std::set<boundary_id_type> edge_bcids;
2291 for (
unsigned int new_s = 0;
2292 new_s != max_ns; ++new_s)
2300 for (
const auto & new_boundary_id : new_bc_ids)
2303 if (new_periodic && new_periodic->
is_my_variable(variable_number))
2304 edge_bcids.insert(new_boundary_id);
2310 if (primary_boundary_edge_neighbor
2316 std::set<boundary_id_type> edge_pairedids;
2317 for (
const auto & new_boundary_id : edge_bcids)
2324 const Elem * primary_elem =
nullptr;
2325 const Elem * main_neigh =
nullptr;
2326 Point main_pt1 = *e1,
2331 for (
const auto & new_boundary_id : edge_bcids)
2345 neigh_pt2.absolute_fuzzy_equals
2352 primary_elem = elem;
2354 const Elem * primary_neigh = primary_boundary_edge_neighbor
2355 (neigh, neigh_pt1, neigh_pt2,
2360 if (new_boundary_id == boundary_id)
2362 main_neigh = primary_neigh;
2363 main_pt1 = neigh_pt1;
2364 main_pt2 = neigh_pt2;
2374 if (primary_neigh == primary_elem)
2376 if (primary_pt1 > primary_pt2)
2377 std::swap(primary_pt1, primary_pt2);
2378 if (neigh_pt1 > neigh_pt2)
2379 std::swap(neigh_pt1, neigh_pt2);
2381 if (neigh_pt2 >= primary_pt2)
2389 if ((primary_neigh->
level() > primary_elem->
level()) ||
2394 (primary_neigh->
level() == primary_elem->
level() &&
2395 primary_neigh->
id() > primary_elem->
id()))
2398 primary_elem = primary_neigh;
2399 primary_pt1 = neigh_pt1;
2400 primary_pt2 = neigh_pt2;
2403 if (!primary_elem ||
2404 primary_elem != main_neigh ||
2405 primary_pt1 != main_pt1 ||
2406 primary_pt2 != main_pt2)
2417 const Point neigh_pt =
2419 if (neigh_pt > my_node)
2433 neigh->
id() > elem->
id()))
2441 const unsigned int n_comp =
2442 my_node.
n_comp(sys_number, variable_number);
2444 for (
unsigned int i=0; i != n_comp; ++i)
2445 my_constrained_dofs.insert
2447 (sys_number, variable_number, i));
2484 for (
unsigned int js = 0; js != n_side_dofs; ++js)
2490 const unsigned int j = my_side_dofs[js];
2495 if (!my_constrained_dofs.count(my_dof_g))
2509 constraint_row = &(constraints[my_dof_g]);
2513 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
2515 const unsigned int i = neigh_side_dofs[
is];
2516 const dof_id_type their_dof_g = neigh_dof_indices[i];
2523 const Real their_dof_value = Ue[
is](js);
2525 if (their_dof_g == my_dof_g)
2527 libmesh_assert_less (std::abs(their_dof_value-1.), 1.e-5);
2528 for (
unsigned int k = 0; k != n_side_dofs; ++k)
2533 if (std::abs(their_dof_value) < 10*
TOLERANCE)
2538 constraint_row->emplace(their_dof_g, their_dof_value);
2548 const std::set<unsigned int> & variables = periodic->
get_variables();
2549 neigh_dof_indices_all_variables.resize(variables.size());
2550 unsigned int index = 0;
2551 for(
unsigned int other_var : variables)
2553 libmesh_assert_msg(base_fe_type == dof_map.
variable_type(other_var),
"FE types must match for all variables involved in constraint");
2556 constraint_row->emplace(neigh_dof_indices_all_variables[index][i],
2557 var_weighting*their_dof_value);
2569 #ifdef LIBMESH_ENABLE_AMR 2570 const unsigned int min_p_level =
2572 if (min_p_level < elem->p_level())
2580 #endif // #ifdef LIBMESH_ENABLE_AMR 2585 #endif // LIBMESH_ENABLE_PERIODIC
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
FEFamily family
The type of finite element.
bool p_refinement
Whether or not the finite elements for this type increase their p refinement level on geometric eleme...
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
A Node is like a Point, but with more information.
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
virtual void zero() override final
Set every element in the vector to 0.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
virtual void print_dphi(std::ostream &os) const override
Prints the value of each shape function's derivative at each quadrature point.
void compute_dual_shape_functions()
Compute dual_phi, dual_dphi, dual_d2phi It is only valid for this to be called after reinit has occur...
virtual bool is_face(const unsigned int i) const =0
bool has_transformation_matrix() const
IntRange< unsigned short > side_index_range() const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
static constexpr Real TOLERANCE
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
We're using a class instead of a typedef to allow forward declarations and future flexibility...
const std::set< unsigned int > & get_variables() const
Get the set of variables for this periodic boundary condition.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
void resize(const unsigned int n)
Resize the vector.
static void dofs_on_edge(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int e, std::vector< unsigned int > &di, const bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with edge e of element elem A...
This is the base class from which all geometric element types are derived.
boundary_id_type pairedboundary
PeriodicBoundaryBase * boundary(boundary_id_type id)
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
Order default_quadrature_order() const
virtual unsigned int n_children() const =0
unsigned int p_level() const
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
void find_edge_neighbors(const Point &p1, const Point &p2, std::set< const Elem *> &neighbor_set) const
This function finds all active elements in the same manifold as this element which touch the current ...
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
unsigned int min_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
unsigned int sys_number() const
This is the MeshBase class.
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
const Variable & variable(const unsigned int c) const override
IntRange< unsigned short > edge_index_range() const
static void coarsened_dof_values(const NumericVector< Number > &global_vector, const DofMap &dof_map, const Elem *coarse_elem, DenseVector< Number > &coarse_dofs, const unsigned int var, const bool use_old_dof_indices=false)
Creates a local projection on coarse_elem, based on the DoF values in global_vector for it's children...
This class handles the numbering of degrees of freedom on a mesh.
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const =0
virtual Point get_corresponding_pos(const Point &pt) const =0
This function should be overridden by derived classes to define how one finds corresponding nodes on ...
const dof_id_type n_nodes
This class defines the notion of a variable in the system.
void compute_dual_shape_coeffs(const std::vector< Real > &JxW, const std::vector< std::vector< OutputShape >> &phi)
Compute the dual basis coefficients dual_coeff we rely on the JxW (or weights) and the phi values...
const Node & node_ref(const unsigned int i) const
virtual Real hmin() const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
virtual unsigned int n_nodes() const =0
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
unsigned int n_variables() const override
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
This function finds all active elements (including this one) which are in the same manifold as this e...
virtual void print_phi(std::ostream &os) const override
Prints the value of each shape function at each quadrature point.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
bool is_constrained_dof(const dof_id_type dof) const
const FEType & variable_type(const unsigned int i) const
virtual void print_dual_dphi(std::ostream &os) const override
PetscErrorCode PetscInt const PetscInt IS * is
InfMapType inf_map
The coordinate mapping type of the infinite element.
static void compute_proj_constraints(DofConstraints &constraints, DofMap &dof_map, const unsigned int variable_number, const Elem *elem)
Computes the constraint matrix contributions (for non-conforming adapted meshes) corresponding to var...
This is the base class for point locators.
bool active_on_subdomain(subdomain_id_type sid) const
virtual unsigned int n_edges() const =0
TensorTools::MakeNumber< OutputShape >::type OutputNumber
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
virtual_for_inffe void determine_calculations()
Determine which values are to be calculated, for both the FE itself and for the FEMap.
const DenseMatrix< Real > & get_transformation_matrix() const
Get the transformation matrix, if it is defined.
unsigned int max_descendant_p_level() const
static void compute_periodic_constraints(DofConstraints &constraints, DofMap &dof_map, const PeriodicBoundaries &boundaries, const MeshBase &mesh, const PointLocatorBase *point_locator, const unsigned int variable_number, const Elem *elem)
Computes the constraint matrix contributions (for meshes with periodic boundary conditions) correspon...
FEFamily radial_family
The type of approximation in radial direction.
int get_order() const
Explicitly request the order as an int.
std::string enum_to_string(const T e)
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
virtual unsigned int n_sides() const =0
const Elem * neighbor_ptr(unsigned int i) const
unsigned int level() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
virtual unsigned short dim() const =0
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
const Node * node_ptr(const unsigned int i) const
virtual bool is_vertex(const unsigned int i) const =0
unsigned int n_neighbors() const
bool is_my_variable(unsigned int var_num) const
virtual void compute_shape_functions(const Elem *elem, const std::vector< Point > &qp) override
After having updated the jacobian and the transformation from local to global coordinates in FEMap::c...
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
void append(const DenseVector< T2 > &other_vector)
Append additional entries to (resizing, but unchanging) the vector.
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...
virtual void print_dual_phi(std::ostream &os) const override
const Elem * neighbor(boundary_id_type boundary_id, const PointLocatorBase &point_locator, const Elem *e, unsigned int side, unsigned int *neigh_side=nullptr) const
This class implements specific orders of Gauss quadrature.
IntRange< unsigned short > node_index_range() const
static std::unique_ptr< FEGenericBase > build_InfFE(const unsigned int dim, const FEType &type)
Builds a specific infinite element type.
The base class for defining periodic boundaries.
Defines a dense vector for use in Finite Element-type computations.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
virtual bool infinite() const =0
virtual void print_d2phi(std::ostream &os) const override
Prints the value of each shape function's second derivatives at each quadrature point.
virtual void print_dual_d2phi(std::ostream &os) const override
static void dofs_on_side(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int s, std::vector< unsigned int > &di, const bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with side s of element elem A...
A Point defines a location in LIBMESH_DIM dimensional Real space.
The constraint matrix storage format.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
virtual bool is_edge(const unsigned int i) const =0
This class forms the foundation from which generic finite elements may be derived.
const Elem * child_ptr(unsigned int i) const
void constrain_p_dofs(unsigned int var, const Elem *elem, unsigned int s, unsigned int p)
Constrains degrees of freedom on side s of element elem which correspond to variable number var and t...
void old_dof_indices(const Elem &elem, unsigned int n, std::vector< dof_id_type > &di, const unsigned int vn) const
Appends to the vector di the old global degree of freedom indices for elem.node_ref(n), for one variable vn.
const FEType & type() const
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.