19 #include "libmesh/dof_map.h" 22 #include "libmesh/boundary_info.h" 23 #include "libmesh/dense_matrix.h" 24 #include "libmesh/dense_vector.h" 25 #include "libmesh/dirichlet_boundaries.h" 26 #include "libmesh/elem.h" 27 #include "libmesh/elem_range.h" 28 #include "libmesh/fe_base.h" 29 #include "libmesh/fe_interface.h" 30 #include "libmesh/fe_type.h" 31 #include "libmesh/function_base.h" 32 #include "libmesh/int_range.h" 33 #include "libmesh/libmesh_logging.h" 34 #include "libmesh/linear_solver.h" 35 #include "libmesh/mesh_base.h" 36 #include "libmesh/null_output_iterator.h" 37 #include "libmesh/mesh_tools.h" 38 #include "libmesh/nonlinear_implicit_system.h" 39 #include "libmesh/numeric_vector.h" 40 #include "libmesh/parallel_algebra.h" 41 #include "libmesh/parallel_elem.h" 42 #include "libmesh/parallel_node.h" 43 #include "libmesh/periodic_boundaries.h" 44 #include "libmesh/periodic_boundary.h" 45 #include "libmesh/periodic_boundary_base.h" 46 #include "libmesh/point_locator_base.h" 47 #include "libmesh/quadrature.h" 48 #include "libmesh/raw_accessor.h" 49 #include "libmesh/sparse_matrix.h" 50 #include "libmesh/static_condensation_dof_map.h" 51 #include "libmesh/system.h" 52 #include "libmesh/tensor_tools.h" 53 #include "libmesh/threads.h" 54 #include "libmesh/enum_to_string.h" 55 #include "libmesh/coupling_matrix.h" 69 #include <unordered_set> 76 class ComputeConstraints
81 #ifdef LIBMESH_ENABLE_PERIODIC
85 const unsigned int variable_number) :
86 _constraints(constraints),
88 #ifdef LIBMESH_ENABLE_PERIODIC
89 _periodic_boundaries(periodic_boundaries),
92 _variable_number(variable_number)
97 const Variable & var_description = _dof_map.variable(_variable_number);
99 #ifdef LIBMESH_ENABLE_PERIODIC 100 std::unique_ptr<PointLocatorBase> point_locator;
101 const bool have_periodic_boundaries =
102 !_periodic_boundaries.empty();
103 if (have_periodic_boundaries && !range.
empty())
104 point_locator = _mesh.sub_point_locator();
107 for (
const auto & elem : range)
110 #ifdef LIBMESH_ENABLE_AMR 116 #ifdef LIBMESH_ENABLE_PERIODIC 120 if (have_periodic_boundaries)
123 _periodic_boundaries,
135 #ifdef LIBMESH_ENABLE_PERIODIC 139 const unsigned int _variable_number;
144 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 145 class ComputeNodeConstraints
149 #ifdef LIBMESH_ENABLE_PERIODIC
153 _node_constraints(node_constraints),
154 #ifdef LIBMESH_ENABLE_PERIODIC
155 _periodic_boundaries(periodic_boundaries),
162 #ifdef LIBMESH_ENABLE_PERIODIC 163 std::unique_ptr<PointLocatorBase> point_locator;
164 bool have_periodic_boundaries = !_periodic_boundaries.empty();
165 if (have_periodic_boundaries && !range.
empty())
166 point_locator = _mesh.sub_point_locator();
169 for (
const auto & elem : range)
171 #ifdef LIBMESH_ENABLE_AMR 174 #ifdef LIBMESH_ENABLE_PERIODIC 178 if (have_periodic_boundaries)
180 _periodic_boundaries,
190 #ifdef LIBMESH_ENABLE_PERIODIC 195 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 198 #ifdef LIBMESH_ENABLE_DIRICHLET 209 AddConstraint(
DofMap & dof_map_in) : dof_map(dof_map_in) {}
213 const Number constraint_rhs)
const = 0;
216 class AddPrimalConstraint :
public AddConstraint
219 AddPrimalConstraint(
DofMap & dof_map_in) : AddConstraint(dof_map_in) {}
223 const Number constraint_rhs)
const 225 if (!dof_map.is_constrained_dof(dof_number))
226 dof_map.add_constraint_row (dof_number, constraint_row,
227 constraint_rhs,
true);
231 class AddAdjointConstraint :
public AddConstraint
234 const unsigned int qoi_index;
237 AddAdjointConstraint(
DofMap & dof_map_in,
unsigned int qoi_index_in)
238 : AddConstraint(dof_map_in), qoi_index(qoi_index_in) {}
242 const Number constraint_rhs)
const 244 dof_map.add_adjoint_constraint_row
245 (qoi_index, dof_number, constraint_row, constraint_rhs,
257 class ConstrainDirichlet
265 const AddConstraint & add_fn;
279 return std::numeric_limits<Real>::quiet_NaN();
296 return std::numeric_limits<Number>::quiet_NaN();
309 struct SingleElemBoundaryInfo
312 const std::map<
boundary_id_type, std::set<std::pair<unsigned int, DirichletBoundary *>>> & ordered_map_in) :
314 boundary_id_to_ordered_dirichlet_boundaries(ordered_map_in),
322 const std::map<boundary_id_type, std::set<std::pair<unsigned int, DirichletBoundary *>>> & boundary_id_to_ordered_dirichlet_boundaries;
325 unsigned short n_sides;
326 unsigned short n_edges;
332 std::map<const DirichletBoundary *, std::vector<bool>> is_boundary_node_map;
333 std::map<const DirichletBoundary *, std::vector<bool>> is_boundary_side_map;
334 std::map<const DirichletBoundary *, std::vector<bool>> is_boundary_edge_map;
335 std::map<const DirichletBoundary *, std::vector<bool>> is_boundary_shellface_map;
337 std::map<const DirichletBoundary *, std::vector<bool>> is_boundary_nodeset_map;
341 std::set<std::pair<unsigned int, DirichletBoundary *>> ordered_dbs;
350 bool reinit(
const Elem * elem_in)
359 is_boundary_node_map.clear();
360 is_boundary_side_map.clear();
361 is_boundary_edge_map.clear();
362 is_boundary_shellface_map.clear();
363 is_boundary_nodeset_map.clear();
370 bool has_dirichlet_constraint =
false;
374 std::vector<boundary_id_type> ids_vec;
376 for (
unsigned char s = 0; s != n_sides; ++s)
381 bool do_this_side =
false;
382 for (
const auto & bc_id : ids_vec)
384 if (
auto it = boundary_id_to_ordered_dirichlet_boundaries.find(bc_id);
385 it != boundary_id_to_ordered_dirichlet_boundaries.end())
390 ordered_dbs.insert(it->second.begin(), it->second.end());
393 for (
const auto & db_pair : it->second)
400 auto pr = is_boundary_side_map.emplace(db_pair.second, std::vector<bool>(n_sides,
false));
401 pr.first->second[s] =
true;
409 has_dirichlet_constraint =
true;
412 for (
unsigned int n = 0; n !=
n_nodes; ++n)
420 for (
const auto & db_pair : ordered_dbs)
424 if (
auto side_it = is_boundary_side_map.find(db_pair.second);
425 side_it != is_boundary_side_map.end() && side_it->second[s])
427 auto pr = is_boundary_node_map.emplace(db_pair.second, std::vector<bool>(
n_nodes,
false));
428 pr.first->second[n] =
true;
434 for (
unsigned int e = 0; e != n_edges; ++e)
442 for (
const auto & db_pair : ordered_dbs)
446 if (
auto side_it = is_boundary_side_map.find(db_pair.second);
447 side_it != is_boundary_side_map.end() && side_it->second[s])
449 auto pr = is_boundary_edge_map.emplace(db_pair.second, std::vector<bool>(n_edges,
false));
450 pr.first->second[e] =
true;
458 for (
unsigned int n=0; n !=
n_nodes; ++n)
462 for (
const auto & bc_id : ids_vec)
464 if (
auto it = boundary_id_to_ordered_dirichlet_boundaries.find(bc_id);
465 it != boundary_id_to_ordered_dirichlet_boundaries.end())
468 ordered_dbs.insert(it->second.begin(), it->second.end());
471 for (
const auto & db_pair : it->second)
473 auto pr = is_boundary_node_map.emplace(db_pair.second, std::vector<bool>(
n_nodes,
false));
474 pr.first->second[n] =
true;
476 auto pr2 = is_boundary_nodeset_map.emplace(db_pair.second, std::vector<bool>(
n_nodes,
false));
477 pr2.first->second[n] =
true;
480 has_dirichlet_constraint =
true;
487 for (
unsigned short e=0; e != n_edges; ++e)
491 bool do_this_side =
false;
492 for (
const auto & bc_id : ids_vec)
494 if (
auto it = boundary_id_to_ordered_dirichlet_boundaries.find(bc_id);
495 it != boundary_id_to_ordered_dirichlet_boundaries.end())
500 ordered_dbs.insert(it->second.begin(), it->second.end());
503 for (
const auto & db_pair : it->second)
505 auto pr = is_boundary_edge_map.emplace(db_pair.second, std::vector<bool>(n_edges,
false));
506 pr.first->second[e] =
true;
514 has_dirichlet_constraint =
true;
517 for (
unsigned int n = 0; n !=
n_nodes; ++n)
525 for (
const auto & db_pair : ordered_dbs)
529 if (
auto edge_it = is_boundary_edge_map.find(db_pair.second);
530 edge_it != is_boundary_edge_map.end() && edge_it->second[e])
532 auto pr = is_boundary_node_map.emplace(db_pair.second, std::vector<bool>(
n_nodes,
false));
533 pr.first->second[n] =
true;
541 for (
unsigned short shellface=0; shellface != 2; ++shellface)
544 bool do_this_shellface =
false;
546 for (
const auto & bc_id : ids_vec)
548 if (
auto it = boundary_id_to_ordered_dirichlet_boundaries.find(bc_id);
549 it != boundary_id_to_ordered_dirichlet_boundaries.end())
551 has_dirichlet_constraint =
true;
552 do_this_shellface =
true;
555 ordered_dbs.insert(it->second.begin(), it->second.end());
558 for (
const auto & db_pair : it->second)
560 auto pr = is_boundary_shellface_map.emplace(db_pair.second, std::vector<bool>(2,
false));
561 pr.first->second[shellface] =
true;
566 if (do_this_shellface)
569 for (
unsigned int n = 0; n !=
n_nodes; ++n)
570 for (
const auto & db_pair : ordered_dbs)
574 if (
auto side_it = is_boundary_shellface_map.find(db_pair.second);
575 side_it != is_boundary_shellface_map.end() && side_it->second[shellface])
577 auto pr = is_boundary_node_map.emplace(db_pair.second, std::vector<bool>(
n_nodes,
false));
578 pr.first->second[n] =
true;
584 return has_dirichlet_constraint;
591 template<
typename OutputType>
592 void apply_lagrange_dirichlet_impl(
const SingleElemBoundaryInfo & sebi,
598 const Elem * elem = sebi.elem;
628 const unsigned int var_component =
632 const unsigned int var = variable.
number();
638 std::unique_ptr<FEMContext> context;
644 context = std::make_unique<FEMContext>
651 if (f_system && context.get())
652 context->pre_fe_reinit(*f_system, elem);
658 const std::vector<dof_id_type> & dof_indices =
662 const unsigned int n_dofs =
663 cast_int<unsigned int>(dof_indices.size());
666 std::vector<char> dof_is_fixed(n_dofs,
false);
678 unsigned int current_dof = 0;
679 for (
unsigned int n=0; n!= sebi.n_nodes; ++n)
684 const unsigned int nc =
694 auto is_boundary_node_it = sebi.is_boundary_node_map.find(&dirichlet);
695 const bool is_boundary_node =
696 (is_boundary_node_it != sebi.is_boundary_node_map.end() &&
697 is_boundary_node_it->second[n]);
700 auto is_boundary_nodeset_it = sebi.is_boundary_nodeset_map.find(&dirichlet);
701 const bool is_boundary_nodeset =
702 (is_boundary_nodeset_it != sebi.is_boundary_nodeset_map.end() &&
703 is_boundary_nodeset_it->second[n]);
706 if ( !(is_boundary_node || is_boundary_nodeset) )
713 libmesh_assert_equal_to (nc, n_vec_dim);
714 for (
unsigned int c = 0; c < n_vec_dim; c++)
717 f_component(f, f_fem, context.get(), var_component+c,
718 elem->
point(n), time);
719 dof_is_fixed[current_dof+c] =
true;
721 current_dof += n_vec_dim;
728 for (
unsigned int i = 0; i < n_dofs; i++)
732 add_fn (dof_indices[i], empty_row, Ue(i));
740 template<
typename OutputType>
741 void apply_dirichlet_impl(
const SingleElemBoundaryInfo & sebi,
747 const Elem * elem = sebi.elem;
754 typedef OutputType OutputShape;
795 const unsigned int var_component =
799 const unsigned int var = variable.
number();
821 std::unique_ptr<FEMContext> context;
827 context = std::make_unique<FEMContext>
848 if (f_system && context.get())
849 context->pre_fe_reinit(*f_system, elem);
855 const std::vector<dof_id_type> & dof_indices =
859 const unsigned int n_dofs =
860 cast_int<unsigned int>(dof_indices.size());
863 std::vector<char> dof_is_fixed(n_dofs,
false);
864 std::vector<int> free_dof(n_dofs, 0);
882 unsigned int current_dof = 0;
883 for (
unsigned int n=0; n!= sebi.n_nodes; ++n)
890 const unsigned int nc =
897 auto is_boundary_node_it = sebi.is_boundary_node_map.find(&dirichlet);
903 const bool not_boundary_node =
904 (is_boundary_node_it == sebi.is_boundary_node_map.end() ||
905 !is_boundary_node_it->second[n]);
907 if (!elem->
is_vertex(n) || not_boundary_node)
914 libmesh_assert_equal_to (nc, 0);
920 libmesh_assert_equal_to (nc, n_vec_dim);
921 for (
unsigned int c = 0; c < n_vec_dim; c++)
924 f_component(f, f_fem, context.get(), var_component+c,
925 elem->
point(n), time);
926 dof_is_fixed[current_dof+c] =
true;
928 current_dof += n_vec_dim;
934 f_component(f, f_fem, context.get(), var_component,
935 elem->
point(n), time);
936 dof_is_fixed[current_dof] =
true;
939 g_component(g, g_fem, context.get(), var_component,
940 elem->
point(n), time);
942 Ue(current_dof) = grad(0);
943 dof_is_fixed[current_dof] =
true;
949 nxplus = elem->
point(n);
953 g_component(g, g_fem, context.get(), var_component,
956 g_component(g, g_fem, context.get(), var_component,
959 Ue(current_dof) = grad(1);
960 dof_is_fixed[current_dof] =
true;
963 Ue(current_dof) = (gxplus(1) - gxminus(1))
965 dof_is_fixed[current_dof] =
true;
971 Ue(current_dof) = grad(2);
972 dof_is_fixed[current_dof] =
true;
975 Ue(current_dof) = (gxplus(2) - gxminus(2))
977 dof_is_fixed[current_dof] =
true;
981 nyplus = elem->
point(n);
985 g_component(g, g_fem, context.get(), var_component,
988 g_component(g, g_fem, context.get(), var_component,
991 Ue(current_dof) = (gyplus(2) - gyminus(2))
993 dof_is_fixed[current_dof] =
true;
997 nxmyp = elem->
point(n),
998 nxpym = elem->
point(n),
999 nxpyp = elem->
point(n);
1009 g_component(g, g_fem, context.get(), var_component,
1012 g_component(g, g_fem, context.get(), var_component,
1015 g_component(g, g_fem, context.get(), var_component,
1018 g_component(g, g_fem, context.get(), var_component,
1020 Number gxzplus = (gxpyp(2) - gxmyp(2))
1022 Number gxzminus = (gxpym(2) - gxmym(2))
1025 Ue(current_dof) = (gxzplus - gxzminus)
1027 dof_is_fixed[current_dof] =
true;
1035 else if (cont ==
C_ONE)
1037 libmesh_assert_equal_to (nc, 1 +
dim);
1039 f_component(f, f_fem, context.get(), var_component,
1040 elem->
point(n), time);
1041 dof_is_fixed[current_dof] =
true;
1044 g_component(g, g_fem, context.get(), var_component,
1045 elem->
point(n), time);
1046 for (
unsigned int i=0; i!=
dim; ++i)
1048 Ue(current_dof) = grad(i);
1049 dof_is_fixed[current_dof] =
true;
1054 libmesh_error_msg(
"Unknown continuity cont = " << cont);
1074 const std::vector<std::vector<OutputShape>> & phi = edge_fe->
get_phi();
1075 const std::vector<Point> & xyz_values = edge_fe->
get_xyz();
1076 const std::vector<Real> & JxW = edge_fe->
get_JxW();
1079 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1082 const std::vector<std::vector<OutputGradient>> & ref_dphi = edge_fe->
get_dphi();
1087 std::vector<unsigned int> edge_dofs;
1093 if (
const auto is_boundary_edge_it = sebi.is_boundary_edge_map.find(&dirichlet);
1094 is_boundary_edge_it != sebi.is_boundary_edge_map.end())
1096 for (
unsigned int e=0; e != sebi.n_edges; ++e)
1098 if (!is_boundary_edge_it->second[e])
1104 const unsigned int n_edge_dofs =
1105 cast_int<unsigned int>(edge_dofs.size());
1109 unsigned int free_dofs = 0;
1110 for (
unsigned int i=0; i != n_edge_dofs; ++i)
1111 if (!dof_is_fixed[edge_dofs[i]])
1112 free_dof[free_dofs++] = i;
1128 for (
unsigned int qp=0; qp<n_qp; qp++)
1131 OutputNumber fineval(0);
1134 for (
unsigned int c = 0; c < n_vec_dim; c++)
1136 f_component(f, f_fem, context.get(), var_component+c,
1137 xyz_values[qp], time);
1140 OutputNumberGradient finegrad;
1143 unsigned int g_rank;
1157 libmesh_error_msg(
"Unknown field type!");
1161 for (
unsigned int c = 0; c < n_vec_dim; c++)
1162 for (
unsigned int d = 0; d < g_rank; d++)
1163 g_accessor(c + d*
dim ) =
1164 g_component(g, g_fem, context.get(), var_component,
1165 xyz_values[qp], time)(c);
1168 for (
unsigned int sidei=0, freei=0; sidei != n_edge_dofs; ++sidei)
1170 unsigned int i = edge_dofs[sidei];
1172 if (dof_is_fixed[i])
1174 for (
unsigned int sidej=0, freej=0; sidej != n_edge_dofs; ++sidej)
1176 unsigned int j = edge_dofs[sidej];
1177 if (dof_is_fixed[j])
1178 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1181 Ke(freei,freej) += phi[i][qp] *
1182 phi[j][qp] * JxW[qp];
1185 if (dof_is_fixed[j])
1186 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp]) ) *
1189 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
1192 if (!dof_is_fixed[j])
1195 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1197 Fe(freei) += (finegrad.contract( (*dphi)[i][qp]) ) *
1206 for (
unsigned int i=0; i != free_dofs; ++i)
1208 Number & ui = Ue(edge_dofs[free_dof[i]]);
1212 dof_is_fixed[edge_dofs[free_dof[i]]] =
true;
1232 const std::vector<std::vector<OutputShape>> & phi = side_fe->
get_phi();
1233 const std::vector<Point> & xyz_values = side_fe->
get_xyz();
1234 const std::vector<Real> & JxW = side_fe->
get_JxW();
1237 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1240 const std::vector<std::vector<OutputGradient>> & ref_dphi = side_fe->
get_dphi();
1245 std::vector<unsigned int> side_dofs;
1251 if (
const auto is_boundary_side_it = sebi.is_boundary_side_map.find(&dirichlet);
1252 is_boundary_side_it != sebi.is_boundary_side_map.end())
1254 for (
unsigned int s=0; s != sebi.n_sides; ++s)
1256 if (!is_boundary_side_it->second[s])
1262 const unsigned int n_side_dofs =
1263 cast_int<unsigned int>(side_dofs.size());
1267 unsigned int free_dofs = 0;
1268 for (
unsigned int i=0; i != n_side_dofs; ++i)
1269 if (!dof_is_fixed[side_dofs[i]])
1270 free_dof[free_dofs++] = i;
1282 side_fe->
reinit(elem, s);
1286 for (
unsigned int qp=0; qp<n_qp; qp++)
1289 OutputNumber fineval(0);
1292 for (
unsigned int c = 0; c < n_vec_dim; c++)
1294 f_component(f, f_fem, context.get(), var_component+c,
1295 xyz_values[qp], time);
1298 OutputNumberGradient finegrad;
1301 unsigned int g_rank;
1315 libmesh_error_msg(
"Unknown field type!");
1319 for (
unsigned int c = 0; c < n_vec_dim; c++)
1320 for (
unsigned int d = 0; d < g_rank; d++)
1321 g_accessor(c + d*
dim ) =
1322 g_component(g, g_fem, context.get(), var_component,
1323 xyz_values[qp], time)(c);
1326 for (
unsigned int sidei=0, freei=0; sidei != n_side_dofs; ++sidei)
1328 unsigned int i = side_dofs[sidei];
1330 if (dof_is_fixed[i])
1332 for (
unsigned int sidej=0, freej=0; sidej != n_side_dofs; ++sidej)
1334 unsigned int j = side_dofs[sidej];
1335 if (dof_is_fixed[j])
1336 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1339 Ke(freei,freej) += phi[i][qp] *
1340 phi[j][qp] * JxW[qp];
1343 if (dof_is_fixed[j])
1344 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
1347 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
1350 if (!dof_is_fixed[j])
1353 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1355 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
1364 for (
unsigned int i=0; i != free_dofs; ++i)
1366 Number & ui = Ue(side_dofs[free_dof[i]]);
1372 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1392 const std::vector<std::vector<OutputShape>> & phi = fe->
get_phi();
1393 const std::vector<Point> & xyz_values = fe->
get_xyz();
1394 const std::vector<Real> & JxW = fe->
get_JxW();
1397 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
1400 const std::vector<std::vector<OutputGradient>> & ref_dphi = fe->
get_dphi();
1408 if (
const auto is_boundary_shellface_it = sebi.is_boundary_shellface_map.find(&dirichlet);
1409 is_boundary_shellface_it != sebi.is_boundary_shellface_map.end())
1411 for (
unsigned int shellface=0; shellface != 2; ++shellface)
1413 if (!is_boundary_shellface_it->second[shellface])
1417 std::vector<unsigned int> shellface_dofs(n_dofs);
1418 std::iota(shellface_dofs.begin(), shellface_dofs.end(), 0);
1422 unsigned int free_dofs = 0;
1423 for (
unsigned int i=0; i != n_dofs; ++i)
1424 if (!dof_is_fixed[shellface_dofs[i]])
1425 free_dof[free_dofs++] = i;
1441 for (
unsigned int qp=0; qp<n_qp; qp++)
1444 OutputNumber fineval(0);
1447 for (
unsigned int c = 0; c < n_vec_dim; c++)
1449 f_component(f, f_fem, context.get(), var_component+c,
1450 xyz_values[qp], time);
1453 OutputNumberGradient finegrad;
1456 unsigned int g_rank;
1470 libmesh_error_msg(
"Unknown field type!");
1474 for (
unsigned int c = 0; c < n_vec_dim; c++)
1475 for (
unsigned int d = 0; d < g_rank; d++)
1476 g_accessor(c + d*
dim ) =
1477 g_component(g, g_fem, context.get(), var_component,
1478 xyz_values[qp], time)(c);
1481 for (
unsigned int shellfacei=0, freei=0;
1482 shellfacei != n_dofs; ++shellfacei)
1484 unsigned int i = shellface_dofs[shellfacei];
1486 if (dof_is_fixed[i])
1488 for (
unsigned int shellfacej=0, freej=0;
1489 shellfacej != n_dofs; ++shellfacej)
1491 unsigned int j = shellface_dofs[shellfacej];
1492 if (dof_is_fixed[j])
1493 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1496 Ke(freei,freej) += phi[i][qp] *
1497 phi[j][qp] * JxW[qp];
1500 if (dof_is_fixed[j])
1501 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
1504 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
1507 if (!dof_is_fixed[j])
1510 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1512 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
1521 for (
unsigned int i=0; i != free_dofs; ++i)
1523 Number & ui = Ue(shellface_dofs[free_dof[i]]);
1525 std::abs(ui - Ushellface(i)) <
TOLERANCE);
1527 dof_is_fixed[shellface_dofs[free_dof[i]]] =
true;
1537 for (
unsigned int i = 0; i < n_dofs; i++)
1541 add_fn (dof_indices[i], empty_row, Ue(i));
1547 ConstrainDirichlet (
DofMap & dof_map_in,
1551 const AddConstraint & add_in) :
1552 dof_map(dof_map_in),
1555 dirichlets(dirichlets_in),
1559 ConstrainDirichlet (ConstrainDirichlet &&) =
default;
1560 ConstrainDirichlet (
const ConstrainDirichlet &) =
default;
1564 ConstrainDirichlet & operator= (
const ConstrainDirichlet &) =
delete;
1565 ConstrainDirichlet & operator= (ConstrainDirichlet &&) =
delete;
1579 System * system =
nullptr;
1584 std::map<boundary_id_type, std::set<std::pair<unsigned int, DirichletBoundary *>>>
1585 boundary_id_to_ordered_dirichlet_boundaries;
1590 const auto & dirichlet = dirichlets[dirichlet_id];
1593 for (
const auto & b_id : dirichlet->
b)
1594 boundary_id_to_ordered_dirichlet_boundaries[b_id].emplace(dirichlet_id, dirichlet.get());
1596 for (
const auto & var : dirichlet->
variables)
1599 auto current_system = variable.
system();
1602 system = current_system;
1604 libmesh_error_msg_if(current_system != system,
1605 "All variables should be defined on the same System");
1614 libmesh_error_msg_if(!system,
"Valid System not found for any Variables.");
1621 auto fem_context = std::make_unique<FEMContext>
1622 (*system,
nullptr,
false);
1633 SingleElemBoundaryInfo sebi(boundary_info, boundary_id_to_ordered_dirichlet_boundaries);
1636 for (
const auto & elem : range)
1644 bool has_dirichlet_constraint = sebi.reinit(elem);
1647 if (!has_dirichlet_constraint)
1650 for (
const auto & db_pair : sebi.ordered_dbs)
1653 const auto & dirichlet = db_pair.second;
1656 for (
const auto & var : dirichlet->
variables)
1662 libmesh_assert_equal_to(variable.
number(), var);
1666 if (fe_type.family ==
SCALAR)
1677 this->apply_lagrange_dirichlet_impl<Real>( sebi, variable, *dirichlet, *fem_context );
1679 this->apply_dirichlet_impl<Real>( sebi, variable, *dirichlet, *fem_context );
1684 this->apply_dirichlet_impl<RealGradient>( sebi, variable, *dirichlet, *fem_context );
1688 libmesh_error_msg(
"Unknown field type!");
1698 #endif // LIBMESH_ENABLE_DIRICHLET 1711 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1716 parallel_object_only();
1726 const DofConstraints::const_iterator lower =
1738 parallel_object_only();
1740 LOG_SCOPE(
"create_dof_constraints()",
"DofMap");
1755 this->
comm().
min(constraint_rows_empty);
1760 const bool possible_local_constraints =
false 1762 || !constraint_rows_empty
1763 #ifdef LIBMESH_ENABLE_AMR 1766 #ifdef LIBMESH_ENABLE_PERIODIC 1769 #ifdef LIBMESH_ENABLE_DIRICHLET 1775 bool possible_global_constraints = possible_local_constraints;
1776 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR) 1779 this->
comm().
max(possible_global_constraints);
1787 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1792 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1796 if (!possible_global_constraints)
1806 mesh.local_elements_end());
1817 #ifdef LIBMESH_ENABLE_PERIODIC 1820 this->
comm().
max(need_point_locator);
1822 if (need_point_locator)
1826 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1829 #ifdef LIBMESH_ENABLE_PERIODIC
1833 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 1844 #ifdef LIBMESH_ENABLE_PERIODIC
1850 #ifdef LIBMESH_ENABLE_DIRICHLET 1869 AddPrimalConstraint(*
this)));
1883 ConstrainDirichlet(*
this,
mesh, time, adb_q,
1884 AddAdjointConstraint(*
this, qoi_index)));
1888 #endif // LIBMESH_ENABLE_DIRICHLET 1892 if (!constraint_rows_empty)
1913 bool constraint_rows_empty = constraint_rows.empty();
1914 this->
comm().
min(constraint_rows_empty);
1920 #ifdef LIBMESH_ENABLE_PERIODIC 1922 "Periodic boundary conditions are not yet implemented for spline meshes");
1927 std::unique_ptr<SparsityPattern::Build> sp;
1928 std::unique_ptr<SparseMatrix<Number>> mat;
1930 const unsigned int n_adjoint_rhs =
1934 std::vector<std::unique_ptr<NumericVector<Number>>>
1935 solve_rhs(n_adjoint_rhs+1);
1940 std::set<dof_id_type> my_dirichlet_spline_dofs;
1943 std::unordered_set<dof_id_type> was_previously_constrained;
1945 const unsigned int sys_num = this->
sys_number();
1946 for (
auto & node_row : constraint_rows)
1948 const Node * node = node_row.first;
1970 for (
const auto & [pr, val] : node_row.second)
1972 const Elem * spline_elem = pr.first;
1975 const Node & spline_node =
1980 dc_row[spline_dof_id] = val;
1986 was_previously_constrained.insert(constrained_id);
1990 for (
auto & row_entry : dc_row)
1991 my_dirichlet_spline_dofs.insert(row_entry.first);
2010 if (this->
comm().size() > 1)
2014 their_dirichlet_spline_dofs;
2020 my_dirichlet_spline_dofs.end()));
2022 for (
auto d : my_dirichlet_spline_dofs)
2024 libmesh_assert_less(d, this->
end_dof(this->
comm().size()-1));
2025 while (d >= this->
end_dof(destination_pid))
2029 their_dirichlet_spline_dofs[destination_pid].push_back(d);
2032 auto receive_dof_functor =
2033 [& my_dirichlet_spline_dofs]
2035 const std::vector<dof_id_type> & dofs)
2037 my_dirichlet_spline_dofs.insert(dofs.begin(), dofs.end());
2040 Parallel::push_parallel_vector_data
2041 (this->
comm(), their_dirichlet_spline_dofs, receive_dof_functor);
2051 bool important_prior_constraints =
2052 !was_previously_constrained.empty();
2053 this->
comm().
max(important_prior_constraints);
2055 if (important_prior_constraints)
2071 mat->attach_dof_map(*
this);
2073 mat->attach_sparsity_pattern(*sp);
2076 for (
auto & node_row : constraint_rows)
2078 const Node * node = node_row.first;
2093 if (was_previously_constrained.count(constrained_id))
2099 std::vector<dof_id_type>
dof_indices(1, constrained_id);
2107 DofConstraintValueMap::const_iterator rhsit =
2108 vals.find(constrained_id);
2109 F(0) = (rhsit == vals.end()) ? 0 : rhsit->second;
2112 if (rhsit != vals.end())
2130 if (!was_previously_constrained.count(d) &&
2131 !my_dirichlet_spline_dofs.count(d))
2136 std::unique_ptr<LinearSolver<Number>> linear_solver =
2139 std::unique_ptr<NumericVector<Number>> projected_vals =
2146 for (
auto sd : my_dirichlet_spline_dofs)
2155 const unsigned int max_its = 5000;
2157 linear_solver->solve(*mat, *projected_vals,
2158 *(solve_rhs[q]), tol, max_its);
2164 for (
auto sd : my_dirichlet_spline_dofs)
2167 Number constraint_rhs = (*projected_vals)(sd);
2169 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2170 vals.emplace(sd, constraint_rhs);
2172 rhs_it.first->second = constraint_rhs;
2182 const Number constraint_rhs,
2183 const bool forbid_constraint_overwrite)
2186 libmesh_error_msg_if(forbid_constraint_overwrite && this->
is_constrained_dof(dof_number),
2187 "ERROR: DOF " << dof_number <<
" was already constrained!");
2189 libmesh_assert_less(dof_number, this->
n_dofs());
2193 libmesh_assert_msg(!constraint_row.count(dof_number),
2194 "Error: constraint_row for dof " << dof_number <<
2195 " should not contain an entry for dof " << dof_number);
2198 for (
const auto & pr : constraint_row)
2199 libmesh_assert_less(pr.first, this->n_dofs());
2205 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
2208 rhs_it.first->second = constraint_rhs;
2215 const Number constraint_rhs,
2216 const bool forbid_constraint_overwrite)
2219 if (forbid_constraint_overwrite)
2222 "ERROR: DOF " << dof_number <<
" has no corresponding primal constraint!");
2254 bool print_nonlocal)
const 2256 parallel_object_only();
2258 std::string local_constraints =
2263 this->
comm().
send(0, local_constraints);
2267 os <<
"Processor 0:\n";
2268 os << local_constraints;
2273 os <<
"Processor " << p <<
":\n";
2274 os << local_constraints;
2281 std::ostringstream os;
2282 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2288 os <<
"Node Constraints:" 2294 if (!print_nonlocal &&
2299 const Point & offset = pr.second;
2301 os <<
"Constraints for Node id " << node->id()
2304 for (
const auto & [cnode, val] : row)
2305 os <<
" (" << cnode->id() <<
"," << val <<
")\t";
2307 os <<
"rhs: " << offset;
2311 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 2318 os <<
"DoF Constraints:" 2327 DofConstraintValueMap::const_iterator rhsit =
2332 os <<
"Constraints for DoF " << i
2335 for (
const auto & item : row)
2336 os <<
" (" << item.first <<
"," << item.second <<
")\t";
2338 os <<
"rhs: " << rhs;
2342 for (
unsigned int qoi_index = 0,
2344 qoi_index != n_qois; ++qoi_index)
2346 os <<
"Adjoint " << qoi_index <<
" DoF rhs values:" 2351 for (
const auto & [i, rhs] : adjoint_map_it->second)
2357 os <<
"RHS for DoF " << i
2370 std::vector<dof_id_type> & elem_dofs,
2371 bool asymmetric_constraint_rows)
const 2373 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
2374 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
2386 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
2389 if ((C.
m() == matrix.
m()) &&
2390 (C.
n() == elem_dofs.size()))
2397 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
2398 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
2399 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
2402 for (
unsigned int i=0,
2403 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2404 i != n_elem_dofs; i++)
2413 if (asymmetric_constraint_rows)
2415 DofConstraints::const_iterator
2428 for (
const auto & item : constraint_row)
2429 for (
unsigned int j=0; j != n_elem_dofs; j++)
2430 if (elem_dofs[j] == item.first)
2431 matrix(i,j) = -item.second;
2441 std::vector<dof_id_type> & elem_dofs,
2442 bool asymmetric_constraint_rows)
const 2444 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
2445 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
2446 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2458 LOG_SCOPE(
"cnstrn_elem_mat_vec()",
"DofMap");
2461 if ((C.
m() == matrix.
m()) &&
2462 (C.
n() == elem_dofs.size()))
2469 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
2470 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
2471 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
2474 for (
unsigned int i=0,
2475 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2476 i != n_elem_dofs; i++)
2488 if (asymmetric_constraint_rows)
2490 DofConstraints::const_iterator
2500 for (
const auto & item : constraint_row)
2501 for (
unsigned int j=0; j != n_elem_dofs; j++)
2502 if (elem_dofs[j] == item.first)
2503 matrix(i,j) = -item.second;
2520 std::vector<dof_id_type> & elem_dofs,
2521 bool asymmetric_constraint_rows,
2522 int qoi_index)
const 2524 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
2525 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
2526 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2539 LOG_SCOPE(
"hetero_cnstrn_elem_mat_vec()",
"DofMap");
2542 if ((C.
m() == matrix.
m()) &&
2543 (C.
n() == elem_dofs.size()))
2551 rhs_values = &it->second;
2566 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
2567 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
2568 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
2570 for (
unsigned int i=0,
2571 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2572 i != n_elem_dofs; i++)
2587 if (asymmetric_constraint_rows)
2589 DofConstraints::const_iterator
2596 for (
const auto & item : constraint_row)
2597 for (
unsigned int j=0; j != n_elem_dofs; j++)
2598 if (elem_dofs[j] == item.first)
2599 matrix(i,j) = -item.second;
2603 const DofConstraintValueMap::const_iterator valpos =
2604 rhs_values->find(dof_id);
2606 rhs(i) = (valpos == rhs_values->end()) ?
2622 std::vector<dof_id_type> & elem_dofs,
2625 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
2626 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
2627 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2633 if (this->_dof_constraints.empty())
2642 this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2644 LOG_SCOPE(
"hetero_cnstrn_elem_jac_res()",
"DofMap");
2647 if ((C.
m() != matrix.
m()) ||
2648 (C.
n() != elem_dofs.size()))
2659 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
2660 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
2661 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
2663 for (
unsigned int i=0,
2664 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2665 i != n_elem_dofs; i++)
2669 if (
auto pos = _dof_constraints.find(dof_id);
2670 pos != _dof_constraints.end())
2683 for (
const auto & item : constraint_row)
2684 for (
unsigned int j=0; j != n_elem_dofs; j++)
2685 if (elem_dofs[j] == item.first)
2686 matrix(i,j) = -item.second;
2688 const DofConstraintValueMap::const_iterator valpos =
2689 _primal_constraint_values.find(dof_id);
2691 Number & rhs_val = rhs(i);
2692 rhs_val = (valpos == _primal_constraint_values.end()) ?
2693 0 : -valpos->second;
2694 for (
const auto & [constraining_dof, coef] : constraint_row)
2695 rhs_val -= coef * solution_local(constraining_dof);
2696 rhs_val += solution_local(dof_id);
2704 std::vector<dof_id_type> & elem_dofs,
2707 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2713 if (this->_dof_constraints.empty())
2721 this->build_constraint_matrix_and_vector (C, H, elem_dofs);
2723 LOG_SCOPE(
"hetero_cnstrn_elem_res()",
"DofMap");
2726 if ((C.
m() != rhs.
size()) ||
2727 (C.
n() != elem_dofs.size()))
2734 for (
unsigned int i=0,
2735 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2736 i != n_elem_dofs; i++)
2740 if (
auto pos = _dof_constraints.find(dof_id);
2741 pos != _dof_constraints.end())
2748 const DofConstraintValueMap::const_iterator valpos =
2749 _primal_constraint_values.find(dof_id);
2751 Number & rhs_val = rhs(i);
2752 rhs_val = (valpos == _primal_constraint_values.end()) ?
2753 0 : -valpos->second;
2754 for (
const auto & [constraining_dof, coef] : constraint_row)
2755 rhs_val -= coef * solution_local(constraining_dof);
2756 rhs_val += solution_local(dof_id);
2764 std::vector<dof_id_type> & elem_dofs,
2767 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2773 if (this->_dof_constraints.empty())
2779 this->build_constraint_matrix (C, elem_dofs);
2781 LOG_SCOPE(
"cnstrn_elem_residual()",
"DofMap");
2784 if (C.
n() != elem_dofs.size())
2791 for (
unsigned int i=0,
2792 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2793 i != n_elem_dofs; i++)
2797 if (
auto pos = _dof_constraints.find(dof_id);
2798 pos != _dof_constraints.end())
2805 Number & rhs_val = rhs(i);
2807 for (
const auto & [constraining_dof, coef] : constraint_row)
2808 rhs_val -= coef * solution_local(constraining_dof);
2809 rhs_val += solution_local(dof_id);
2817 std::vector<dof_id_type> & elem_dofs,
2818 bool asymmetric_constraint_rows,
2819 int qoi_index)
const 2821 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
2822 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
2823 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
2836 LOG_SCOPE(
"hetero_cnstrn_elem_vec()",
"DofMap");
2839 if ((C.
m() == matrix.
m()) &&
2840 (C.
n() == elem_dofs.size()))
2848 rhs_values = &it->second;
2859 for (
unsigned int i=0,
2860 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2861 i != n_elem_dofs; i++)
2870 if (asymmetric_constraint_rows && rhs_values)
2872 const DofConstraintValueMap::const_iterator valpos =
2873 rhs_values->find(dof_id);
2875 rhs(i) = (valpos == rhs_values->end()) ?
2890 std::vector<dof_id_type> & row_dofs,
2891 std::vector<dof_id_type> & col_dofs,
2892 bool asymmetric_constraint_rows)
const 2894 libmesh_assert_equal_to (row_dofs.size(), matrix.
m());
2895 libmesh_assert_equal_to (col_dofs.size(), matrix.
n());
2908 std::vector<dof_id_type> orig_row_dofs(row_dofs);
2909 std::vector<dof_id_type> orig_col_dofs(col_dofs);
2914 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
2916 row_dofs = orig_row_dofs;
2917 col_dofs = orig_col_dofs;
2919 bool constraint_found =
false;
2923 if ((R.
m() == matrix.
m()) &&
2924 (R.
n() == row_dofs.size()))
2927 constraint_found =
true;
2930 if ((C.
m() == matrix.
n()) &&
2931 (C.
n() == col_dofs.size()))
2934 constraint_found =
true;
2938 if (constraint_found)
2940 libmesh_assert_equal_to (matrix.
m(), row_dofs.size());
2941 libmesh_assert_equal_to (matrix.
n(), col_dofs.size());
2944 for (
unsigned int i=0,
2945 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2946 i != n_row_dofs; i++)
2951 if (row_dofs[i] != col_dofs[j])
2957 if (asymmetric_constraint_rows)
2959 DofConstraints::const_iterator
2968 for (
const auto & item : constraint_row)
2969 for (
unsigned int j=0,
2970 n_col_dofs = cast_int<unsigned int>(col_dofs.size());
2971 j != n_col_dofs; j++)
2972 if (col_dofs[j] == item.first)
2973 matrix(i,j) = -item.second;
2982 std::vector<dof_id_type> & row_dofs,
2985 libmesh_assert_equal_to (rhs.
size(), row_dofs.size());
2996 LOG_SCOPE(
"constrain_elem_vector()",
"DofMap");
2999 if ((R.
m() == rhs.
size()) &&
3000 (R.
n() == row_dofs.size()))
3006 libmesh_assert_equal_to (row_dofs.size(), rhs.
size());
3008 for (
unsigned int i=0,
3009 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
3010 i != n_row_dofs; i++)
3025 std::vector<dof_id_type> & row_dofs,
3028 libmesh_assert_equal_to (v.
size(), row_dofs.size());
3029 libmesh_assert_equal_to (w.
size(), row_dofs.size());
3040 LOG_SCOPE(
"cnstrn_elem_dyad_mat()",
"DofMap");
3043 if ((R.
m() == v.
size()) &&
3044 (R.
n() == row_dofs.size()))
3054 libmesh_assert_equal_to (row_dofs.size(), v.
size());
3055 libmesh_assert_equal_to (row_dofs.size(), w.
size());
3059 for (
unsigned int i=0,
3060 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
3061 i != n_row_dofs; i++)
3090 bool homogeneous)
const 3092 parallel_object_only();
3097 LOG_SCOPE(
"enforce_constraints_exactly()",
"DofMap");
3107 std::unique_ptr<NumericVector<Number>> v_built;
3115 i<v_built->last_local_index(); i++)
3116 v_built->set(i, (*v)(i));
3118 v_global = v_built.
get();
3131 v_local = v_built.
get();
3148 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
3162 for (
const auto & [dof, val] : constraint_row)
3183 bool homogeneous)
const 3185 parallel_object_only();
3196 std::unique_ptr<NumericVector<Number>> solution_built;
3198 solution_local = solution;
3205 solution_built->close();
3206 solution_local = solution_built.
get();
3214 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
3222 for (
const auto & [dof, val] : constraint_row)
3224 exact_value += (*solution_local)(constrained_dof);
3239 parallel_object_only();
3247 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
3254 for (
const auto & j : constraint_row)
3255 jac->
set(constrained_dof, j.first, -j.second);
3256 jac->
set(constrained_dof, constrained_dof, 1);
3262 unsigned int q)
const 3264 parallel_object_only();
3269 LOG_SCOPE(
"enforce_adjoint_constraints_exactly()",
"DofMap");
3273 std::unique_ptr<NumericVector<Number>> v_built;
3281 i<v_built->last_local_index(); i++)
3282 v_built->set(i, v(i));
3284 v_global = v_built.
get();
3296 v_local = v_built.
get();
3306 libmesh_error_msg(
"ERROR: Unknown v.type() == " << v.
type());
3315 const AdjointDofConstraintValues::const_iterator
3319 nullptr : &adjoint_constraint_map_it->second;
3329 if (
const auto adjoint_constraint_it = constraint_map->find(constrained_dof);
3330 adjoint_constraint_it != constraint_map->end())
3334 for (
const auto & j : constraint_row)
3354 std::pair<Real, Real>
3365 Real max_absolute_error = 0., max_relative_error = 0.;
3369 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
3372 std::vector<dof_id_type> local_dof_indices;
3374 for (
const auto & elem :
mesh.active_local_element_ptr_range())
3377 std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
3388 libmesh_assert_equal_to (C.
m(), raw_dof_indices.size());
3389 libmesh_assert_equal_to (C.
n(), local_dof_indices.size());
3400 DofConstraints::const_iterator
3407 DofConstraintValueMap::const_iterator rhsit =
3414 if (local_dof_indices[j] != global_dof)
3416 vec(local_dof_indices[j]);
3419 max_absolute_error = std::max(max_absolute_error,
3421 max_relative_error = std::max(max_relative_error,
3428 return std::pair<Real, Real>(max_absolute_error, max_relative_error);
3434 std::vector<dof_id_type> & elem_dofs,
3435 const bool called_recursively)
const 3437 LOG_SCOPE_IF(
"build_constraint_matrix()",
"DofMap", !called_recursively);
3440 typedef std::set<dof_id_type> RCSet;
3443 bool we_have_constraints =
false;
3450 for (
const auto & dof : elem_dofs)
3453 we_have_constraints =
true;
3456 DofConstraints::const_iterator
3466 for (
const auto & item : constraint_row)
3467 dof_set.insert (item.first);
3472 if (!we_have_constraints)
3475 for (
const auto & dof : elem_dofs)
3476 dof_set.erase (dof);
3484 if (!dof_set.empty() ||
3485 !called_recursively)
3487 const unsigned int old_size =
3488 cast_int<unsigned int>(elem_dofs.size());
3491 elem_dofs.insert(elem_dofs.end(),
3492 dof_set.begin(), dof_set.end());
3497 cast_int<unsigned int>(elem_dofs.size()));
3500 for (
unsigned int i=0; i != old_size; i++)
3504 DofConstraints::const_iterator
3514 for (
const auto & item : constraint_row)
3515 for (
unsigned int j=0,
3516 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3517 j != n_elem_dofs; j++)
3518 if (elem_dofs[j] == item.first)
3519 C(i,j) = item.second;
3533 if ((C.
n() == Cnew.
m()) &&
3534 (Cnew.
n() == elem_dofs.size()))
3537 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
3545 std::vector<dof_id_type> & elem_dofs,
3547 const bool called_recursively)
const 3549 LOG_SCOPE_IF(
"build_constraint_matrix_and_vector()",
"DofMap", !called_recursively);
3552 typedef std::set<dof_id_type> RCSet;
3555 bool we_have_constraints =
false;
3562 for (
const auto & dof : elem_dofs)
3565 we_have_constraints =
true;
3568 DofConstraints::const_iterator
3578 for (
const auto & item : constraint_row)
3579 dof_set.insert (item.first);
3584 if (!we_have_constraints)
3587 for (
const auto & dof : elem_dofs)
3588 dof_set.erase (dof);
3596 if (!dof_set.empty() ||
3597 !called_recursively)
3604 rhs_values = &it->second;
3606 const unsigned int old_size =
3607 cast_int<unsigned int>(elem_dofs.size());
3610 elem_dofs.insert(elem_dofs.end(),
3611 dof_set.begin(), dof_set.end());
3616 cast_int<unsigned int>(elem_dofs.size()));
3620 for (
unsigned int i=0; i != old_size; i++)
3624 DofConstraints::const_iterator
3634 for (
const auto & item : constraint_row)
3635 for (
unsigned int j=0,
3636 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
3637 j != n_elem_dofs; j++)
3638 if (elem_dofs[j] == item.first)
3639 C(i,j) = item.second;
3643 if (
const auto rhsit = rhs_values->find(elem_dofs[i]);
3644 rhsit != rhs_values->end())
3645 H(i) = rhsit->second;
3662 if ((C.
n() == Cnew.
m()) &&
3663 (Cnew.
n() == elem_dofs.size()))
3672 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
3680 parallel_object_only();
3689 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3691 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 3693 this->
comm().
max(has_constraints);
3694 if (!has_constraints)
3699 const unsigned int max_qoi_num =
3703 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3705 std::vector<Parallel::Request> packed_range_sends;
3719 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
3721 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3722 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
3725 const unsigned int sys_num = this->
sys_number();
3728 for (
auto & elem :
as_range(
mesh.active_not_local_elements_begin(),
3729 mesh.active_not_local_elements_end()))
3745 for (
unsigned int v=0; v !=
n_vars; ++v)
3747 const unsigned int n_comp = elem->
n_comp(sys_num,v);
3748 for (
unsigned int c=0; c != n_comp; ++c)
3750 const unsigned int id =
3758 for (
unsigned short n = 0; n !=
n_nodes; ++n)
3762 for (
unsigned int v=0; v !=
n_vars; ++v)
3764 const unsigned int n_comp = node.
n_comp(sys_num,v);
3765 for (
unsigned int c=0; c != n_comp; ++c)
3767 const unsigned int id =
3775 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3776 for (
unsigned short n = 0; n !=
n_nodes; ++n)
3784 std::map<processor_id_type, std::vector<dof_id_type>>
3785 pushed_id_vecs, received_id_vecs;
3786 for (
auto & p : pushed_ids)
3787 pushed_id_vecs[p.first].assign(p.second.begin(), p.second.end());
3789 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3790 pushed_keys_vals, received_keys_vals;
3791 std::map<processor_id_type, std::vector<std::vector<Number>>> pushed_rhss, received_rhss;
3792 for (
auto & p : pushed_id_vecs)
3794 auto & keys_vals = pushed_keys_vals[p.first];
3795 keys_vals.reserve(p.second.size());
3797 auto & rhss = pushed_rhss[p.first];
3798 rhss.reserve(p.second.size());
3799 for (
auto & pushed_id : p.second)
3802 keys_vals.emplace_back(row.begin(), row.end());
3804 rhss.push_back(std::vector<Number>(max_qoi_num+1));
3805 std::vector<Number> & rhs = rhss.back();
3806 DofConstraintValueMap::const_iterator rhsit =
3811 for (
unsigned int q = 0; q != max_qoi_num; ++q)
3813 AdjointDofConstraintValues::const_iterator adjoint_map_it =
3820 adjoint_map_it->second;
3822 DofConstraintValueMap::const_iterator adj_rhsit =
3823 constraint_map.find(pushed_id);
3826 (adj_rhsit == constraint_map.end()) ?
3827 0 : adj_rhsit->second;
3832 auto ids_action_functor =
3833 [& received_id_vecs]
3835 const std::vector<dof_id_type> & data)
3837 received_id_vecs[pid] = data;
3840 Parallel::push_parallel_vector_data
3841 (this->
comm(), pushed_id_vecs, ids_action_functor);
3843 auto keys_vals_action_functor =
3844 [& received_keys_vals]
3846 const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
3848 received_keys_vals[pid] = data;
3851 Parallel::push_parallel_vector_data
3852 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
3854 auto rhss_action_functor =
3857 const std::vector<std::vector<Number>> & data)
3859 received_rhss[pid] = data;
3862 Parallel::push_parallel_vector_data
3863 (this->
comm(), pushed_rhss, rhss_action_functor);
3868 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3869 std::map<processor_id_type, std::vector<dof_id_type>>
3870 pushed_node_id_vecs, received_node_id_vecs;
3871 for (
auto & p : pushed_node_ids)
3872 pushed_node_id_vecs[p.first].assign(p.second.begin(), p.second.end());
3874 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3875 pushed_node_keys_vals, received_node_keys_vals;
3876 std::map<processor_id_type, std::vector<Point>> pushed_offsets, received_offsets;
3878 for (
auto & p : pushed_node_id_vecs)
3884 std::set<const Node *> nodes_requested;
3886 auto & node_keys_vals = pushed_node_keys_vals[pid];
3887 node_keys_vals.reserve(p.second.size());
3889 auto & offsets = pushed_offsets[pid];
3890 offsets.reserve(p.second.size());
3892 for (
auto & pushed_node_id : p.second)
3896 const std::size_t row_size = row.size();
3897 node_keys_vals.push_back
3898 (std::vector<std::pair<dof_id_type,Real>>());
3899 std::vector<std::pair<dof_id_type,Real>> & this_node_kv =
3900 node_keys_vals.back();
3901 this_node_kv.reserve(row_size);
3902 for (
const auto & j : row)
3904 this_node_kv.emplace_back(j.first->id(), j.second);
3909 if (j.first->processor_id() != pid && dist_mesh)
3910 nodes_requested.insert(j.first);
3924 (pid, &
mesh, nodes_requested.begin(), nodes_requested.end(),
3925 packed_range_sends.back(), range_tag);
3929 auto node_ids_action_functor =
3930 [& received_node_id_vecs]
3932 const std::vector<dof_id_type> & data)
3934 received_node_id_vecs[pid] = data;
3937 Parallel::push_parallel_vector_data
3938 (this->
comm(), pushed_node_id_vecs, node_ids_action_functor);
3940 auto node_keys_vals_action_functor =
3941 [& received_node_keys_vals]
3943 const std::vector<std::vector<std::pair<dof_id_type,Real>>> & data)
3945 received_node_keys_vals[pid] = data;
3948 Parallel::push_parallel_vector_data
3949 (this->
comm(), pushed_node_keys_vals,
3950 node_keys_vals_action_functor);
3952 auto node_offsets_action_functor =
3953 [& received_offsets]
3955 const std::vector<Point> & data)
3957 received_offsets[pid] = data;
3960 Parallel::push_parallel_vector_data
3961 (this->
comm(), pushed_offsets, node_offsets_action_functor);
3966 for (
auto & [pid, pushed_ids_to_me] : received_id_vecs)
3970 const auto & pushed_keys_vals_to_me = received_keys_vals.at(pid);
3971 const auto & pushed_rhss_to_me = received_rhss.at(pid);
3973 libmesh_assert_equal_to (pushed_ids_to_me.size(),
3974 pushed_keys_vals_to_me.size());
3975 libmesh_assert_equal_to (pushed_ids_to_me.size(),
3976 pushed_rhss_to_me.size());
3987 for (
auto & kv : pushed_keys_vals_to_me[i])
3989 libmesh_assert_less(kv.first, this->n_dofs());
3990 row[kv.first] = kv.second;
3993 const Number primal_rhs = pushed_rhss_to_me[i][max_qoi_num];
3998 if (primal_rhs !=
Number(0))
4003 for (
unsigned int q = 0; q != max_qoi_num; ++q)
4005 AdjointDofConstraintValues::iterator adjoint_map_it =
4008 const Number adj_rhs = pushed_rhss_to_me[i][q];
4019 adjoint_map_it->second;
4021 if (adj_rhs !=
Number(0))
4022 constraint_map[constrained] = adj_rhs;
4024 constraint_map.erase(constrained);
4030 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 4032 for (
auto & [pid, pushed_node_ids_to_me] : received_node_id_vecs)
4039 (
Node**)
nullptr, range_tag);
4043 const auto & pushed_node_keys_vals_to_me = received_node_keys_vals.at(pid);
4044 const auto & pushed_offsets_to_me = received_offsets.at(pid);
4046 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
4047 pushed_node_keys_vals_to_me.size());
4048 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
4049 pushed_offsets_to_me.size());
4053 dof_id_type constrained_id = pushed_node_ids_to_me[i];
4061 for (
auto & kv : pushed_node_keys_vals_to_me[i])
4065 row[key_node] = kv.second;
4071 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 4078 typedef std::set<dof_id_type> DoF_RCSet;
4079 DoF_RCSet unexpanded_dofs;
4082 unexpanded_dofs.insert(i.first);
4088 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 4089 typedef std::set<const Node *> Node_RCSet;
4090 Node_RCSet unexpanded_nodes;
4093 unexpanded_nodes.insert(i.first);
4097 bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
4098 this->
comm().
max(unexpanded_set_nonempty);
4100 while (unexpanded_set_nonempty)
4103 parallel_object_only();
4106 Node_RCSet node_request_set;
4109 std::map<processor_id_type, std::vector<dof_id_type>>
4113 std::map<processor_id_type, dof_id_type> node_ids_on_proc;
4116 for (
const auto & i : unexpanded_nodes)
4119 for (
const auto & j : row)
4121 const Node *
const node = j.first;
4127 !_node_constraints.count(node))
4128 node_request_set.insert(node);
4134 unexpanded_nodes.clear();
4137 for (
const auto & node : node_request_set)
4140 libmesh_assert_less (node->processor_id(), this->
n_processors());
4141 node_ids_on_proc[node->processor_id()]++;
4144 for (
auto pair : node_ids_on_proc)
4145 requested_node_ids[pair.first].reserve(pair.second);
4148 for (
const auto & node : node_request_set)
4149 requested_node_ids[node->processor_id()].push_back(node->id());
4151 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
4153 auto node_row_gather_functor =
4157 & packed_range_sends,
4160 const std::vector<dof_id_type> & ids,
4161 std::vector<row_datum> & data)
4165 std::set<const Node *> nodes_requested;
4168 const std::size_t query_size = ids.size();
4170 data.resize(query_size);
4171 for (std::size_t i=0; i != query_size; ++i)
4178 std::size_t row_size = row.size();
4179 data[i].reserve(row_size);
4180 for (
const auto & j : row)
4182 const Node * node = j.first;
4183 data[i].emplace_back(node->
id(), j.second);
4189 nodes_requested.insert(node);
4215 (pid, &
mesh, nodes_requested.begin(), nodes_requested.end(),
4216 packed_range_sends.back(), range_tag);
4220 typedef Point node_rhs_datum;
4222 auto node_rhs_gather_functor =
4226 const std::vector<dof_id_type> & ids,
4227 std::vector<node_rhs_datum> & data)
4230 const std::size_t query_size = ids.size();
4232 data.resize(query_size);
4233 for (std::size_t i=0; i != query_size; ++i)
4240 data[i](0) = std::numeric_limits<Real>::quiet_NaN();
4244 auto node_row_action_functor =
4251 const std::vector<dof_id_type> & ids,
4252 const std::vector<row_datum> & data)
4259 (
Node**)
nullptr, range_tag);
4262 const std::size_t query_size = ids.size();
4264 for (std::size_t i=0; i != query_size; ++i)
4270 if (data[i].empty())
4281 for (
auto & pair : data[i])
4283 const Node * key_node =
4286 row[key_node] = pair.second;
4290 unexpanded_nodes.insert(constrained_node);
4295 auto node_rhs_action_functor =
4299 const std::vector<dof_id_type> & ids,
4300 const std::vector<node_rhs_datum> & data)
4303 const std::size_t query_size = ids.size();
4305 for (std::size_t i=0; i != query_size; ++i)
4318 row_datum * node_row_ex =
nullptr;
4319 Parallel::pull_parallel_vector_data
4320 (this->
comm(), requested_node_ids, node_row_gather_functor,
4321 node_row_action_functor, node_row_ex);
4324 node_rhs_datum * node_rhs_ex =
nullptr;
4325 Parallel::pull_parallel_vector_data
4326 (this->
comm(), requested_node_ids, node_rhs_gather_functor,
4327 node_rhs_action_functor, node_rhs_ex);
4332 unexpanded_set_nonempty = !unexpanded_nodes.empty();
4333 this->
comm().
max(unexpanded_set_nonempty);
4335 Parallel::wait(packed_range_sends);
4336 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 4360 const unsigned int max_qoi_num =
4365 typedef std::set<dof_id_type> RCSet;
4366 RCSet unexpanded_set;
4369 unexpanded_set.insert(i.first);
4371 while (!unexpanded_set.empty())
4372 for (RCSet::iterator i = unexpanded_set.begin();
4373 i != unexpanded_set.end(); )
4376 DofConstraints::iterator
4383 DofConstraintValueMap::iterator rhsit =
4389 std::vector<DofConstraintValueMap::iterator> adjoint_rhs_iterators;
4390 adjoint_rhs_iterators.resize(max_qoi_num);
4393 std::vector<Number> adjoint_constraint_rhs(max_qoi_num, 0.0);
4398 const std::size_t q = adjoint_map.first;
4399 adjoint_rhs_iterators[q] = adjoint_map.second.find(*i);
4401 adjoint_constraint_rhs[q] =
4402 (adjoint_rhs_iterators[q] == adjoint_map.second.end()) ?
4403 0 : adjoint_rhs_iterators[q]->second;
4406 std::vector<dof_id_type> constraints_to_expand;
4408 for (
const auto & item : constraint_row)
4409 if (item.first != *i && this->is_constrained_dof(item.first))
4411 unexpanded_set.insert(item.first);
4412 constraints_to_expand.push_back(item.first);
4415 for (
const auto & expandable : constraints_to_expand)
4417 const Real this_coef = constraint_row[expandable];
4419 DofConstraints::const_iterator
4426 for (
const auto & item : subconstraint_row)
4430 constraint_row[item.first] += item.second * this_coef;
4435 constraint_rhs += subrhsit->second * this_coef;
4440 if (
auto adjoint_subrhsit = adjoint_map.second.find(expandable);
4441 adjoint_subrhsit != adjoint_map.second.end())
4442 adjoint_constraint_rhs[adjoint_map.first] += adjoint_subrhsit->second * this_coef;
4445 constraint_row.erase(expandable);
4450 if (constraint_rhs !=
Number(0))
4457 if (constraint_rhs !=
Number(0))
4458 rhsit->second = constraint_rhs;
4466 const std::size_t q = adjoint_map.first;
4468 if(adjoint_rhs_iterators[q] == adjoint_map.second.end())
4470 if (adjoint_constraint_rhs[q] !=
Number(0))
4471 (adjoint_map.second)[*i] = adjoint_constraint_rhs[q];
4473 adjoint_map.second.erase(*i);
4477 if (adjoint_constraint_rhs[q] !=
Number(0))
4478 adjoint_rhs_iterators[q]->second = adjoint_constraint_rhs[q];
4480 adjoint_map.second.erase(adjoint_rhs_iterators[q]);
4484 if (constraints_to_expand.empty())
4485 i = unexpanded_set.erase(i);
4502 #ifdef LIBMESH_ENABLE_CONSTRAINTS 4512 typedef std::set<dof_id_type> RCSet;
4513 RCSet unexpanded_set;
4519 for (
const auto & i : dof_constraints_copy)
4520 unexpanded_set.insert(i.first);
4522 while (!unexpanded_set.empty())
4523 for (RCSet::iterator i = unexpanded_set.begin();
4524 i != unexpanded_set.end(); )
4527 DofConstraints::iterator
4528 pos = dof_constraints_copy.find(*i);
4540 std::vector<dof_id_type> constraints_to_expand;
4542 for (
const auto & item : constraint_row)
4543 if (item.first != *i && this->is_constrained_dof(item.first))
4545 unexpanded_set.insert(item.first);
4546 constraints_to_expand.push_back(item.first);
4549 for (
const auto & expandable : constraints_to_expand)
4551 const Real this_coef = constraint_row[expandable];
4553 DofConstraints::const_iterator
4554 subpos = dof_constraints_copy.find(expandable);
4560 for (
const auto & item : subconstraint_row)
4562 libmesh_error_msg_if(item.first == expandable,
"Constraint loop detected");
4564 constraint_row[item.first] += item.second * this_coef;
4573 constraint_row.erase(expandable);
4592 if (constraints_to_expand.empty())
4593 i = unexpanded_set.erase(i);
4614 parallel_object_only();
4623 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 4625 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 4627 this->
comm().
max(has_constraints);
4628 if (!has_constraints)
4635 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 4636 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
4637 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 4639 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
4645 while (constrained >=
_end_df[constrained_proc_id])
4646 constrained_proc_id++;
4651 for (
auto & j : row)
4656 while (constraining >=
_end_df[constraining_proc_id])
4657 constraining_proc_id++;
4660 constraining_proc_id != constrained_proc_id)
4661 pushed_ids[constraining_proc_id].insert(constrained);
4668 std::vector<std::vector<std::pair<dof_id_type, Real>>>>
4669 pushed_keys_vals, pushed_keys_vals_to_me;
4671 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Number>>>
4672 pushed_ids_rhss, pushed_ids_rhss_to_me;
4681 for (
const auto & [pid, pid_ids] : pushed_ids)
4683 const std::size_t ids_size = pid_ids.size();
4684 std::vector<std::vector<std::pair<dof_id_type, Real>>> &
4685 keys_vals = pushed_keys_vals[pid];
4686 std::vector<std::pair<dof_id_type,Number>> &
4687 ids_rhss = pushed_ids_rhss[pid];
4688 keys_vals.resize(ids_size);
4689 ids_rhss.resize(ids_size);
4692 std::set<dof_id_type>::const_iterator it;
4693 for (push_i = 0, it = pid_ids.begin();
4694 it != pid_ids.end(); ++push_i, ++it)
4698 keys_vals[push_i].assign(row.begin(), row.end());
4700 DofConstraintValueMap::const_iterator rhsit =
4702 ids_rhss[push_i].first = constrained;
4703 ids_rhss[push_i].second =
4712 auto ids_rhss_action_functor =
4713 [& pushed_ids_rhss_to_me]
4715 const std::vector<std::pair<dof_id_type, Number>> & data)
4717 pushed_ids_rhss_to_me[pid] = data;
4720 auto keys_vals_action_functor =
4721 [& pushed_keys_vals_to_me]
4723 const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
4725 pushed_keys_vals_to_me[pid] = data;
4728 Parallel::push_parallel_vector_data
4729 (this->
comm(), pushed_ids_rhss, ids_rhss_action_functor);
4730 Parallel::push_parallel_vector_data
4731 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
4734 auto receive_dof_constraints =
4736 & pushed_ids_rhss_to_me,
4737 & pushed_keys_vals_to_me]
4740 for (
const auto & [pid, ids_rhss] : pushed_ids_rhss_to_me)
4742 const auto & keys_vals = pushed_keys_vals_to_me[pid];
4744 libmesh_assert_equal_to
4745 (ids_rhss.size(), keys_vals.size());
4757 for (
auto & key_val : keys_vals[i])
4759 libmesh_assert_less(key_val.first, this->n_dofs());
4760 row[key_val.first] = key_val.second;
4762 if (ids_rhss[i].second !=
Number(0))
4772 receive_dof_constraints();
4774 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 4778 const Node * constrained = i.first;
4784 for (
auto & j : row)
4786 const Node * constraining = j.first;
4790 pushed_node_ids[constraining->
processor_id()].insert(constrained->
id());
4796 std::vector<std::vector<std::pair<dof_id_type,Real>>>>
4797 pushed_node_keys_vals, pushed_node_keys_vals_to_me;
4798 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Point>>>
4799 pushed_node_ids_offsets, pushed_node_ids_offsets_to_me;
4800 std::map<processor_id_type, std::vector<const Node *>> pushed_node_vecs;
4802 for (
const auto & [pid, pid_ids]: pushed_node_ids)
4804 const std::size_t ids_size = pid_ids.size();
4805 std::vector<std::vector<std::pair<dof_id_type,Real>>> &
4806 keys_vals = pushed_node_keys_vals[pid];
4807 std::vector<std::pair<dof_id_type, Point>> &
4808 ids_offsets = pushed_node_ids_offsets[pid];
4809 keys_vals.resize(ids_size);
4810 ids_offsets.resize(ids_size);
4811 std::set<Node *> nodes;
4814 std::set<dof_id_type>::const_iterator it;
4815 for (push_i = 0, it = pid_ids.begin();
4816 it != pid_ids.end(); ++push_i, ++it)
4821 nodes.insert(constrained);
4824 std::size_t row_size = row.size();
4825 keys_vals[push_i].reserve(row_size);
4826 for (
const auto & j : row)
4828 Node * constraining =
const_cast<Node *
>(j.first);
4830 keys_vals[push_i].emplace_back(constraining->
id(), j.second);
4833 nodes.insert(constraining);
4836 ids_offsets[push_i].first = *it;
4842 auto & pid_nodes = pushed_node_vecs[pid];
4843 pid_nodes.assign(nodes.begin(), nodes.end());
4847 auto node_ids_offsets_action_functor =
4848 [& pushed_node_ids_offsets_to_me]
4850 const std::vector<std::pair<dof_id_type, Point>> & data)
4852 pushed_node_ids_offsets_to_me[pid] = data;
4855 auto node_keys_vals_action_functor =
4856 [& pushed_node_keys_vals_to_me]
4858 const std::vector<std::vector<std::pair<dof_id_type, Real>>> & data)
4860 pushed_node_keys_vals_to_me[pid] = data;
4864 Parallel::push_parallel_vector_data
4865 (this->
comm(), pushed_node_ids_offsets, node_ids_offsets_action_functor);
4866 Parallel::push_parallel_vector_data
4867 (this->
comm(), pushed_node_keys_vals, node_keys_vals_action_functor);
4873 auto null_node_functor = [](
processor_id_type,
const std::vector<const Node *> &){};
4876 Parallel::push_parallel_packed_range
4877 (this->
comm(), pushed_node_vecs, &
mesh, null_node_functor);
4879 for (
const auto & [pid, ids_offsets] : pushed_node_ids_offsets_to_me)
4881 const auto & keys_vals = pushed_node_keys_vals_to_me[pid];
4883 libmesh_assert_equal_to
4884 (ids_offsets.size(), keys_vals.size());
4889 dof_id_type constrained_id = ids_offsets[i].first;
4897 for (
auto & key_val : keys_vals[i])
4900 row[key_node] = key_val.second;
4903 ids_offsets[i].second;
4907 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 4920 typedef std::map<dof_id_type, std::set<dof_id_type>> DofConstrainsMap;
4921 DofConstrainsMap dof_id_constrains;
4925 for (
const auto & j : row)
4930 while (constraining >=
_end_df[constraining_proc_id])
4931 constraining_proc_id++;
4934 dof_id_constrains[constraining].insert(constrained);
4942 for (
const auto & elem :
as_range(
mesh.active_not_local_elements_begin(),
4943 mesh.active_not_local_elements_end()))
4945 std::vector<dof_id_type> my_dof_indices;
4948 for (
const auto & dof : my_dof_indices)
4950 if (
auto dcmi = dof_id_constrains.find(dof);
4951 dcmi != dof_id_constrains.end())
4953 for (
const auto & constrained : dcmi->second)
4956 while (constrained >=
_end_df[the_constrained_proc_id])
4957 the_constrained_proc_id++;
4960 if (elemproc != the_constrained_proc_id)
4961 pushed_ids[elemproc].insert(constrained);
4967 pushed_ids_rhss.clear();
4968 pushed_ids_rhss_to_me.clear();
4969 pushed_keys_vals.clear();
4970 pushed_keys_vals_to_me.clear();
4975 Parallel::push_parallel_vector_data
4976 (this->
comm(), pushed_ids_rhss, ids_rhss_action_functor);
4977 Parallel::push_parallel_vector_data
4978 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
4980 receive_dof_constraints();
4992 (elements_to_couple,
4993 temporary_coupling_matrices,
4996 mesh.active_local_elements_begin(),
4997 mesh.active_local_elements_end(),
5001 std::set<dof_id_type> requested_dofs;
5003 for (
const auto & pr : elements_to_couple)
5005 const Elem * elem = pr.first;
5008 std::vector<dof_id_type> element_dofs;
5011 for (
auto dof : element_dofs)
5012 requested_dofs.insert(dof);
5020 std::set<dof_id_type> & unexpanded_dofs,
5023 typedef std::set<dof_id_type> DoF_RCSet;
5027 const unsigned int max_qoi_num =
5033 bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
5034 this->
comm().
max(unexpanded_set_nonempty);
5036 while (unexpanded_set_nonempty)
5039 parallel_object_only();
5042 DoF_RCSet dof_request_set;
5045 std::map<processor_id_type, std::vector<dof_id_type>>
5049 std::map<processor_id_type, dof_id_type>
5053 for (
const auto & unexpanded_dof : unexpanded_dofs)
5062 dof_request_set.insert(unexpanded_dof);
5070 for (
const auto & j : row)
5078 dof_request_set.insert(constraining_dof);
5084 unexpanded_dofs.clear();
5088 for (
const auto & i : dof_request_set)
5092 dof_ids_on_proc[proc_id]++;
5095 for (
auto & pair : dof_ids_on_proc)
5097 requested_dof_ids[pair.first].reserve(pair.second);
5102 for (
const auto & i : dof_request_set)
5106 requested_dof_ids[proc_id].push_back(i);
5109 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
5111 typedef std::vector<Number> rhss_datum;
5113 auto row_gather_functor =
5116 const std::vector<dof_id_type> & ids,
5117 std::vector<row_datum> & data)
5120 const std::size_t query_size = ids.size();
5122 data.resize(query_size);
5123 for (std::size_t i=0; i != query_size; ++i)
5129 std::size_t row_size = row.size();
5130 data[i].reserve(row_size);
5131 for (
const auto & j : row)
5133 data[i].push_back(j);
5161 auto rhss_gather_functor =
5165 const std::vector<dof_id_type> & ids,
5166 std::vector<rhss_datum> & data)
5169 const std::size_t query_size = ids.size();
5171 data.resize(query_size);
5172 for (std::size_t i=0; i != query_size; ++i)
5178 DofConstraintValueMap::const_iterator rhsit =
5184 for (
unsigned int q = 0; q != max_qoi_num; ++q)
5186 AdjointDofConstraintValues::const_iterator adjoint_map_it =
5191 data[i].push_back(0);
5196 adjoint_map_it->second;
5198 DofConstraintValueMap::const_iterator adj_rhsit =
5199 constraint_map.find(constrained);
5201 ((adj_rhsit == constraint_map.end()) ?
5202 0 : adj_rhsit->second);
5208 auto row_action_functor =
5212 const std::vector<dof_id_type> & ids,
5213 const std::vector<row_datum> & data)
5216 const std::size_t query_size = ids.size();
5218 for (std::size_t i=0; i != query_size; ++i)
5224 if (data[i].empty())
5233 for (
auto & pair : data[i])
5235 libmesh_assert_less(pair.first, this->n_dofs());
5236 row[pair.first] = pair.second;
5240 unexpanded_dofs.insert(constrained);
5245 auto rhss_action_functor =
5249 const std::vector<dof_id_type> & ids,
5250 const std::vector<rhss_datum> & data)
5253 const std::size_t query_size = ids.size();
5255 for (std::size_t i=0; i != query_size; ++i)
5257 if (!data[i].empty())
5260 if (data[i][0] !=
Number(0))
5265 for (
unsigned int q = 0; q != max_qoi_num; ++q)
5267 AdjointDofConstraintValues::iterator adjoint_map_it =
5271 data[i][q+1] ==
Number(0))
5279 adjoint_map_it->second;
5281 if (data[i][q+1] !=
Number(0))
5282 constraint_map[constrained] =
5285 constraint_map.erase(constrained);
5293 row_datum * row_ex =
nullptr;
5294 Parallel::pull_parallel_vector_data
5295 (this->
comm(), requested_dof_ids, row_gather_functor,
5296 row_action_functor, row_ex);
5299 rhss_datum * rhs_ex =
nullptr;
5300 Parallel::pull_parallel_vector_data
5301 (this->
comm(), requested_dof_ids, rhss_gather_functor,
5302 rhss_action_functor, rhs_ex);
5306 unexpanded_set_nonempty = !unexpanded_dofs.empty();
5307 this->
comm().
max(unexpanded_set_nonempty);
5314 parallel_object_only();
5323 this->
comm().
max(has_constraints);
5324 if (!has_constraints)
5328 for (
const auto & j : constraint_row)
5343 add_row(constraint_row);
5357 std::unordered_set<dof_id_type> extra_dependencies;
5360 std::vector<dof_id_type> di;
5362 for (
const auto & dof_id : di)
5366 add_row(pos->second);
5372 #endif // LIBMESH_ENABLE_CONSTRAINTS 5375 #ifdef LIBMESH_ENABLE_AMR 5385 libmesh_assert_greater (elem->
p_level(), p);
5386 libmesh_assert_less (s, elem->
n_sides());
5388 const unsigned int sys_num = this->
sys_number();
5392 for (
unsigned int n = 0; n !=
n_nodes; ++n)
5396 const unsigned int low_nc =
5398 const unsigned int high_nc =
5410 for (
unsigned int i = low_nc; i != high_nc; ++i)
5418 const unsigned int total_dofs = node.
n_comp(sys_num, var);
5419 libmesh_assert_greater_equal (total_dofs, high_nc);
5422 for (
unsigned int j = low_nc; j != high_nc; ++j)
5424 const unsigned int i = total_dofs - j - 1;
5432 #endif // LIBMESH_ENABLE_AMR 5435 #ifdef LIBMESH_ENABLE_DIRICHLET 5443 unsigned int qoi_index)
5445 unsigned int old_size = cast_int<unsigned int>
5447 for (
unsigned int i = old_size; i <= qoi_index; ++i)
5452 (std::make_unique<DirichletBoundary>(dirichlet_boundary));
5476 unsigned int old_size = cast_int<unsigned int>
5478 for (
unsigned int i = old_size; i <= q; ++i)
5488 auto lam = [&boundary_to_remove](
const auto & bdy)
5489 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
5500 unsigned int qoi_index)
5505 auto lam = [&boundary_to_remove](
const auto & bdy)
5506 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
5521 const std::set<boundary_id_type>& mesh_side_bcids =
5523 const std::set<boundary_id_type>& mesh_edge_bcids =
5525 const std::set<boundary_id_type>& mesh_node_bcids =
5527 const std::set<boundary_id_type>& dbc_bcids = boundary.
b;
5532 for (
const auto & bc_id : dbc_bcids)
5537 bool found_bcid = (mesh_side_bcids.find(bc_id) != mesh_side_bcids.end() ||
5538 mesh_edge_bcids.find(bc_id) != mesh_edge_bcids.end() ||
5539 mesh_node_bcids.find(bc_id) != mesh_node_bcids.end());
5546 libmesh_error_msg_if(!found_bcid,
5547 "Could not find Dirichlet boundary id " << bc_id <<
" in mesh!");
5551 #endif // LIBMESH_ENABLE_DIRICHLET 5554 #ifdef LIBMESH_ENABLE_PERIODIC 5575 if (!existing_boundary)
5588 existing_boundary->merge(boundary);
5595 existing_inverse_boundary->
merge(inverse_boundary);
5599 #ifdef LIBMESH_HAVE_RTTI 5603 libmesh_assert(
typeid(inverse_boundary) ==
typeid(*existing_inverse_boundary));
void remove_adjoint_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary, unsigned int q)
Removes from the system the specified Dirichlet boundary for the adjoint equation defined by Quantity...
std::unique_ptr< FEMFunctionBase< Gradient > > g_fem
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
std::string get_local_constraints(bool print_nonlocal=false) const
Gets a string reporting all DoF and Node constraints local to this processor.
FEFamily family
The type of finite element.
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.
void constrain_element_dyad_matrix(DenseVector< Number > &v, DenseVector< Number > &w, std::vector< dof_id_type > &row_dofs, bool asymmetric_constraint_rows=true) const
Constrains a dyadic element matrix B = v w'.
bool is_constrained_node(const Node *node) const
void add_adjoint_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary, unsigned int q)
Adds a copy of the specified Dirichlet boundary to the system, corresponding to the adjoint problem d...
void check_dirichlet_bcid_consistency(const MeshBase &mesh, const DirichletBoundary &boundary) const
Check that all the ids in dirichlet_bcids are actually present in the mesh.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
virtual Output component(unsigned int i, const Point &p, Real time=0.)
constraint_rows_type & get_constraint_rows()
Constraint rows accessors.
A Node is like a Point, but with more information.
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for edge/face (2D/3D) finite element object for variable var for the largest dimension in th...
virtual void zero() override final
Set every element in the vector to 0.
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
std::unique_ptr< PointLocatorBase > sub_point_locator() const
std::unique_ptr< FunctionBase< Number > > f
void scatter_constraints(MeshBase &)
Sends constraint equations to constraining processors.
void add_periodic_boundary(const PeriodicBoundaryBase &periodic_boundary)
Adds a copy of the specified periodic boundary to the system.
static void compute_node_constraints(NodeConstraints &constraints, const Elem *elem)
Computes the nodal constraint contributions (for non-conforming adapted meshes), using Lagrange geome...
bool _error_on_constraint_loop
This flag indicates whether or not we do an opt-mode check for the presence of constraint loops...
void add_adjoint_constraint_row(const unsigned int qoi_index, const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...
void get_edge_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for edge (3D only!) finite element object for variable var.
void process_mesh_constraint_rows(const MeshBase &mesh)
Adds any spline constraints from the Mesh to our DoF constraints.
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
void constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix and vector.
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a LinearSolver using the linear solver package specified by solver_package.
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...
dof_id_type n_dofs() const
static constexpr Real TOLERANCE
Real jacobian_tolerance
Defaults to zero, but can be set to a custom small negative value to try and avoid spurious zero (or ...
We're using a class instead of a typedef to allow forward declarations and future flexibility...
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const =0
MessageTag get_unique_tag(int tagvalue=MessageTag::invalid_tag) const
const std::set< unsigned int > & get_variables() const
Get the set of variables for this periodic boundary condition.
dof_id_type n_local_constrained_dofs() const
virtual numeric_index_type size() const =0
void resize(const unsigned int n)
Resize the vector.
void remove_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Removes the specified Dirichlet boundary from the system.
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...
std::vector< dof_id_type > _send_list
A list containing all the global DOF indices that affect the solution on my processor.
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false, bool use_condensed_system=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling...
This is the base class from which all geometric element types are derived.
boundary_id_type pairedboundary
void gather_constraints(MeshBase &mesh, std::set< dof_id_type > &unexpanded_dofs, bool look_for_constrainees)
Helper function for querying about constraint equations on other processors.
static FEFieldType field_type(const FEType &fe_type)
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
std::unique_ptr< DirichletBoundaries > _dirichlet_boundaries
Data structure containing Dirichlet functions.
NumericVector< Number > * rhs
The system matrix.
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
const Parallel::Communicator & comm() const
The Node constraint storage format.
unsigned int p_level() const
std::vector< unsigned int > variables
void set_algebraic_type(const AlgebraicType atype)
Setting which determines whether to initialize algebraic structures (elem_*) on each element and set ...
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
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.
std::map< const Elem *, const CouplingMatrix *, CompareDofObjectsByPIDAndThenID > map_type
What elements do we care about and what variables do we care about on each element?
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The StoredRange class defines a contiguous, divisible set of objects.
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.
const MeshBase & get_mesh() const
void send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, std::size_t approx_buffer_size=1000000) const
Real distance(const Point &p)
Number exact_value(const Point &p, const Parameters ¶meters, const std::string &, const std::string &)
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
unsigned int sys_number() const
uint8_t processor_id_type
This is the MeshBase class.
const Variable & variable(const unsigned int c) const override
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value)=0
Set the element (i,j) to value.
void enforce_adjoint_constraints_exactly(NumericVector< Number > &v, unsigned int q) const
Heterogeneously constrains the numeric vector v, which represents an adjoint solution defined on the ...
AdjointDofConstraintValues _adjoint_constraint_values
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this)^T * arg.
dof_id_type end_dof() const
void check_for_constraint_loops()
static void compute_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...
void merge(const PeriodicBoundaryBase &pb)
const std::set< boundary_id_type > & get_node_boundary_ids() const
void enforce_constraints_on_residual(const NonlinearImplicitSystem &system, NumericVector< Number > *rhs, NumericVector< Number > const *solution, bool homogeneous=true) const
This class handles the numbering of degrees of freedom on a mesh.
std::unique_ptr< FEMFunctionBase< Number > > f_fem
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const =0
const std::vector< std::vector< OutputGradient > > & get_dphi() const
unsigned int first_scalar_number() const
processor_id_type n_processors() const
virtual bool is_serial() const
void set_jacobian_tolerance(Real tol)
Set the Jacobian tolerance used for determining when the mapping fails.
boundary_id_type myboundary
The boundary ID of this boundary and its counterpart.
const dof_id_type n_nodes
dof_id_type first_dof() const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
This class defines the notion of a variable in the system.
bool has_static_condensation() const
Checks whether we have static condensation.
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
Performs the scaled matrix-vector multiplication, dest += factor * (*this) * arg. ...
bool has_adjoint_dirichlet_boundaries(unsigned int q) const
const Node & node_ref(const unsigned int i) const
void min(const T &r, T &o, Request &req) const
StaticCondensationDofMap & get_static_condensation()
void add_constraint_row(const dof_id_type dof_number, const DofConstraintRow &constraint_row, const Number constraint_rhs, const bool forbid_constraint_overwrite)
Adds a copy of the user-defined row to the constraint matrix, using an inhomogeneous right-hand-side ...
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
const System & get_system() const
Accessor for associated system.
virtual unsigned int n_nodes() const =0
std::set< std::unique_ptr< CouplingMatrix >, Utility::CompareUnderlying > CouplingMatricesSet
void heterogeneously_constrain_element_vector(const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
Constrains the element vector.
void receive_packed_range(const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Manages consistently variables, degrees of freedom, and coefficient vectors.
unsigned int n_variables() const override
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
virtual void init_context(const FEMContext &)
Prepares a context object for use.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
We're using a class instead of a typedef to allow forward declarations and future flexibility...
void print_dof_constraints(std::ostream &os=libMesh::out, bool print_nonlocal=false) const
Prints (from processor 0) all DoF and Node constraints.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
bool is_constrained_dof(const dof_id_type dof) const
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
const FEType & variable_type(const unsigned int i) const
virtual_for_inffe const std::vector< Real > & get_JxW() const
void allgather_recursive_constraints(MeshBase &)
Gathers constraint equation dependencies from other processors.
This class provides all data required for a physics package (e.g.
virtual void reinit(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)=0
This is at the core of this class.
const std::vector< dof_id_type > & get_dof_indices() const
Accessor for element dof indices.
DofConstraints _dof_constraints
Data structure containing DOF constraints.
unsigned int n_points() const
virtual_for_inffe const std::vector< Point > & get_xyz() const
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, CouplingMatricesSet &temporary_coupling_matrices, const GhostingFunctorIterator &gf_begin, const GhostingFunctorIterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
bool active_on_subdomain(subdomain_id_type sid) const
virtual unsigned int n_edges() const =0
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
If we want the DofMap to be able to make copies of references and store them in the underlying map...
static unsigned int n_vec_dim(const MeshBase &mesh, const FEType &fe_type)
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
std::pair< Real, Real > max_constraint_error(const System &system, NumericVector< Number > *v=nullptr) const
Tests the constrained degrees of freedom on the numeric vector v, which represents a solution defined...
A do-nothing class for templated methods that expect output iterator arguments.
Storage for DofConstraint right hand sides for a particular problem.
std::string enum_to_string(const T e)
GhostingFunctorIterator coupling_functors_end() const
End of range of coupling functors.
virtual bool closed() const
unsigned int n_vars() const
static FEContinuity get_continuity(const FEType &fe_type)
Returns the input FEType's FEContinuity based on the underlying FEFamily and potentially the Order...
const std::set< boundary_id_type > & get_boundary_ids() const
std::vector< std::unique_ptr< DirichletBoundaries > > _adjoint_dirichlet_boundaries
Data structure containing Dirichlet functions.
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual numeric_index_type first_local_index() const =0
virtual unsigned int n_sides() const =0
virtual void edge_reinit(const Elem *elem, const unsigned int edge, const Real tolerance=TOLERANCE, const std::vector< Point > *pts=nullptr, const std::vector< Real > *weights=nullptr)=0
Reinitializes all the physical element-dependent data based on the edge of the element elem...
ParallelType type() const
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void left_multiply_transpose(const DenseMatrix< T > &A)
Left multiplies by the transpose of the matrix A.
void process_constraints(MeshBase &)
Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dof...
subdomain_id_type subdomain_id() const
std::unique_ptr< FunctionBase< Gradient > > g
timpi_pure bool verify(const T &r) const
dof_id_type n_constrained_dofs() const
void constrain_element_vector(DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
Constrains the element vector.
void max(const T &r, T &o, Request &req) const
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
const DirichletBoundaries * get_adjoint_dirichlet_boundaries(unsigned int q) const
virtual bool is_vertex(const unsigned int i) const =0
bool _verify_dirichlet_bc_consistency
Flag which determines whether we should do some additional checking of the consistency of the Dirichl...
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
void add_constraints_to_send_list()
Adds entries to the _send_list vector corresponding to DoFs which are dependencies for constraint equ...
virtual void right_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- (*this) * M3.
SparseMatrix< Number > * matrix
The system matrix.
DofConstraintValueMap _primal_constraint_values
virtual numeric_index_type local_size() const =0
void heterogeneously_constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
Constrains the element matrix and vector.
const std::set< boundary_id_type > & get_edge_boundary_ids() const
virtual Output component(const FEMContext &, unsigned int i, const Point &p, Real time=0.)
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
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.
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...
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
unsigned int mesh_dimension() const
unsigned int variable_number(std::string_view var) const
dof_id_type n_local_dofs() const
virtual unsigned int size() const override final
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
void build_constraint_matrix(DenseMatrix< Number > &C, std::vector< dof_id_type > &elem_dofs, const bool called_recursively=false) const
Build the constraint matrix C associated with the element degree of freedom indices elem_dofs...
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Accessor for interior finite element object for variable var for the largest dimension in the mesh...
void heterogeneously_constrain_element_residual(DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
Constrains the element residual.
The base class for defining periodic boundaries.
void create_dof_constraints(const MeshBase &, Real time=0)
Rebuilds the raw degree of freedom and DofObject constraints, based on attached DirichletBoundary obj...
std::set< boundary_id_type > b
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
A row of the Node constraint mapping.
virtual void set(const numeric_index_type i, const T value)=0
Sets v(i) = value.
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
const QBase & get_edge_qrule() const
Accessor for element edge quadrature rule.
void heterogeneously_constrain_element_jacobian_and_residual(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
Constrains the element Jacobian and residual.
unsigned int number() const
const FEMap & get_fe_map() const
FEFamily
defines an enum for finite element families.
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
void constrain_element_residual(DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, NumericVector< Number > &solution_local) const
Constrains the element residual.
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 periodic boundary conditions) corresponding to vari...
const DofMap & get_dof_map() const
processor_id_type processor_id() 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, 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.
dof_id_type node_id(const unsigned int i) const
const Point & point(const unsigned int i) const
virtual numeric_index_type last_local_index() const =0
The constraint matrix storage format.
const std::vector< dof_id_type > & get_send_list() const
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
static void compute_periodic_node_constraints(NodeConstraints &constraints, const PeriodicBoundaries &boundaries, const MeshBase &mesh, const PointLocatorBase *point_locator, const Elem *elem)
Computes the node position constraint equation contributions (for meshes with periodic boundary condi...
This class forms the foundation from which generic finite elements may be derived.
void constrain_nothing(std::vector< dof_id_type > &dofs) const
Does not actually constrain anything, but modifies dofs in the same way as any of the constrain funct...
const QBase & get_element_qrule() const
Accessor for element interior quadrature rule for the dimension of the current _elem.
This class provides single index access to FieldType (i.e.
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this) * arg.
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 check_for_cyclic_constraints()
Throw an error if we detect any constraint loops, i.e.
const QBase & get_side_qrule() const
Accessor for element side quadrature rule for the dimension of the current _elem. ...
GhostingFunctorIterator coupling_functors_begin() const
Beginning of range of coupling functors.
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
bool local_index(dof_id_type dof_index) const
const std::vector< std::vector< OutputShape > > & get_phi() const
const FEType & type() const
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh. ...
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix.
virtual void localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.
void enforce_constraints_on_jacobian(const NonlinearImplicitSystem &system, SparseMatrix< Number > *jac) const