49 const Elem * primary_boundary_point_neighbor(
const Elem * elem,
52 const std::set<boundary_id_type> & boundary_ids)
56 const Elem * primary = elem;
59 std::vector<boundary_id_type> bc_ids;
62 std::unique_ptr<const Elem> periodic_side;
64 std::set<const Elem *> point_neighbors;
66 for (
const auto & pt_neighbor : point_neighbors)
72 if ((pt_neighbor->level() > primary->
level()) ||
73 (pt_neighbor->level() == primary->
level() &&
74 pt_neighbor->id() < primary->
id()))
80 bool vertex_on_periodic_side =
false;
81 for (
auto ns : pt_neighbor->side_index_range())
85 bool on_relevant_boundary =
false;
86 for (
const auto &
id : boundary_ids)
87 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
88 on_relevant_boundary =
true;
90 if (!on_relevant_boundary)
93 pt_neighbor->build_side_ptr(periodic_side, ns);
94 if (!periodic_side->contains_point(p))
97 vertex_on_periodic_side =
true;
101 if (vertex_on_periodic_side)
102 primary = pt_neighbor;
109 const Elem * primary_boundary_edge_neighbor(
const Elem * elem,
113 const std::set<boundary_id_type> & boundary_ids)
117 const Elem * primary = elem;
119 std::set<const Elem *> edge_neighbors;
123 std::vector<boundary_id_type> bc_ids;
126 std::unique_ptr<const Elem> periodic_side;
128 for (
const auto & e_neighbor : edge_neighbors)
134 if ((e_neighbor->level() > primary->
level()) ||
135 (e_neighbor->level() == primary->
level() &&
136 e_neighbor->id() < primary->
id()))
142 bool vertex_on_periodic_side =
false;
143 for (
auto ns : e_neighbor->side_index_range())
147 bool on_relevant_boundary =
false;
148 for (
const auto &
id : boundary_ids)
149 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
150 on_relevant_boundary =
true;
152 if (!on_relevant_boundary)
155 e_neighbor->build_side_ptr(periodic_side, ns);
156 if (!(periodic_side->contains_point(p1) &&
157 periodic_side->contains_point(p2)))
160 vertex_on_periodic_side =
true;
164 if (vertex_on_periodic_side)
165 primary = e_neighbor;
181 std::unique_ptr<FEGenericBase<Real>>
193 return libmesh_make_unique<FE<0,CLOUGH>>(fet);
196 return libmesh_make_unique<FE<0,HERMITE>>(fet);
199 return libmesh_make_unique<FE<0,LAGRANGE>>(fet);
202 return libmesh_make_unique<FE<0,L2_LAGRANGE>>(fet);
205 return libmesh_make_unique<FE<0,HIERARCHIC>>(fet);
208 return libmesh_make_unique<FE<0,L2_HIERARCHIC>>(fet);
211 return libmesh_make_unique<FE<0,MONOMIAL>>(fet);
213 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 215 return libmesh_make_unique<FE<0,SZABAB>>(fet);
218 return libmesh_make_unique<FE<0,BERNSTEIN>>(fet);
222 return libmesh_make_unique<FEXYZ<0>>(fet);
225 return libmesh_make_unique<FEScalar<0>>(fet);
228 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
237 return libmesh_make_unique<FE<1,CLOUGH>>(fet);
240 return libmesh_make_unique<FE<1,HERMITE>>(fet);
243 return libmesh_make_unique<FE<1,LAGRANGE>>(fet);
246 return libmesh_make_unique<FE<1,L2_LAGRANGE>>(fet);
249 return libmesh_make_unique<FE<1,HIERARCHIC>>(fet);
252 return libmesh_make_unique<FE<1,L2_HIERARCHIC>>(fet);
255 return libmesh_make_unique<FE<1,MONOMIAL>>(fet);
257 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 259 return libmesh_make_unique<FE<1,SZABAB>>(fet);
262 return libmesh_make_unique<FE<1,BERNSTEIN>>(fet);
266 return libmesh_make_unique<FEXYZ<1>>(fet);
269 return libmesh_make_unique<FEScalar<1>>(fet);
272 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
283 return libmesh_make_unique<FE<2,CLOUGH>>(fet);
286 return libmesh_make_unique<FE<2,HERMITE>>(fet);
289 return libmesh_make_unique<FE<2,LAGRANGE>>(fet);
292 return libmesh_make_unique<FE<2,L2_LAGRANGE>>(fet);
295 return libmesh_make_unique<FE<2,HIERARCHIC>>(fet);
298 return libmesh_make_unique<FE<2,L2_HIERARCHIC>>(fet);
301 return libmesh_make_unique<FE<2,MONOMIAL>>(fet);
303 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 305 return libmesh_make_unique<FE<2,SZABAB>>(fet);
308 return libmesh_make_unique<FE<2,BERNSTEIN>>(fet);
312 return libmesh_make_unique<FEXYZ<2>>(fet);
315 return libmesh_make_unique<FEScalar<2>>(fet);
318 return libmesh_make_unique<FESubdivision>(fet);
321 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
332 libmesh_error_msg(
"ERROR: Clough-Tocher elements currently only support 1D and 2D");
335 return libmesh_make_unique<FE<3,HERMITE>>(fet);
338 return libmesh_make_unique<FE<3,LAGRANGE>>(fet);
341 return libmesh_make_unique<FE<3,L2_LAGRANGE>>(fet);
344 return libmesh_make_unique<FE<3,HIERARCHIC>>(fet);
347 return libmesh_make_unique<FE<3,L2_HIERARCHIC>>(fet);
350 return libmesh_make_unique<FE<3,MONOMIAL>>(fet);
352 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 354 return libmesh_make_unique<FE<3,SZABAB>>(fet);
357 return libmesh_make_unique<FE<3,BERNSTEIN>>(fet);
361 return libmesh_make_unique<FEXYZ<3>>(fet);
364 return libmesh_make_unique<FEScalar<3>>(fet);
367 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
372 libmesh_error_msg(
"Invalid dimension dim = " << dim);
379 std::unique_ptr<FEGenericBase<RealGradient>>
391 return libmesh_make_unique<FELagrangeVec<0>>(fet);
394 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
402 return libmesh_make_unique<FELagrangeVec<1>>(fet);
405 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
413 return libmesh_make_unique<FELagrangeVec<2>>(fet);
416 return libmesh_make_unique<FENedelecOne<2>>(fet);
419 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
427 return libmesh_make_unique<FELagrangeVec<3>>(fet);
430 return libmesh_make_unique<FENedelecOne<3>>(fet);
433 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
438 libmesh_error_msg(
"Invalid dimension dim = " << dim);
448 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 452 std::unique_ptr<FEGenericBase<Real>>
465 libmesh_error_msg(
"ERROR: Can't build an infinite element with FEFamily = " << fet.
radial_family);
472 return libmesh_make_unique<InfFE<1,JACOBI_20_00,CARTESIAN>>(fet);
475 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
484 return libmesh_make_unique<InfFE<1,JACOBI_30_00,CARTESIAN>>(fet);
487 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
496 return libmesh_make_unique<InfFE<1,LEGENDRE,CARTESIAN>>(fet);
499 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
508 return libmesh_make_unique<InfFE<1,LAGRANGE,CARTESIAN>>(fet);
511 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
516 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
529 libmesh_error_msg(
"ERROR: Can't build an infinite element with FEFamily = " << fet.
radial_family);
536 return libmesh_make_unique<InfFE<2,JACOBI_20_00,CARTESIAN>>(fet);
539 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
548 return libmesh_make_unique<InfFE<2,JACOBI_30_00,CARTESIAN>>(fet);
551 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
560 return libmesh_make_unique<InfFE<2,LEGENDRE,CARTESIAN>>(fet);
563 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
572 return libmesh_make_unique<InfFE<2,LAGRANGE,CARTESIAN>>(fet);
575 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
580 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
593 libmesh_error_msg(
"ERROR: Don't build an infinite element with FEFamily = " << fet.
radial_family);
600 return libmesh_make_unique<InfFE<3,JACOBI_20_00,CARTESIAN>>(fet);
603 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
612 return libmesh_make_unique<InfFE<3,JACOBI_30_00,CARTESIAN>>(fet);
615 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
624 return libmesh_make_unique<InfFE<3,LEGENDRE,CARTESIAN>>(fet);
627 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
636 return libmesh_make_unique<InfFE<3,LAGRANGE,CARTESIAN>>(fet);
639 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
644 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
649 libmesh_error_msg(
"Invalid dimension dim = " << dim);
656 std::unique_ptr<FEGenericBase<RealGradient>>
661 libmesh_not_implemented();
662 return std::unique_ptr<FEVectorBase>();
665 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 668 template <
typename OutputType>
670 const std::vector<Point> & qp)
678 LOG_SCOPE(
"compute_shape_functions()",
"FE");
680 this->determine_calculations();
683 this->_fe_trans->map_phi(this->dim, elem, qp, (*
this), this->phi);
686 this->_fe_trans->map_dphi(this->dim, elem, qp, (*
this), this->dphi,
687 this->dphidx, this->dphidy, this->dphidz);
689 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 691 this->_fe_trans->map_d2phi(this->dim, qp, (*
this), this->d2phi,
692 this->d2phidx2, this->d2phidxdy, this->d2phidxdz,
693 this->d2phidy2, this->d2phidydz, this->d2phidz2);
694 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES 698 this->_fe_trans->map_curl(this->dim, elem, qp, (*
this), this->curl_phi);
702 this->_fe_trans->map_div(this->dim, elem, qp, (*
this), this->div_phi);
706 template <
typename OutputType>
711 os <<
" phi[" << i <<
"][" << j <<
"]=" << phi[i][j] << std::endl;
717 template <
typename OutputType>
722 os <<
" dphi[" << i <<
"][" << j <<
"]=" << dphi[i][j];
727 template <
typename OutputType>
730 this->calculations_started =
true;
734 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 735 if (!this->calculate_phi && !this->calculate_dphi && !this->calculate_d2phi
736 && !this->calculate_curl_phi && !this->calculate_div_phi)
738 this->calculate_phi = this->calculate_dphi = this->calculate_d2phi = this->calculate_dphiref =
true;
741 this->calculate_curl_phi =
true;
742 this->calculate_div_phi =
true;
746 if (!this->calculate_phi && !this->calculate_dphi && !this->calculate_curl_phi && !this->calculate_div_phi)
748 this->calculate_phi = this->calculate_dphi = this->calculate_dphiref =
true;
751 this->calculate_curl_phi =
true;
752 this->calculate_div_phi =
true;
755 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES 758 if (this->calculate_phi)
759 this->_fe_trans->init_map_phi(*
this);
761 if (this->calculate_dphiref)
762 this->_fe_trans->init_map_dphi(*
this);
764 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 765 if (this->calculate_d2phi)
766 this->_fe_trans->init_map_d2phi(*
this);
767 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES 772 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 775 template <
typename OutputType>
780 os <<
" d2phi[" << i <<
"][" << j <<
"]=" << d2phi[i][j];
787 #ifdef LIBMESH_ENABLE_AMR 789 template <
typename OutputType>
795 const unsigned int var,
796 const bool use_old_dof_indices)
799 std::vector<unsigned int> new_side_dofs, old_side_dofs;
802 unsigned int dim = elem->
dim();
805 const unsigned int n_children = elem->
n_children();
810 std::unique_ptr<FEGenericBase<OutputShape>> fe
812 std::unique_ptr<FEGenericBase<OutputShape>> fe_coarse
818 std::vector<Point> coarse_qpoints;
822 const std::vector<std::vector<OutputShape>> & phi_values =
824 const std::vector<std::vector<OutputShape>> & phi_coarse =
825 fe_coarse->get_phi();
829 const std::vector<std::vector<OutputGradient>> * dphi_values =
831 const std::vector<std::vector<OutputGradient>> * dphi_coarse =
838 const std::vector<std::vector<OutputGradient>> &
839 ref_dphi_values = fe->get_dphi();
840 dphi_values = &ref_dphi_values;
841 const std::vector<std::vector<OutputGradient>> &
842 ref_dphi_coarse = fe_coarse->get_dphi();
843 dphi_coarse = &ref_dphi_coarse;
847 const std::vector<Real> & JxW =
852 const std::vector<Point> & xyz_values =
857 FEType fe_type = base_fe_type, temp_fe_type;
866 const unsigned int new_n_dofs =
870 std::vector<char> dof_is_fixed(new_n_dofs,
false);
871 std::vector<int> free_dof(new_n_dofs, 0);
887 std::vector<dof_id_type> node_dof_indices;
888 if (use_old_dof_indices)
893 unsigned int current_dof = 0;
894 for (
unsigned int n=0; n!=
n_nodes; ++n)
898 const unsigned int my_nc =
903 current_dof += my_nc;
907 temp_fe_type = base_fe_type;
921 const unsigned int nc =
924 for (
unsigned int i=0; i!= nc; ++i)
927 old_vector(node_dof_indices[current_dof]);
928 dof_is_fixed[current_dof] =
true;
941 const unsigned int n_new_side_dofs =
942 cast_int<unsigned int>(new_side_dofs.size());
946 unsigned int free_dofs = 0;
947 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
948 if (!dof_is_fixed[new_side_dofs[i]])
949 free_dof[free_dofs++] = i;
957 for (
unsigned int c=0; c != n_children; ++c)
963 std::vector<dof_id_type> child_dof_indices;
964 if (use_old_dof_indices)
966 child_dof_indices, var);
969 child_dof_indices, var);
970 const unsigned int child_n_dofs =
971 cast_int<unsigned int>
972 (child_dof_indices.size());
974 temp_fe_type = base_fe_type;
976 static_cast<Order>(temp_fe_type.order +
980 temp_fe_type, e, old_side_dofs);
984 fe->attach_quadrature_rule (qedgerule.get());
985 fe->edge_reinit (child, e);
986 const unsigned int n_qp = qedgerule->n_points();
989 xyz_values, coarse_qpoints);
991 fe_coarse->reinit(elem, &coarse_qpoints);
994 for (
unsigned int qp=0; qp<n_qp; qp++)
1004 for (
unsigned int i=0; i<child_n_dofs;
1008 (old_vector(child_dof_indices[i])*
1011 finegrad += (*dphi_values)[i][qp] *
1012 old_vector(child_dof_indices[i]);
1016 for (
unsigned int sidei=0, freei=0; sidei != n_new_side_dofs; ++sidei)
1018 unsigned int i = new_side_dofs[sidei];
1020 if (dof_is_fixed[i])
1022 for (
unsigned int sidej=0, freej=0; sidej != n_new_side_dofs; ++sidej)
1025 new_side_dofs[sidej];
1026 if (dof_is_fixed[j])
1029 phi_coarse[j][qp]) *
1034 phi_coarse[j][qp]) *
1038 if (dof_is_fixed[j])
1041 (*dphi_coarse)[j][qp]) *
1046 (*dphi_coarse)[j][qp]) *
1049 if (!dof_is_fixed[j])
1064 for (
unsigned int i=0; i != free_dofs; ++i)
1066 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1070 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1081 const unsigned int n_new_side_dofs =
1082 cast_int<unsigned int>(new_side_dofs.size());
1086 unsigned int free_dofs = 0;
1087 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
1088 if (!dof_is_fixed[new_side_dofs[i]])
1089 free_dof[free_dofs++] = i;
1097 for (
unsigned int c=0; c != n_children; ++c)
1103 std::vector<dof_id_type> child_dof_indices;
1104 if (use_old_dof_indices)
1106 child_dof_indices, var);
1109 child_dof_indices, var);
1110 const unsigned int child_n_dofs =
1111 cast_int<unsigned int>
1112 (child_dof_indices.size());
1114 temp_fe_type = base_fe_type;
1115 temp_fe_type.
order =
1116 static_cast<Order>(temp_fe_type.order +
1120 temp_fe_type, s, old_side_dofs);
1124 fe->attach_quadrature_rule (qsiderule.get());
1125 fe->reinit (child, s);
1126 const unsigned int n_qp = qsiderule->n_points();
1129 xyz_values, coarse_qpoints);
1131 fe_coarse->reinit(elem, &coarse_qpoints);
1134 for (
unsigned int qp=0; qp<n_qp; qp++)
1144 for (
unsigned int i=0; i<child_n_dofs;
1148 old_vector(child_dof_indices[i]) *
1151 finegrad += (*dphi_values)[i][qp] *
1152 old_vector(child_dof_indices[i]);
1156 for (
unsigned int sidei=0, freei=0; sidei != n_new_side_dofs; ++sidei)
1158 unsigned int i = new_side_dofs[sidei];
1160 if (dof_is_fixed[i])
1162 for (
unsigned int sidej=0, freej=0; sidej != n_new_side_dofs; ++sidej)
1165 new_side_dofs[sidej];
1166 if (dof_is_fixed[j])
1169 phi_coarse[j][qp]) *
1174 phi_coarse[j][qp]) *
1178 if (dof_is_fixed[j])
1181 (*dphi_coarse)[j][qp]) *
1186 (*dphi_coarse)[j][qp]) *
1189 if (!dof_is_fixed[j])
1203 for (
unsigned int i=0; i != free_dofs; ++i)
1205 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1209 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1217 unsigned int free_dofs = 0;
1218 for (
unsigned int i=0; i != new_n_dofs; ++i)
1219 if (!dof_is_fixed[i])
1220 free_dof[free_dofs++] = i;
1229 std::vector<dof_id_type> child_dof_indices;
1230 if (use_old_dof_indices)
1232 child_dof_indices, var);
1235 child_dof_indices, var);
1236 const unsigned int child_n_dofs =
1237 cast_int<unsigned int>
1238 (child_dof_indices.size());
1242 fe->attach_quadrature_rule (qrule.get());
1243 fe->reinit (&child);
1244 const unsigned int n_qp = qrule->n_points();
1247 xyz_values, coarse_qpoints);
1249 fe_coarse->reinit(elem, &coarse_qpoints);
1252 for (
unsigned int qp=0; qp<n_qp; qp++)
1262 for (
unsigned int i=0; i<child_n_dofs; i++)
1265 (old_vector(child_dof_indices[i]) *
1268 finegrad += (*dphi_values)[i][qp] *
1269 old_vector(child_dof_indices[i]);
1273 for (
unsigned int i=0, freei=0;
1274 i != new_n_dofs; ++i)
1277 if (dof_is_fixed[i])
1279 for (
unsigned int j=0, freej=0; j !=
1282 if (dof_is_fixed[j])
1285 phi_coarse[j][qp]) *
1290 phi_coarse[j][qp]) *
1294 if (dof_is_fixed[j])
1297 (*dphi_coarse)[j][qp]) *
1302 (*dphi_coarse)[j][qp]) *
1305 if (!dof_is_fixed[j])
1319 for (
unsigned int i=0; i != free_dofs; ++i)
1321 Number & ui = Ue(free_dof[i]);
1328 dof_is_fixed[free_dof[i]] =
true;
1334 for (
unsigned int i=0; i != new_n_dofs; ++i)
1335 libmesh_assert(dof_is_fixed[i]);
1341 template <
typename OutputType>
1347 const bool use_old_dof_indices)
1351 for (
unsigned int v=0; v != dof_map.
n_variables(); ++v)
1355 coarsened_dof_values(old_vector, dof_map, elem, Usub,
1356 use_old_dof_indices);
1364 template <
typename OutputType>
1368 const unsigned int variable_number,
1371 libmesh_assert(elem);
1373 const unsigned int Dim = elem->
dim();
1386 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1395 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1399 my_fe->attach_quadrature_rule (&my_qface);
1400 std::vector<Point> neigh_qface;
1402 const std::vector<Real> & JxW = my_fe->get_JxW();
1403 const std::vector<Point> & q_point = my_fe->get_xyz();
1404 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1405 const std::vector<std::vector<OutputShape>> & neigh_phi =
1406 neigh_fe->get_phi();
1407 const std::vector<Point> * face_normals =
nullptr;
1408 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1409 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1411 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1412 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1416 const std::vector<Point> & ref_face_normals =
1417 my_fe->get_normals();
1418 face_normals = &ref_face_normals;
1419 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1422 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1423 neigh_fe->get_dphi();
1424 neigh_dphi = &ref_neigh_dphi;
1429 std::vector<DenseVector<Real>> Ue;
1446 libmesh_assert_less (s_neigh, neigh->
n_neighbors());
1451 libmesh_assert(neigh->
active());
1452 const unsigned int min_p_level =
1457 const unsigned int old_elem_level = elem->
p_level();
1458 if (elem->
p_level() != min_p_level)
1459 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() - old_elem_level + min_p_level);
1460 const unsigned int old_neigh_level = neigh->
p_level();
1461 if (old_neigh_level != min_p_level)
1462 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() - old_neigh_level + min_p_level);
1464 my_fe->reinit(elem, s);
1472 my_dof_indices.reserve (elem->
n_nodes());
1473 neigh_dof_indices.reserve (neigh->
n_nodes());
1482 const unsigned int n_qp = my_qface.n_points();
1485 q_point, neigh_qface);
1487 neigh_fe->reinit(neigh, &neigh_qface);
1491 FEType elem_fe_type = base_fe_type;
1492 if (old_elem_level != min_p_level)
1494 FEType neigh_fe_type = base_fe_type;
1495 if (old_neigh_level != min_p_level)
1500 const unsigned int n_side_dofs =
1501 cast_int<unsigned int>(my_side_dofs.size());
1502 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
1504 Ke.
resize (n_side_dofs, n_side_dofs);
1505 Ue.resize(n_side_dofs);
1509 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1511 const unsigned int i = my_side_dofs[is];
1512 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1514 const unsigned int j = my_side_dofs[js];
1515 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1519 Ke(is,js) += JxW[qp] *
1521 (*face_normals)[qp],
1523 (*face_normals)[qp]);
1530 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1532 const unsigned int i = neigh_side_dofs[is];
1534 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1536 const unsigned int j = my_side_dofs[js];
1537 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1545 (*face_normals)[qp],
1547 (*face_normals)[qp]);
1553 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1555 const unsigned int j = my_side_dofs[js];
1561 bool self_constraint =
false;
1562 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1564 const unsigned int i = neigh_side_dofs[is];
1565 const dof_id_type their_dof_g = neigh_dof_indices[i];
1568 if (their_dof_g == my_dof_g)
1571 const Real their_dof_value = Ue[is](js);
1572 libmesh_assert_less (
std::abs(their_dof_value-1.),
1575 for (
unsigned int k = 0; k != n_side_dofs; ++k)
1576 libmesh_assert(k == is ||
1581 self_constraint =
true;
1586 if (self_constraint)
1600 constraint_row = &(constraints[my_dof_g]);
1601 libmesh_assert(constraint_row->empty());
1604 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1606 const unsigned int i = neigh_side_dofs[is];
1607 const dof_id_type their_dof_g = neigh_dof_indices[i];
1609 libmesh_assert_not_equal_to (their_dof_g, my_dof_g);
1611 const Real their_dof_value = Ue[is](js);
1616 constraint_row->insert(std::make_pair(their_dof_g,
1621 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() + old_elem_level - min_p_level);
1622 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + old_neigh_level - min_p_level);
1629 const unsigned int min_p_level =
1631 if (min_p_level < elem->p_level())
1635 libmesh_assert(my_fe->is_hierarchic());
1642 #endif // #ifdef LIBMESH_ENABLE_AMR 1646 #ifdef LIBMESH_ENABLE_PERIODIC 1647 template <
typename OutputType>
1655 const unsigned int variable_number,
1659 if (boundaries.empty())
1662 libmesh_assert(elem);
1668 const unsigned int Dim = elem->
dim();
1672 const unsigned int sys_number = dof_map.
sys_number();
1677 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1687 const Real primary_hmin = elem->
hmin();
1689 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1693 my_fe->attach_quadrature_rule (&my_qface);
1694 std::vector<Point> neigh_qface;
1696 const std::vector<Real> & JxW = my_fe->get_JxW();
1697 const std::vector<Point> & q_point = my_fe->get_xyz();
1698 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1699 const std::vector<std::vector<OutputShape>> & neigh_phi =
1700 neigh_fe->get_phi();
1701 const std::vector<Point> * face_normals =
nullptr;
1702 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1703 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1704 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1705 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1709 const std::vector<Point> & ref_face_normals =
1710 my_fe->get_normals();
1711 face_normals = &ref_face_normals;
1712 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1715 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1716 neigh_fe->get_dphi();
1717 neigh_dphi = &ref_neigh_dphi;
1722 std::vector<DenseVector<Real>> Ue;
1725 std::vector<boundary_id_type> bc_ids;
1729 const unsigned short int max_ns = elem->
n_sides();
1730 for (
unsigned short int s = 0; s != max_ns; ++s)
1737 for (
const auto & boundary_id : bc_ids)
1742 libmesh_assert(point_locator);
1745 const Elem * neigh = boundaries.
neighbor(boundary_id, *point_locator, elem, s);
1747 if (neigh ==
nullptr)
1748 libmesh_error_msg(
"PeriodicBoundaries point locator object returned nullptr!");
1756 unsigned int s_neigh =
1760 #ifdef LIBMESH_ENABLE_AMR 1764 libmesh_assert(neigh->
active());
1765 const unsigned int min_p_level =
1773 const unsigned int old_elem_level = elem->
p_level();
1774 if (old_elem_level != min_p_level)
1775 (
const_cast<Elem *
>(elem))->hack_p_level(min_p_level);
1776 const unsigned int old_neigh_level = neigh->
p_level();
1777 if (old_neigh_level != min_p_level)
1778 (
const_cast<Elem *
>(neigh))->hack_p_level(min_p_level);
1779 #endif // #ifdef LIBMESH_ENABLE_AMR 1787 my_fe->reinit(elem, s);
1797 std::vector<std::vector<dof_id_type>> neigh_dof_indices_all_variables;
1800 const std::set<unsigned int> & variables = periodic->
get_variables();
1801 neigh_dof_indices_all_variables.resize(variables.size());
1802 unsigned int index = 0;
1803 for(
unsigned int var : variables)
1805 dof_map.
dof_indices (neigh, neigh_dof_indices_all_variables[index],
1811 const unsigned int n_qp = my_qface.n_points();
1815 std::vector<Point> neigh_point(q_point.size());
1820 neigh_point, neigh_qface);
1822 neigh_fe->reinit(neigh, &neigh_qface);
1831 #ifdef LIBMESH_ENABLE_AMR 1832 if (elem->
p_level() != old_elem_level)
1833 (const_cast<Elem *>(elem))->hack_p_level(old_elem_level);
1834 if (neigh->
p_level() != old_neigh_level)
1835 (const_cast<Elem *>(neigh))->hack_p_level(old_neigh_level);
1836 #endif // #ifdef LIBMESH_ENABLE_AMR 1838 const unsigned int n_side_dofs =
1839 cast_int<unsigned int>
1840 (my_side_dofs.size());
1841 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
1843 Ke.
resize (n_side_dofs, n_side_dofs);
1844 Ue.resize(n_side_dofs);
1848 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1850 const unsigned int i = my_side_dofs[is];
1851 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1853 const unsigned int j = my_side_dofs[js];
1854 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1856 Ke(is,js) += JxW[qp] *
1860 Ke(is,js) += JxW[qp] *
1862 (*face_normals)[qp],
1864 (*face_normals)[qp]);
1871 for (
unsigned int is = 0; is != n_side_dofs; ++is)
1873 const unsigned int i = neigh_side_dofs[is];
1875 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1877 const unsigned int j = my_side_dofs[js];
1878 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1886 (*face_normals)[qp],
1888 (*face_normals)[qp]);
1942 std::set<dof_id_type> my_constrained_dofs;
1945 std::vector<boundary_id_type> new_bc_ids;
1947 for (
unsigned int n = 0; n != elem->
n_nodes(); ++n)
1959 std::set<boundary_id_type> point_bcids;
1961 for (
unsigned int new_s = 0;
1962 new_s != max_ns; ++new_s)
1969 for (
const auto & new_boundary_id : new_bc_ids)
1972 if (new_periodic && new_periodic->
is_my_variable(variable_number))
1973 point_bcids.insert(new_boundary_id);
1979 if (primary_boundary_point_neighbor
1985 std::set<boundary_id_type> point_pairedids;
1986 for (
const auto & new_boundary_id : point_bcids)
1993 const Elem * primary_elem =
nullptr;
1994 const Elem * main_neigh =
nullptr;
1995 Point main_pt = my_node,
1996 primary_pt = my_node;
1998 for (
const auto & new_boundary_id : point_bcids)
2004 const Point neigh_pt =
2017 primary_elem = elem;
2019 const Elem * primary_neigh =
2020 primary_boundary_point_neighbor(neigh, neigh_pt,
2024 libmesh_assert(primary_neigh);
2026 if (new_boundary_id == boundary_id)
2028 main_neigh = primary_neigh;
2035 if ((primary_neigh->
level() > primary_elem->
level()) ||
2040 (primary_neigh->
level() == primary_elem->
level() &&
2041 primary_neigh->
id() > primary_elem->
id()) ||
2045 (primary_neigh == primary_elem &&
2046 (neigh_pt > primary_pt)))
2049 primary_elem = primary_neigh;
2050 primary_pt = neigh_pt;
2053 if (!primary_elem ||
2054 primary_elem != main_neigh ||
2055 primary_pt != main_pt)
2062 for (; e != elem->
n_edges(); ++e)
2067 libmesh_assert_less (e, elem->
n_edges());
2073 for (
unsigned int nn = 0; nn != elem->
n_nodes(); ++nn)
2091 libmesh_assert (e1 && e2);
2096 std::set<boundary_id_type> edge_bcids;
2098 for (
unsigned int new_s = 0;
2099 new_s != max_ns; ++new_s)
2107 for (
const auto & new_boundary_id : new_bc_ids)
2110 if (new_periodic && new_periodic->
is_my_variable(variable_number))
2111 edge_bcids.insert(new_boundary_id);
2117 if (primary_boundary_edge_neighbor
2123 std::set<boundary_id_type> edge_pairedids;
2124 for (
const auto & new_boundary_id : edge_bcids)
2131 const Elem * primary_elem =
nullptr;
2132 const Elem * main_neigh =
nullptr;
2133 Point main_pt1 = *e1,
2138 for (
const auto & new_boundary_id : edge_bcids)
2152 neigh_pt2.absolute_fuzzy_equals
2159 primary_elem = elem;
2161 const Elem * primary_neigh = primary_boundary_edge_neighbor
2162 (neigh, neigh_pt1, neigh_pt2,
2165 libmesh_assert(primary_neigh);
2167 if (new_boundary_id == boundary_id)
2169 main_neigh = primary_neigh;
2170 main_pt1 = neigh_pt1;
2171 main_pt2 = neigh_pt2;
2181 if (primary_neigh == primary_elem)
2183 if (primary_pt1 > primary_pt2)
2185 if (neigh_pt1 > neigh_pt2)
2188 if (neigh_pt2 >= primary_pt2)
2196 if ((primary_neigh->
level() > primary_elem->
level()) ||
2201 (primary_neigh->
level() == primary_elem->
level() &&
2202 primary_neigh->
id() > primary_elem->
id()))
2205 primary_elem = primary_neigh;
2206 primary_pt1 = neigh_pt1;
2207 primary_pt2 = neigh_pt2;
2210 if (!primary_elem ||
2211 primary_elem != main_neigh ||
2212 primary_pt1 != main_pt1 ||
2213 primary_pt2 != main_pt2)
2224 const Point neigh_pt =
2226 if (neigh_pt > my_node)
2240 neigh->
id() > elem->
id()))
2248 const unsigned int n_comp =
2249 my_node.
n_comp(sys_number, variable_number);
2251 for (
unsigned int i=0; i != n_comp; ++i)
2252 my_constrained_dofs.insert
2254 (sys_number, variable_number, i));
2291 for (
unsigned int js = 0; js != n_side_dofs; ++js)
2297 const unsigned int j = my_side_dofs[js];
2302 if (!my_constrained_dofs.count(my_dof_g))
2316 constraint_row = &(constraints[my_dof_g]);
2317 libmesh_assert(constraint_row->empty());
2320 for (
unsigned int is = 0; is != n_side_dofs; ++is)
2322 const unsigned int i = neigh_side_dofs[is];
2323 const dof_id_type their_dof_g = neigh_dof_indices[i];
2330 const Real their_dof_value = Ue[is](js);
2332 if (their_dof_g == my_dof_g)
2334 libmesh_assert_less (
std::abs(their_dof_value-1.), 1.e-5);
2335 for (
unsigned int k = 0; k != n_side_dofs; ++k)
2336 libmesh_assert(k == is ||
std::abs(Ue[k](js)) < 1.e-5);
2345 constraint_row->insert(std::make_pair(their_dof_g,
2356 const std::set<unsigned int> & variables = periodic->
get_variables();
2357 neigh_dof_indices_all_variables.resize(variables.size());
2358 unsigned int index = 0;
2359 for(
unsigned int other_var : variables)
2361 libmesh_assert_msg(base_fe_type == dof_map.
variable_type(other_var),
"FE types must match for all variables involved in constraint");
2364 constraint_row->insert(std::make_pair(neigh_dof_indices_all_variables[index][i],
2365 var_weighting*their_dof_value));
2377 #ifdef LIBMESH_ENABLE_AMR 2378 const unsigned int min_p_level =
2380 if (min_p_level < elem->p_level())
2384 libmesh_assert(my_fe->is_hierarchic());
2388 #endif // #ifdef LIBMESH_ENABLE_AMR 2394 #endif // LIBMESH_ENABLE_PERIODIC
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)
Manages the family, order, etc. parameters for a given FE.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
A geometric point in (x,y,z) space associated with a DOF.
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
const unsigned int invalid_uint
unsigned int n_comp(const unsigned int s, const unsigned int var) const
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
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)
Maps between boundary ids and PeriodicBoundaryBase objects.
virtual void compute_shape_functions(const Elem *elem, const std::vector< Point > &qp)
const std::set< unsigned int > & get_variables() const
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
void resize(const unsigned int n)
const FEType & variable_type(const unsigned int c) const
unsigned int side_with_boundary_id(const Elem *const elem, const boundary_id_type boundary_id) const
The base class for all geometric element types.
boundary_id_type pairedboundary
IntRange< std::size_t > index_range(const std::vector< T > &vec)
PeriodicBoundaryBase * boundary(boundary_id_type id)
unsigned int n_variables() const
static FEFieldType field_type(const FEType &fe_type)
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
void find_edge_neighbors(const Point &p1, const Point &p2, std::set< const Elem *> &neighbor_set) const
static const Real TOLERANCE
const BoundaryInfo & get_boundary_info() const
void print_phi(std::ostream &os) const
unsigned int min_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
void old_dof_indices(const Elem *const elem, std::vector< dof_id_type > &di, const unsigned int vn=libMesh::invalid_uint) const
unsigned int sys_number() const
SimpleRange< ChildRefIter > child_ref_range()
IntRange< unsigned short > edge_index_range() const
std::vector< boundary_id_type > boundary_ids(const Node *node) 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)
Manages the degrees of freedom (DOFs) in a simulation.
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
void print_d2phi(std::ostream &os) const
const dof_id_type n_nodes
const Node & node_ref(const unsigned int i) const
virtual Real hmin() const
virtual unsigned int n_nodes() const =0
unsigned int which_neighbor_am_i(const Elem *e) const
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Used by the Mesh to keep track of boundary nodes and elements.
bool is_constrained_dof(const dof_id_type dof) const
static const dof_id_type invalid_id
static Point inverse_map(const unsigned int dim, const FEType &fe_t, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
static void compute_proj_constraints(DofConstraints &constraints, DofMap &dof_map, const unsigned int variable_number, const Elem *elem)
virtual unsigned int n_edges() const =0
TensorTools::MakeNumber< OutputShape >::type OutputNumber
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
void determine_calculations()
const DenseMatrix< Real > & get_transformation_matrix() const
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)
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
const Elem * neighbor(boundary_id_type boundary_id, const PointLocatorBase &point_locator, const Elem *e, unsigned int side) const
virtual unsigned short dim() const =0
const Node * node_ptr(const unsigned int i) const
virtual bool is_vertex(const unsigned int i) const =0
virtual void zero() override
void swap(Iterator &lhs, Iterator &rhs)
unsigned int n_neighbors() const
bool is_my_variable(unsigned int var_num) const
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
void resize(const unsigned int new_m, const unsigned int new_n)
void append(const DenseVector< T2 > &other_vector)
Implements 1, 2, and 3D "Gaussian" quadrature rules.
static std::unique_ptr< FEGenericBase > build_InfFE(const unsigned int dim, const FEType &type)
Base class for all PeriodicBoundary implementations.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
A matrix object used for finite element assembly and numerics.
void print_dphi(std::ostream &os) const
virtual ElemType type() const =0
long double min(long double a, double b)
A geometric point in (x,y,z) space.
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
const Elem * child_ptr(unsigned int i) const
void constrain_p_dofs(unsigned int var, const Elem *elem, unsigned int s, unsigned int p)
virtual void zero() override