21 #include "libmesh/fe.h"
22 #include "libmesh/inf_fe.h"
23 #include "libmesh/libmesh_logging.h"
24 #include "libmesh/auto_ptr.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/numeric_vector.h"
34 #include "libmesh/periodic_boundary_base.h"
35 #include "libmesh/periodic_boundaries.h"
36 #include "libmesh/quadrature.h"
37 #include "libmesh/quadrature_gauss.h"
38 #include "libmesh/tensor_value.h"
39 #include "libmesh/threads.h"
40 #include "libmesh/fe_type.h"
48 #ifdef LIBMESH_ENABLE_PERIODIC
51 const Elem * primary_boundary_point_neighbor(
const Elem * elem,
54 const std::set<boundary_id_type> & boundary_ids)
58 const Elem * primary = elem;
61 std::vector<boundary_id_type> bc_ids;
64 std::unique_ptr<const Elem> periodic_side;
66 std::set<const Elem *> point_neighbors;
68 for (
const auto & pt_neighbor : point_neighbors)
74 if ((pt_neighbor->level() > primary->
level()) ||
75 (pt_neighbor->level() == primary->
level() &&
76 pt_neighbor->id() < primary->
id()))
82 bool vertex_on_periodic_side =
false;
83 for (
auto ns : pt_neighbor->side_index_range())
87 bool on_relevant_boundary =
false;
88 for (
const auto &
id : boundary_ids)
89 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
90 on_relevant_boundary =
true;
92 if (!on_relevant_boundary)
95 pt_neighbor->build_side_ptr(periodic_side, ns);
96 if (!periodic_side->contains_point(p))
99 vertex_on_periodic_side =
true;
103 if (vertex_on_periodic_side)
104 primary = pt_neighbor;
111 const Elem * primary_boundary_edge_neighbor(
const Elem * elem,
115 const std::set<boundary_id_type> & boundary_ids)
119 const Elem * primary = elem;
121 std::set<const Elem *> edge_neighbors;
125 std::vector<boundary_id_type> bc_ids;
128 std::unique_ptr<const Elem> periodic_side;
130 for (
const auto & e_neighbor : edge_neighbors)
136 if ((e_neighbor->level() > primary->
level()) ||
137 (e_neighbor->level() == primary->
level() &&
138 e_neighbor->id() < primary->
id()))
144 bool vertex_on_periodic_side =
false;
145 for (
auto ns : e_neighbor->side_index_range())
149 bool on_relevant_boundary =
false;
150 for (
const auto &
id : boundary_ids)
151 if (std::find(bc_ids.begin(), bc_ids.end(), id) != bc_ids.end())
152 on_relevant_boundary =
true;
154 if (!on_relevant_boundary)
157 e_neighbor->build_side_ptr(periodic_side, ns);
158 if (!(periodic_side->contains_point(p1) &&
159 periodic_side->contains_point(p2)))
162 vertex_on_periodic_side =
true;
166 if (vertex_on_periodic_side)
167 primary = e_neighbor;
173 #endif // LIBMESH_ENABLE_PERIODIC
185 std::unique_ptr<FEGenericBase<Real>>
197 return libmesh_make_unique<FE<0,CLOUGH>>(fet);
200 return libmesh_make_unique<FE<0,HERMITE>>(fet);
203 return libmesh_make_unique<FE<0,LAGRANGE>>(fet);
206 return libmesh_make_unique<FE<0,L2_LAGRANGE>>(fet);
209 return libmesh_make_unique<FE<0,HIERARCHIC>>(fet);
212 return libmesh_make_unique<FE<0,L2_HIERARCHIC>>(fet);
215 return libmesh_make_unique<FE<0,MONOMIAL>>(fet);
217 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
219 return libmesh_make_unique<FE<0,SZABAB>>(fet);
222 return libmesh_make_unique<FE<0,BERNSTEIN>>(fet);
225 return libmesh_make_unique<FE<0,RATIONAL_BERNSTEIN>>(fet);
229 return libmesh_make_unique<FEXYZ<0>>(fet);
232 return libmesh_make_unique<FEScalar<0>>(fet);
235 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
244 return libmesh_make_unique<FE<1,CLOUGH>>(fet);
247 return libmesh_make_unique<FE<1,HERMITE>>(fet);
250 return libmesh_make_unique<FE<1,LAGRANGE>>(fet);
253 return libmesh_make_unique<FE<1,L2_LAGRANGE>>(fet);
256 return libmesh_make_unique<FE<1,HIERARCHIC>>(fet);
259 return libmesh_make_unique<FE<1,L2_HIERARCHIC>>(fet);
262 return libmesh_make_unique<FE<1,MONOMIAL>>(fet);
264 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
266 return libmesh_make_unique<FE<1,SZABAB>>(fet);
269 return libmesh_make_unique<FE<1,BERNSTEIN>>(fet);
272 return libmesh_make_unique<FE<1,RATIONAL_BERNSTEIN>>(fet);
276 return libmesh_make_unique<FEXYZ<1>>(fet);
279 return libmesh_make_unique<FEScalar<1>>(fet);
282 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
293 return libmesh_make_unique<FE<2,CLOUGH>>(fet);
296 return libmesh_make_unique<FE<2,HERMITE>>(fet);
299 return libmesh_make_unique<FE<2,LAGRANGE>>(fet);
302 return libmesh_make_unique<FE<2,L2_LAGRANGE>>(fet);
305 return libmesh_make_unique<FE<2,HIERARCHIC>>(fet);
308 return libmesh_make_unique<FE<2,L2_HIERARCHIC>>(fet);
311 return libmesh_make_unique<FE<2,MONOMIAL>>(fet);
313 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
315 return libmesh_make_unique<FE<2,SZABAB>>(fet);
318 return libmesh_make_unique<FE<2,BERNSTEIN>>(fet);
321 return libmesh_make_unique<FE<2,RATIONAL_BERNSTEIN>>(fet);
325 return libmesh_make_unique<FEXYZ<2>>(fet);
328 return libmesh_make_unique<FEScalar<2>>(fet);
331 return libmesh_make_unique<FESubdivision>(fet);
334 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
345 libmesh_error_msg(
"ERROR: Clough-Tocher elements currently only support 1D and 2D");
348 return libmesh_make_unique<FE<3,HERMITE>>(fet);
351 return libmesh_make_unique<FE<3,LAGRANGE>>(fet);
354 return libmesh_make_unique<FE<3,L2_LAGRANGE>>(fet);
357 return libmesh_make_unique<FE<3,HIERARCHIC>>(fet);
360 return libmesh_make_unique<FE<3,L2_HIERARCHIC>>(fet);
363 return libmesh_make_unique<FE<3,MONOMIAL>>(fet);
365 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
367 return libmesh_make_unique<FE<3,SZABAB>>(fet);
370 return libmesh_make_unique<FE<3,BERNSTEIN>>(fet);
373 return libmesh_make_unique<FE<3,RATIONAL_BERNSTEIN>>(fet);
377 return libmesh_make_unique<FEXYZ<3>>(fet);
380 return libmesh_make_unique<FEScalar<3>>(fet);
383 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
388 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
395 std::unique_ptr<FEGenericBase<RealGradient>>
407 return libmesh_make_unique<FELagrangeVec<0>>(fet);
410 return libmesh_make_unique<FEMonomialVec<0>>(fet);
413 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
421 return libmesh_make_unique<FELagrangeVec<1>>(fet);
424 return libmesh_make_unique<FEMonomialVec<1>>(fet);
427 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
435 return libmesh_make_unique<FELagrangeVec<2>>(fet);
438 return libmesh_make_unique<FEMonomialVec<2>>(fet);
441 return libmesh_make_unique<FENedelecOne<2>>(fet);
444 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
452 return libmesh_make_unique<FELagrangeVec<3>>(fet);
455 return libmesh_make_unique<FEMonomialVec<3>>(fet);
458 return libmesh_make_unique<FENedelecOne<3>>(fet);
461 libmesh_error_msg(
"ERROR: Bad FEType.family= " << fet.
family);
466 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
476 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
480 std::unique_ptr<FEGenericBase<Real>>
493 libmesh_error_msg(
"ERROR: Can't build an infinite element with FEFamily = " << fet.
radial_family);
500 return libmesh_make_unique<InfFE<1,JACOBI_20_00,CARTESIAN>>(fet);
503 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
512 return libmesh_make_unique<InfFE<1,JACOBI_30_00,CARTESIAN>>(fet);
515 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
524 return libmesh_make_unique<InfFE<1,LEGENDRE,CARTESIAN>>(fet);
527 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
536 return libmesh_make_unique<InfFE<1,LAGRANGE,CARTESIAN>>(fet);
539 libmesh_error_msg(
"ERROR: Can't build an infinite element with InfMapType = " << fet.
inf_map);
544 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
557 libmesh_error_msg(
"ERROR: Can't build an infinite element with FEFamily = " << fet.
radial_family);
564 return libmesh_make_unique<InfFE<2,JACOBI_20_00,CARTESIAN>>(fet);
567 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
576 return libmesh_make_unique<InfFE<2,JACOBI_30_00,CARTESIAN>>(fet);
579 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
588 return libmesh_make_unique<InfFE<2,LEGENDRE,CARTESIAN>>(fet);
591 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
600 return libmesh_make_unique<InfFE<2,LAGRANGE,CARTESIAN>>(fet);
603 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
608 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
621 libmesh_error_msg(
"ERROR: Don't build an infinite element with FEFamily = " << fet.
radial_family);
628 return libmesh_make_unique<InfFE<3,JACOBI_20_00,CARTESIAN>>(fet);
631 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
640 return libmesh_make_unique<InfFE<3,JACOBI_30_00,CARTESIAN>>(fet);
643 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
652 return libmesh_make_unique<InfFE<3,LEGENDRE,CARTESIAN>>(fet);
655 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
664 return libmesh_make_unique<InfFE<3,LAGRANGE,CARTESIAN>>(fet);
667 libmesh_error_msg(
"ERROR: Don't build an infinite element with InfMapType = " << fet.
inf_map);
672 libmesh_error_msg(
"ERROR: Bad FEType.radial_family= " << fet.
radial_family);
677 libmesh_error_msg(
"Invalid dimension dim = " <<
dim);
684 std::unique_ptr<FEGenericBase<RealGradient>>
689 libmesh_not_implemented();
690 return std::unique_ptr<FEVectorBase>();
693 #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
696 template <
typename OutputType>
698 const std::vector<Point> & qp)
706 LOG_SCOPE(
"compute_shape_functions()",
"FE");
708 this->determine_calculations();
711 this->_fe_trans->map_phi(this->
dim, elem, qp, (*
this), this->phi);
714 this->_fe_trans->map_dphi(this->
dim, elem, qp, (*
this), this->dphi,
715 this->dphidx, this->dphidy, this->dphidz);
717 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
719 this->_fe_trans->map_d2phi(this->
dim, qp, (*
this), this->d2phi,
720 this->d2phidx2, this->d2phidxdy, this->d2phidxdz,
721 this->d2phidy2, this->d2phidydz, this->d2phidz2);
722 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
726 this->_fe_trans->map_curl(this->
dim, elem, qp, (*
this), this->curl_phi);
730 this->_fe_trans->map_div(this->
dim, elem, qp, (*
this), this->div_phi);
734 template <
typename OutputType>
739 os <<
" phi[" << i <<
"][" << j <<
"]=" << phi[i][j] << std::endl;
745 template <
typename OutputType>
750 os <<
" dphi[" << i <<
"][" << j <<
"]=" << dphi[i][j];
755 template <
typename OutputType>
758 this->calculations_started =
true;
762 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
763 if (!this->calculate_phi && !this->calculate_dphi &&
764 !this->calculate_d2phi && !this->calculate_curl_phi &&
765 !this->calculate_div_phi && !this->calculate_map)
767 this->calculate_phi = this->calculate_dphi = this->calculate_d2phi = this->calculate_dphiref =
true;
770 this->calculate_curl_phi =
true;
771 this->calculate_div_phi =
true;
775 if (!this->calculate_phi && !this->calculate_dphi &&
776 !this->calculate_curl_phi && !this->calculate_div_phi &&
777 !this->calculate_map)
779 this->calculate_phi = this->calculate_dphi = this->calculate_dphiref =
true;
782 this->calculate_curl_phi =
true;
783 this->calculate_div_phi =
true;
786 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
789 if (this->calculate_phi)
790 this->_fe_trans->init_map_phi(*
this);
792 if (this->calculate_dphiref)
793 this->_fe_trans->init_map_dphi(*
this);
795 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
796 if (this->calculate_d2phi)
797 this->_fe_trans->init_map_d2phi(*
this);
798 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
803 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
806 template <
typename OutputType>
811 os <<
" d2phi[" << i <<
"][" << j <<
"]=" << d2phi[i][j];
818 #ifdef LIBMESH_ENABLE_AMR
820 template <
typename OutputType>
826 const unsigned int var,
827 const bool use_old_dof_indices)
830 std::vector<unsigned int> new_side_dofs, old_side_dofs;
833 unsigned int dim = elem->
dim();
836 const unsigned int n_children = elem->
n_children();
841 std::unique_ptr<FEGenericBase<OutputShape>> fe
843 std::unique_ptr<FEGenericBase<OutputShape>> fe_coarse
849 std::vector<Point> coarse_qpoints;
853 const std::vector<std::vector<OutputShape>> & phi_values =
855 const std::vector<std::vector<OutputShape>> & phi_coarse =
856 fe_coarse->get_phi();
860 const std::vector<std::vector<OutputGradient>> * dphi_values =
862 const std::vector<std::vector<OutputGradient>> * dphi_coarse =
869 const std::vector<std::vector<OutputGradient>> &
870 ref_dphi_values = fe->get_dphi();
871 dphi_values = &ref_dphi_values;
872 const std::vector<std::vector<OutputGradient>> &
873 ref_dphi_coarse = fe_coarse->get_dphi();
874 dphi_coarse = &ref_dphi_coarse;
878 const std::vector<Real> & JxW =
883 const std::vector<Point> & xyz_values =
888 FEType fe_type = base_fe_type, temp_fe_type;
890 fe_type.
order = static_cast<Order>(fe_type.
order +
897 const unsigned int new_n_dofs =
901 std::vector<char> dof_is_fixed(new_n_dofs,
false);
902 std::vector<int> free_dof(new_n_dofs, 0);
918 std::vector<dof_id_type> node_dof_indices;
919 if (use_old_dof_indices)
924 unsigned int current_dof = 0;
925 for (
unsigned int n=0; n!=
n_nodes; ++n)
929 const unsigned int my_nc =
934 current_dof += my_nc;
938 temp_fe_type = base_fe_type;
952 const unsigned int nc =
955 for (
unsigned int i=0; i!= nc; ++i)
958 old_vector(node_dof_indices[current_dof]);
959 dof_is_fixed[current_dof] =
true;
972 const unsigned int n_new_side_dofs =
973 cast_int<unsigned int>(new_side_dofs.size());
977 unsigned int free_dofs = 0;
978 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
979 if (!dof_is_fixed[new_side_dofs[i]])
980 free_dof[free_dofs++] = i;
988 for (
unsigned int c=0; c != n_children; ++c)
994 std::vector<dof_id_type> child_dof_indices;
995 if (use_old_dof_indices)
997 child_dof_indices, var);
1000 child_dof_indices, var);
1001 const unsigned int child_n_dofs =
1002 cast_int<unsigned int>
1003 (child_dof_indices.size());
1005 temp_fe_type = base_fe_type;
1006 temp_fe_type.
order =
1007 static_cast<Order>(temp_fe_type.order +
1011 temp_fe_type, e, old_side_dofs);
1015 fe->attach_quadrature_rule (qedgerule.get());
1016 fe->edge_reinit (child, e);
1017 const unsigned int n_qp = qedgerule->n_points();
1022 fe_coarse->reinit(elem, &coarse_qpoints);
1025 for (
unsigned int qp=0; qp<n_qp; qp++)
1035 for (
unsigned int i=0; i<child_n_dofs;
1039 (old_vector(child_dof_indices[i])*
1042 finegrad += (*dphi_values)[i][qp] *
1043 old_vector(child_dof_indices[i]);
1047 for (
unsigned int sidei=0, freei=0; sidei != n_new_side_dofs; ++sidei)
1049 unsigned int i = new_side_dofs[sidei];
1051 if (dof_is_fixed[i])
1053 for (
unsigned int sidej=0, freej=0; sidej != n_new_side_dofs; ++sidej)
1056 new_side_dofs[sidej];
1057 if (dof_is_fixed[j])
1060 phi_coarse[j][qp]) *
1065 phi_coarse[j][qp]) *
1069 if (dof_is_fixed[j])
1072 (*dphi_coarse)[j][qp]) *
1077 (*dphi_coarse)[j][qp]) *
1080 if (!dof_is_fixed[j])
1095 for (
unsigned int i=0; i != free_dofs; ++i)
1097 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1101 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1112 const unsigned int n_new_side_dofs =
1113 cast_int<unsigned int>(new_side_dofs.size());
1117 unsigned int free_dofs = 0;
1118 for (
unsigned int i=0; i != n_new_side_dofs; ++i)
1119 if (!dof_is_fixed[new_side_dofs[i]])
1120 free_dof[free_dofs++] = i;
1128 for (
unsigned int c=0; c != n_children; ++c)
1134 std::vector<dof_id_type> child_dof_indices;
1135 if (use_old_dof_indices)
1137 child_dof_indices, var);
1140 child_dof_indices, var);
1141 const unsigned int child_n_dofs =
1142 cast_int<unsigned int>
1143 (child_dof_indices.size());
1145 temp_fe_type = base_fe_type;
1146 temp_fe_type.
order =
1147 static_cast<Order>(temp_fe_type.order +
1151 temp_fe_type, s, old_side_dofs);
1155 fe->attach_quadrature_rule (qsiderule.get());
1156 fe->reinit (child, s);
1157 const unsigned int n_qp = qsiderule->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])
1234 for (
unsigned int i=0; i != free_dofs; ++i)
1236 Number & ui = Ue(new_side_dofs[free_dof[i]]);
1240 dof_is_fixed[new_side_dofs[free_dof[i]]] =
true;
1248 unsigned int free_dofs = 0;
1249 for (
unsigned int i=0; i != new_n_dofs; ++i)
1250 if (!dof_is_fixed[i])
1251 free_dof[free_dofs++] = i;
1260 std::vector<dof_id_type> child_dof_indices;
1261 if (use_old_dof_indices)
1263 child_dof_indices, var);
1266 child_dof_indices, var);
1267 const unsigned int child_n_dofs =
1268 cast_int<unsigned int>
1269 (child_dof_indices.size());
1273 fe->attach_quadrature_rule (qrule.get());
1274 fe->reinit (&child);
1275 const unsigned int n_qp = qrule->n_points();
1279 fe_coarse->reinit(elem, &coarse_qpoints);
1282 for (
unsigned int qp=0; qp<n_qp; qp++)
1292 for (
unsigned int i=0; i<child_n_dofs; i++)
1295 (old_vector(child_dof_indices[i]) *
1298 finegrad += (*dphi_values)[i][qp] *
1299 old_vector(child_dof_indices[i]);
1303 for (
unsigned int i=0, freei=0;
1304 i != new_n_dofs; ++i)
1307 if (dof_is_fixed[i])
1309 for (
unsigned int j=0, freej=0; j !=
1312 if (dof_is_fixed[j])
1315 phi_coarse[j][qp]) *
1320 phi_coarse[j][qp]) *
1324 if (dof_is_fixed[j])
1327 (*dphi_coarse)[j][qp]) *
1332 (*dphi_coarse)[j][qp]) *
1335 if (!dof_is_fixed[j])
1349 for (
unsigned int i=0; i != free_dofs; ++i)
1351 Number & ui = Ue(free_dof[i]);
1358 dof_is_fixed[free_dof[i]] =
true;
1364 for (
unsigned int i=0; i != new_n_dofs; ++i)
1371 template <
typename OutputType>
1377 const bool use_old_dof_indices)
1381 for (
unsigned int v=0; v != dof_map.
n_variables(); ++v)
1385 coarsened_dof_values(old_vector, dof_map, elem, Usub,
1386 v, use_old_dof_indices);
1394 template <
typename OutputType>
1398 const unsigned int variable_number,
1403 const unsigned int Dim = elem->
dim();
1417 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1426 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1430 my_fe->attach_quadrature_rule (&my_qface);
1431 std::vector<Point> neigh_qface;
1433 const std::vector<Real> & JxW = my_fe->get_JxW();
1434 const std::vector<Point> & q_point = my_fe->get_xyz();
1435 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1436 const std::vector<std::vector<OutputShape>> & neigh_phi =
1437 neigh_fe->get_phi();
1438 const std::vector<Point> * face_normals =
nullptr;
1439 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1440 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1442 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1443 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1447 const std::vector<Point> & ref_face_normals =
1448 my_fe->get_normals();
1449 face_normals = &ref_face_normals;
1450 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1453 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1454 neigh_fe->get_dphi();
1455 neigh_dphi = &ref_neigh_dphi;
1460 std::vector<DenseVector<Real>> Ue;
1482 libmesh_assert_less (s_neigh, neigh->
n_neighbors());
1488 const unsigned int min_p_level =
1493 const unsigned int old_elem_level = elem->
p_level();
1494 if (elem->
p_level() != min_p_level)
1495 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() - old_elem_level + min_p_level);
1496 const unsigned int old_neigh_level = neigh->
p_level();
1497 if (old_neigh_level != min_p_level)
1498 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() - old_neigh_level + min_p_level);
1500 my_fe->reinit(elem, s);
1508 my_dof_indices.reserve (elem->
n_nodes());
1509 neigh_dof_indices.reserve (neigh->
n_nodes());
1518 const unsigned int n_qp = my_qface.n_points();
1522 neigh_fe->reinit(neigh, &neigh_qface);
1526 FEType elem_fe_type = base_fe_type;
1527 if (old_elem_level != min_p_level)
1529 FEType neigh_fe_type = base_fe_type;
1530 if (old_neigh_level != min_p_level)
1535 const unsigned int n_side_dofs =
1536 cast_int<unsigned int>(my_side_dofs.size());
1537 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
1540 for (
auto i : my_side_dofs)
1541 libmesh_assert_less(i, my_dof_indices.size());
1542 for (
auto i : neigh_side_dofs)
1543 libmesh_assert_less(i, neigh_dof_indices.size());
1546 Ke.
resize (n_side_dofs, n_side_dofs);
1547 Ue.resize(n_side_dofs);
1551 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1553 const unsigned int i = my_side_dofs[
is];
1554 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1556 const unsigned int j = my_side_dofs[js];
1557 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1561 Ke(
is,js) += JxW[qp] *
1563 (*face_normals)[qp],
1565 (*face_normals)[qp]);
1572 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1574 const unsigned int i = neigh_side_dofs[
is];
1576 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1578 const unsigned int j = my_side_dofs[js];
1579 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1587 (*face_normals)[qp],
1589 (*face_normals)[qp]);
1595 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1597 const unsigned int j = my_side_dofs[js];
1603 bool self_constraint =
false;
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];
1610 if (their_dof_g == my_dof_g)
1613 const Real their_dof_value = Ue[
is](js);
1614 libmesh_assert_less (
std::abs(their_dof_value-1.),
1617 for (
unsigned int k = 0; k != n_side_dofs; ++k)
1623 self_constraint =
true;
1628 if (self_constraint)
1642 constraint_row = &(constraints[my_dof_g]);
1646 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1648 const unsigned int i = neigh_side_dofs[
is];
1649 const dof_id_type their_dof_g = neigh_dof_indices[i];
1651 libmesh_assert_not_equal_to (their_dof_g, my_dof_g);
1653 const Real their_dof_value = Ue[
is](js);
1658 constraint_row->insert(std::make_pair(their_dof_g,
1663 my_fe->set_fe_order(my_fe->get_fe_type().order.get_order() + old_elem_level - min_p_level);
1664 neigh_fe->set_fe_order(neigh_fe->get_fe_type().order.get_order() + old_neigh_level - min_p_level);
1671 const unsigned int min_p_level =
1673 if (min_p_level < elem->p_level())
1684 #endif // #ifdef LIBMESH_ENABLE_AMR
1688 #ifdef LIBMESH_ENABLE_PERIODIC
1689 template <
typename OutputType>
1697 const unsigned int variable_number,
1701 if (boundaries.empty())
1710 const unsigned int Dim = elem->
dim();
1714 const unsigned int sys_number = dof_map.
sys_number();
1719 std::unique_ptr<FEGenericBase<OutputShape>> my_fe
1729 const Real primary_hmin = elem->
hmin();
1731 std::unique_ptr<FEGenericBase<OutputShape>> neigh_fe
1735 my_fe->attach_quadrature_rule (&my_qface);
1736 std::vector<Point> neigh_qface;
1738 const std::vector<Real> & JxW = my_fe->get_JxW();
1739 const std::vector<Point> & q_point = my_fe->get_xyz();
1740 const std::vector<std::vector<OutputShape>> & phi = my_fe->get_phi();
1741 const std::vector<std::vector<OutputShape>> & neigh_phi =
1742 neigh_fe->get_phi();
1743 const std::vector<Point> * face_normals =
nullptr;
1744 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1745 const std::vector<std::vector<OutputGradient>> * neigh_dphi =
nullptr;
1746 std::vector<dof_id_type> my_dof_indices, neigh_dof_indices;
1747 std::vector<unsigned int> my_side_dofs, neigh_side_dofs;
1751 const std::vector<Point> & ref_face_normals =
1752 my_fe->get_normals();
1753 face_normals = &ref_face_normals;
1754 const std::vector<std::vector<OutputGradient>> & ref_dphi =
1757 const std::vector<std::vector<OutputGradient>> & ref_neigh_dphi =
1758 neigh_fe->get_dphi();
1759 neigh_dphi = &ref_neigh_dphi;
1764 std::vector<DenseVector<Real>> Ue;
1767 std::vector<boundary_id_type> bc_ids;
1771 const unsigned short int max_ns = elem->
n_sides();
1772 for (
unsigned short int s = 0; s != max_ns; ++s)
1779 for (
const auto & boundary_id : bc_ids)
1787 const Elem * neigh = boundaries.
neighbor(boundary_id, *point_locator, elem, s);
1789 if (neigh ==
nullptr)
1790 libmesh_error_msg(
"PeriodicBoundaries point locator object returned nullptr!");
1798 unsigned int s_neigh =
1802 #ifdef LIBMESH_ENABLE_AMR
1807 const unsigned int min_p_level =
1815 const unsigned int old_elem_level = elem->
p_level();
1816 if (old_elem_level != min_p_level)
1817 (const_cast<Elem *>(elem))->hack_p_level(min_p_level);
1818 const unsigned int old_neigh_level = neigh->
p_level();
1819 if (old_neigh_level != min_p_level)
1820 (const_cast<Elem *>(neigh))->hack_p_level(min_p_level);
1821 #endif // #ifdef LIBMESH_ENABLE_AMR
1829 my_fe->reinit(elem, s);
1839 std::vector<std::vector<dof_id_type>> neigh_dof_indices_all_variables;
1842 const std::set<unsigned int> & variables = periodic->
get_variables();
1843 neigh_dof_indices_all_variables.resize(variables.size());
1844 unsigned int index = 0;
1845 for(
unsigned int var : variables)
1847 dof_map.
dof_indices (neigh, neigh_dof_indices_all_variables[index],
1853 const unsigned int n_qp = my_qface.n_points();
1857 std::vector<Point> neigh_point(q_point.size());
1864 neigh_fe->reinit(neigh, &neigh_qface);
1873 #ifdef LIBMESH_ENABLE_AMR
1874 if (elem->
p_level() != old_elem_level)
1875 (const_cast<Elem *>(elem))->hack_p_level(old_elem_level);
1876 if (neigh->
p_level() != old_neigh_level)
1877 (const_cast<Elem *>(neigh))->hack_p_level(old_neigh_level);
1878 #endif // #ifdef LIBMESH_ENABLE_AMR
1880 const unsigned int n_side_dofs =
1881 cast_int<unsigned int>
1882 (my_side_dofs.size());
1883 libmesh_assert_equal_to (n_side_dofs, neigh_side_dofs.size());
1885 Ke.
resize (n_side_dofs, n_side_dofs);
1886 Ue.resize(n_side_dofs);
1890 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1892 const unsigned int i = my_side_dofs[
is];
1893 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1895 const unsigned int j = my_side_dofs[js];
1896 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1898 Ke(
is,js) += JxW[qp] *
1902 Ke(
is,js) += JxW[qp] *
1904 (*face_normals)[qp],
1906 (*face_normals)[qp]);
1913 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
1915 const unsigned int i = neigh_side_dofs[
is];
1917 for (
unsigned int js = 0; js != n_side_dofs; ++js)
1919 const unsigned int j = my_side_dofs[js];
1920 for (
unsigned int qp = 0; qp != n_qp; ++qp)
1928 (*face_normals)[qp],
1930 (*face_normals)[qp]);
1984 std::set<dof_id_type> my_constrained_dofs;
1987 std::vector<boundary_id_type> new_bc_ids;
2001 std::set<boundary_id_type> point_bcids;
2003 for (
unsigned int new_s = 0;
2004 new_s != max_ns; ++new_s)
2011 for (
const auto & new_boundary_id : new_bc_ids)
2014 if (new_periodic && new_periodic->
is_my_variable(variable_number))
2015 point_bcids.insert(new_boundary_id);
2021 if (primary_boundary_point_neighbor
2027 std::set<boundary_id_type> point_pairedids;
2028 for (
const auto & new_boundary_id : point_bcids)
2035 const Elem * primary_elem =
nullptr;
2036 const Elem * main_neigh =
nullptr;
2037 Point main_pt = my_node,
2038 primary_pt = my_node;
2040 for (
const auto & new_boundary_id : point_bcids)
2046 const Point neigh_pt =
2059 primary_elem = elem;
2061 const Elem * primary_neigh =
2062 primary_boundary_point_neighbor(neigh, neigh_pt,
2068 if (new_boundary_id == boundary_id)
2070 main_neigh = primary_neigh;
2077 if ((primary_neigh->
level() > primary_elem->
level()) ||
2082 (primary_neigh->
level() == primary_elem->
level() &&
2083 primary_neigh->
id() > primary_elem->
id()) ||
2087 (primary_neigh == primary_elem &&
2088 (neigh_pt > primary_pt)))
2091 primary_elem = primary_neigh;
2092 primary_pt = neigh_pt;
2095 if (!primary_elem ||
2096 primary_elem != main_neigh ||
2097 primary_pt != main_pt)
2103 unsigned int e=0, ne = elem->
n_edges();
2104 for (; e != ne; ++e)
2109 libmesh_assert_less (e, elem->
n_edges());
2138 std::set<boundary_id_type> edge_bcids;
2140 for (
unsigned int new_s = 0;
2141 new_s != max_ns; ++new_s)
2149 for (
const auto & new_boundary_id : new_bc_ids)
2152 if (new_periodic && new_periodic->
is_my_variable(variable_number))
2153 edge_bcids.insert(new_boundary_id);
2159 if (primary_boundary_edge_neighbor
2165 std::set<boundary_id_type> edge_pairedids;
2166 for (
const auto & new_boundary_id : edge_bcids)
2173 const Elem * primary_elem =
nullptr;
2174 const Elem * main_neigh =
nullptr;
2175 Point main_pt1 = *e1,
2180 for (
const auto & new_boundary_id : edge_bcids)
2194 neigh_pt2.absolute_fuzzy_equals
2201 primary_elem = elem;
2203 const Elem * primary_neigh = primary_boundary_edge_neighbor
2204 (neigh, neigh_pt1, neigh_pt2,
2209 if (new_boundary_id == boundary_id)
2211 main_neigh = primary_neigh;
2212 main_pt1 = neigh_pt1;
2213 main_pt2 = neigh_pt2;
2223 if (primary_neigh == primary_elem)
2225 if (primary_pt1 > primary_pt2)
2227 if (neigh_pt1 > neigh_pt2)
2230 if (neigh_pt2 >= primary_pt2)
2238 if ((primary_neigh->
level() > primary_elem->
level()) ||
2243 (primary_neigh->
level() == primary_elem->
level() &&
2244 primary_neigh->
id() > primary_elem->
id()))
2247 primary_elem = primary_neigh;
2248 primary_pt1 = neigh_pt1;
2249 primary_pt2 = neigh_pt2;
2252 if (!primary_elem ||
2253 primary_elem != main_neigh ||
2254 primary_pt1 != main_pt1 ||
2255 primary_pt2 != main_pt2)
2266 const Point neigh_pt =
2268 if (neigh_pt > my_node)
2282 neigh->
id() > elem->
id()))
2290 const unsigned int n_comp =
2291 my_node.
n_comp(sys_number, variable_number);
2293 for (
unsigned int i=0; i != n_comp; ++i)
2294 my_constrained_dofs.insert
2296 (sys_number, variable_number, i));
2333 for (
unsigned int js = 0; js != n_side_dofs; ++js)
2339 const unsigned int j = my_side_dofs[js];
2344 if (!my_constrained_dofs.count(my_dof_g))
2358 constraint_row = &(constraints[my_dof_g]);
2362 for (
unsigned int is = 0;
is != n_side_dofs; ++
is)
2364 const unsigned int i = neigh_side_dofs[
is];
2365 const dof_id_type their_dof_g = neigh_dof_indices[i];
2372 const Real their_dof_value = Ue[
is](js);
2374 if (their_dof_g == my_dof_g)
2376 libmesh_assert_less (
std::abs(their_dof_value-1.), 1.e-5);
2377 for (
unsigned int k = 0; k != n_side_dofs; ++k)
2387 constraint_row->insert(std::make_pair(their_dof_g,
2398 const std::set<unsigned int> & variables = periodic->
get_variables();
2399 neigh_dof_indices_all_variables.resize(variables.size());
2400 unsigned int index = 0;
2401 for(
unsigned int other_var : variables)
2403 libmesh_assert_msg(base_fe_type == dof_map.
variable_type(other_var),
"FE types must match for all variables involved in constraint");
2406 constraint_row->insert(std::make_pair(neigh_dof_indices_all_variables[index][i],
2407 var_weighting*their_dof_value));
2419 #ifdef LIBMESH_ENABLE_AMR
2420 const unsigned int min_p_level =
2422 if (min_p_level < elem->p_level())
2430 #endif // #ifdef LIBMESH_ENABLE_AMR
2436 #endif // LIBMESH_ENABLE_PERIODIC