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/mesh_base.h"
35 #include "libmesh/mesh_inserter_iterator.h"
36 #include "libmesh/mesh_tools.h"
37 #include "libmesh/nonlinear_implicit_system.h"
38 #include "libmesh/numeric_vector.h"
39 #include "libmesh/parallel_algebra.h"
40 #include "libmesh/parallel_elem.h"
41 #include "libmesh/parallel_node.h"
42 #include "libmesh/periodic_boundaries.h"
43 #include "libmesh/periodic_boundary.h"
44 #include "libmesh/periodic_boundary_base.h"
45 #include "libmesh/point_locator_base.h"
46 #include "libmesh/quadrature.h"
47 #include "libmesh/raw_accessor.h"
48 #include "libmesh/sparse_matrix.h"
49 #include "libmesh/system.h"
50 #include "libmesh/tensor_tools.h"
51 #include "libmesh/threads.h"
70 class ComputeConstraints
75 #ifdef LIBMESH_ENABLE_PERIODIC
79 const unsigned int variable_number) :
80 _constraints(constraints),
82 #ifdef LIBMESH_ENABLE_PERIODIC
83 _periodic_boundaries(periodic_boundaries),
86 _variable_number(variable_number)
91 const Variable & var_description = _dof_map.variable(_variable_number);
93 #ifdef LIBMESH_ENABLE_PERIODIC
94 std::unique_ptr<PointLocatorBase> point_locator;
95 const bool have_periodic_boundaries =
96 !_periodic_boundaries.empty();
97 if (have_periodic_boundaries && !range.
empty())
98 point_locator = _mesh.sub_point_locator();
101 for (
const auto & elem : range)
104 #ifdef LIBMESH_ENABLE_AMR
110 #ifdef LIBMESH_ENABLE_PERIODIC
114 if (have_periodic_boundaries)
117 _periodic_boundaries,
129 #ifdef LIBMESH_ENABLE_PERIODIC
133 const unsigned int _variable_number;
138 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
139 class ComputeNodeConstraints
143 #ifdef LIBMESH_ENABLE_PERIODIC
147 _node_constraints(node_constraints),
148 #ifdef LIBMESH_ENABLE_PERIODIC
149 _periodic_boundaries(periodic_boundaries),
156 #ifdef LIBMESH_ENABLE_PERIODIC
157 std::unique_ptr<PointLocatorBase> point_locator;
158 bool have_periodic_boundaries = !_periodic_boundaries.empty();
159 if (have_periodic_boundaries && !range.
empty())
160 point_locator = _mesh.sub_point_locator();
163 for (
const auto & elem : range)
165 #ifdef LIBMESH_ENABLE_AMR
168 #ifdef LIBMESH_ENABLE_PERIODIC
172 if (have_periodic_boundaries)
174 _periodic_boundaries,
184 #ifdef LIBMESH_ENABLE_PERIODIC
189 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
192 #ifdef LIBMESH_ENABLE_DIRICHLET
203 AddConstraint(
DofMap & dof_map_in) : dof_map(dof_map_in) {}
207 const Number constraint_rhs)
const = 0;
210 class AddPrimalConstraint :
public AddConstraint
213 AddPrimalConstraint(
DofMap & dof_map_in) : AddConstraint(dof_map_in) {}
217 const Number constraint_rhs)
const
219 if (!dof_map.is_constrained_dof(dof_number))
220 dof_map.add_constraint_row (dof_number, constraint_row,
221 constraint_rhs,
true);
225 class AddAdjointConstraint :
public AddConstraint
228 const unsigned int qoi_index;
231 AddAdjointConstraint(
DofMap & dof_map_in,
unsigned int qoi_index_in)
232 : AddConstraint(dof_map_in), qoi_index(qoi_index_in) {}
236 const Number constraint_rhs)
const
238 dof_map.add_adjoint_constraint_row
239 (qoi_index, dof_number, constraint_row, constraint_rhs,
251 class ConstrainDirichlet
259 const AddConstraint & add_fn;
273 return std::numeric_limits<Real>::quiet_NaN();
290 return std::numeric_limits<Number>::quiet_NaN();
295 template<
typename OutputType>
297 const unsigned int var,
299 const FEType & fe_type)
const
301 typedef OutputType OutputShape;
316 const std::set<boundary_id_type> & b = dirichlet.
b;
343 const unsigned int var_component =
363 const std::vector<std::vector<OutputShape>> & phi = fe->get_phi();
367 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
382 const std::vector<std::vector<OutputGradient>> & ref_dphi = fe->get_dphi();
387 const std::vector<Real> & JxW = fe->get_JxW();
390 const std::vector<Point> & xyz_values = fe->get_xyz();
393 std::vector<dof_id_type> dof_indices;
395 std::vector<unsigned int> side_dofs;
400 std::unique_ptr<FEMContext> context;
406 context = libmesh_make_unique<FEMContext>(*f_system);
414 for (
const auto & elem : range)
426 const unsigned short n_sides = elem->n_sides();
427 const unsigned short n_edges = elem->n_edges();
428 const unsigned short n_nodes = elem->n_nodes();
432 std::vector<bool> is_boundary_node(
n_nodes,
false),
433 is_boundary_edge(n_edges,
false),
434 is_boundary_side(n_sides,
false),
435 is_boundary_shellface(2,
false);
438 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
442 bool has_dirichlet_constraint =
false;
446 std::vector<boundary_id_type> ids_vec;
448 for (
unsigned char s = 0; s != n_sides; ++s)
453 bool do_this_side =
false;
454 for (
const auto & bc_id : ids_vec)
463 is_boundary_side[s] =
true;
464 has_dirichlet_constraint =
true;
467 for (
unsigned int n = 0; n !=
n_nodes; ++n)
468 if (elem->is_node_on_side(n,s))
469 is_boundary_node[n] =
true;
470 for (
unsigned int e = 0; e != n_edges; ++e)
471 if (elem->is_edge_on_side(e,s))
472 is_boundary_edge[e] =
true;
477 for (
unsigned int n=0; n !=
n_nodes; ++n)
479 boundary_info.
boundary_ids (elem->node_ptr(n), ids_vec);
481 for (
const auto & bc_id : ids_vec)
484 is_boundary_node[n] =
true;
485 is_boundary_nodeset[n] =
true;
486 has_dirichlet_constraint =
true;
492 for (
unsigned short e=0; e != n_edges; ++e)
496 for (
const auto & bc_id : ids_vec)
499 is_boundary_edge[e] =
true;
500 has_dirichlet_constraint =
true;
506 for (
unsigned short shellface=0; shellface != 2; ++shellface)
510 for (
const auto & bc_id : ids_vec)
513 is_boundary_shellface[shellface] =
true;
514 has_dirichlet_constraint =
true;
518 if(!has_dirichlet_constraint)
535 if (f_system && context.get())
536 context->pre_fe_reinit(*f_system, elem);
543 const unsigned int n_dofs =
544 cast_int<unsigned int>(dof_indices.size());
547 std::vector<char> dof_is_fixed(n_dofs,
false);
548 std::vector<int> free_dof(n_dofs, 0);
551 const ElemType elem_type = elem->type();
566 unsigned int current_dof = 0;
567 for (
unsigned int n=0; n!=
n_nodes; ++n)
571 const unsigned int nc =
574 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
575 !is_boundary_nodeset[n])
582 libmesh_assert_equal_to (nc, 0);
588 libmesh_assert_equal_to (nc, n_vec_dim);
589 for (
unsigned int c = 0; c < n_vec_dim; c++)
592 f_component(f, f_fem, context.get(), var_component+c,
593 elem->point(n), time);
594 dof_is_fixed[current_dof+c] =
true;
596 current_dof += n_vec_dim;
602 f_component(f, f_fem, context.get(), var_component,
603 elem->point(n), time);
604 dof_is_fixed[current_dof] =
true;
607 g_component(g, g_fem, context.get(), var_component,
608 elem->point(n), time);
610 Ue(current_dof) = grad(0);
611 dof_is_fixed[current_dof] =
true;
616 Point nxminus = elem->point(n),
617 nxplus = elem->point(n);
621 g_component(g, g_fem, context.get(), var_component,
624 g_component(g, g_fem, context.get(), var_component,
627 Ue(current_dof) = grad(1);
628 dof_is_fixed[current_dof] =
true;
631 Ue(current_dof) = (gxplus(1) - gxminus(1))
633 dof_is_fixed[current_dof] =
true;
639 Ue(current_dof) = grad(2);
640 dof_is_fixed[current_dof] =
true;
643 Ue(current_dof) = (gxplus(2) - gxminus(2))
645 dof_is_fixed[current_dof] =
true;
648 Point nyminus = elem->point(n),
649 nyplus = elem->point(n);
653 g_component(g, g_fem, context.get(), var_component,
656 g_component(g, g_fem, context.get(), var_component,
659 Ue(current_dof) = (gyplus(2) - gyminus(2))
661 dof_is_fixed[current_dof] =
true;
664 Point nxmym = elem->point(n),
665 nxmyp = elem->point(n),
666 nxpym = elem->point(n),
667 nxpyp = elem->point(n);
677 g_component(g, g_fem, context.get(), var_component,
680 g_component(g, g_fem, context.get(), var_component,
683 g_component(g, g_fem, context.get(), var_component,
686 g_component(g, g_fem, context.get(), var_component,
688 Number gxzplus = (gxpyp(2) - gxmyp(2))
690 Number gxzminus = (gxpym(2) - gxmym(2))
693 Ue(current_dof) = (gxzplus - gxzminus)
695 dof_is_fixed[current_dof] =
true;
703 else if (cont ==
C_ONE)
705 libmesh_assert_equal_to (nc, 1 +
dim);
707 f_component(f, f_fem, context.get(), var_component,
708 elem->point(n), time);
709 dof_is_fixed[current_dof] =
true;
712 g_component(g, g_fem, context.get(), var_component,
713 elem->point(n), time);
714 for (
unsigned int i=0; i!=
dim; ++i)
716 Ue(current_dof) = grad(i);
717 dof_is_fixed[current_dof] =
true;
722 libmesh_error_msg(
"Unknown continuity cont = " << cont);
727 for (
unsigned int e=0; e != n_edges; ++e)
729 if (!is_boundary_edge[e])
735 const unsigned int n_side_dofs =
736 cast_int<unsigned int>(side_dofs.size());
740 unsigned int free_dofs = 0;
741 for (
unsigned int i=0; i != n_side_dofs; ++i)
742 if (!dof_is_fixed[side_dofs[i]])
743 free_dof[free_dofs++] = i;
755 fe->attach_quadrature_rule (qedgerule.get());
756 fe->edge_reinit (elem, e);
757 const unsigned int n_qp = qedgerule->n_points();
760 for (
unsigned int qp=0; qp<n_qp; qp++)
763 OutputNumber fineval(0);
766 for (
unsigned int c = 0; c < n_vec_dim; c++)
768 f_component(f, f_fem, context.get(), var_component+c,
769 xyz_values[qp], time);
772 OutputNumberGradient finegrad;
789 libmesh_error_msg(
"Unknown field type!");
793 for (
unsigned int c = 0; c < n_vec_dim; c++)
794 for (
unsigned int d = 0; d < g_rank; d++)
795 g_accessor(c + d*
dim ) =
796 g_component(g, g_fem, context.get(), var_component,
797 xyz_values[qp], time)(c);
800 for (
unsigned int sidei=0, freei=0; sidei != n_side_dofs; ++sidei)
802 unsigned int i = side_dofs[sidei];
806 for (
unsigned int sidej=0, freej=0; sidej != n_side_dofs; ++sidej)
808 unsigned int j = side_dofs[sidej];
810 Fe(freei) -= phi[i][qp] * phi[j][qp] *
813 Ke(freei,freej) += phi[i][qp] *
814 phi[j][qp] * JxW[qp];
818 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp]) ) *
821 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
824 if (!dof_is_fixed[j])
827 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
829 Fe(freei) += (finegrad.contract( (*dphi)[i][qp]) ) *
838 for (
unsigned int i=0; i != free_dofs; ++i)
840 Number & ui = Ue(side_dofs[free_dof[i]]);
844 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
850 for (
unsigned int s=0; s != n_sides; ++s)
852 if (!is_boundary_side[s])
858 const unsigned int n_side_dofs =
859 cast_int<unsigned int>(side_dofs.size());
863 unsigned int free_dofs = 0;
864 for (
unsigned int i=0; i != n_side_dofs; ++i)
865 if (!dof_is_fixed[side_dofs[i]])
866 free_dof[free_dofs++] = i;
878 fe->attach_quadrature_rule (qsiderule.get());
879 fe->reinit (elem, s);
880 const unsigned int n_qp = qsiderule->n_points();
883 for (
unsigned int qp=0; qp<n_qp; qp++)
886 OutputNumber fineval(0);
889 for (
unsigned int c = 0; c < n_vec_dim; c++)
891 f_component(f, f_fem, context.get(), var_component+c,
892 xyz_values[qp], time);
895 OutputNumberGradient finegrad;
912 libmesh_error_msg(
"Unknown field type!");
916 for (
unsigned int c = 0; c < n_vec_dim; c++)
917 for (
unsigned int d = 0; d < g_rank; d++)
918 g_accessor(c + d*
dim ) =
919 g_component(g, g_fem, context.get(), var_component,
920 xyz_values[qp], time)(c);
923 for (
unsigned int sidei=0, freei=0; sidei != n_side_dofs; ++sidei)
925 unsigned int i = side_dofs[sidei];
929 for (
unsigned int sidej=0, freej=0; sidej != n_side_dofs; ++sidej)
931 unsigned int j = side_dofs[sidej];
933 Fe(freei) -= phi[i][qp] * phi[j][qp] *
936 Ke(freei,freej) += phi[i][qp] *
937 phi[j][qp] * JxW[qp];
941 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
944 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
947 if (!dof_is_fixed[j])
950 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
952 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
961 for (
unsigned int i=0; i != free_dofs; ++i)
963 Number & ui = Ue(side_dofs[free_dof[i]]);
967 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
973 for (
unsigned int shellface=0; shellface != 2; ++shellface)
975 if (!is_boundary_shellface[shellface])
979 std::vector<unsigned int> shellface_dofs(n_dofs);
980 std::iota(shellface_dofs.begin(), shellface_dofs.end(), 0);
984 unsigned int free_dofs = 0;
985 for (
unsigned int i=0; i != n_dofs; ++i)
986 if (!dof_is_fixed[shellface_dofs[i]])
987 free_dof[free_dofs++] = i;
999 fe->attach_quadrature_rule (qrule.get());
1001 const unsigned int n_qp = qrule->n_points();
1004 for (
unsigned int qp=0; qp<n_qp; qp++)
1007 OutputNumber fineval(0);
1010 for (
unsigned int c = 0; c < n_vec_dim; c++)
1012 f_component(f, f_fem, context.get(), var_component+c,
1013 xyz_values[qp], time);
1016 OutputNumberGradient finegrad;
1019 unsigned int g_rank;
1033 libmesh_error_msg(
"Unknown field type!");
1037 for (
unsigned int c = 0; c < n_vec_dim; c++)
1038 for (
unsigned int d = 0; d < g_rank; d++)
1039 g_accessor(c + d*
dim ) =
1040 g_component(g, g_fem, context.get(), var_component,
1041 xyz_values[qp], time)(c);
1044 for (
unsigned int shellfacei=0, freei=0;
1045 shellfacei != n_dofs; ++shellfacei)
1047 unsigned int i = shellface_dofs[shellfacei];
1049 if (dof_is_fixed[i])
1051 for (
unsigned int shellfacej=0, freej=0;
1052 shellfacej != n_dofs; ++shellfacej)
1054 unsigned int j = shellface_dofs[shellfacej];
1055 if (dof_is_fixed[j])
1056 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1059 Ke(freei,freej) += phi[i][qp] *
1060 phi[j][qp] * JxW[qp];
1063 if (dof_is_fixed[j])
1064 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
1067 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
1070 if (!dof_is_fixed[j])
1073 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1075 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
1084 for (
unsigned int i=0; i != free_dofs; ++i)
1086 Number & ui = Ue(shellface_dofs[free_dof[i]]);
1090 dof_is_fixed[shellface_dofs[free_dof[i]]] =
true;
1098 for (
unsigned int i = 0; i < n_dofs; i++)
1102 add_fn (dof_indices[i], empty_row, Ue(i));
1110 ConstrainDirichlet (
DofMap & dof_map_in,
1114 const AddConstraint & add_in) :
1115 dof_map(dof_map_in),
1118 dirichlet(dirichlet_in),
1121 ConstrainDirichlet (
const ConstrainDirichlet & in) :
1122 dof_map(in.dof_map),
1125 dirichlet(in.dirichlet),
1126 add_fn(in.add_fn) { }
1137 for (
const auto & var : dirichlet.
variables)
1150 this->apply_dirichlet_impl<Real>( range, var, variable, fe_type );
1155 this->apply_dirichlet_impl<RealGradient>( range, var, variable, fe_type );
1159 libmesh_error_msg(
"Unknown field type!");
1168 #endif // LIBMESH_ENABLE_DIRICHLET
1181 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1186 parallel_object_only();
1189 this->
comm().sum(nc_dofs);
1196 const DofConstraints::const_iterator lower =
1208 parallel_object_only();
1210 LOG_SCOPE(
"create_dof_constraints()",
"DofMap");
1223 const bool possible_local_constraints =
false
1225 #ifdef LIBMESH_ENABLE_AMR
1228 #ifdef LIBMESH_ENABLE_PERIODIC
1231 #ifdef LIBMESH_ENABLE_DIRICHLET
1237 bool possible_global_constraints = possible_local_constraints;
1238 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR)
1241 this->
comm().max(possible_global_constraints);
1244 if (!possible_global_constraints)
1250 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1255 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1280 #ifdef LIBMESH_ENABLE_PERIODIC
1283 this->
comm().max(need_point_locator);
1285 if (need_point_locator)
1289 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1295 #ifdef LIBMESH_ENABLE_PERIODIC
1299 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1311 for (
unsigned int variable_number=0; variable_number<this->
n_variables();
1312 ++variable_number, range.
reset())
1316 #ifdef LIBMESH_ENABLE_PERIODIC
1322 #ifdef LIBMESH_ENABLE_DIRICHLET
1323 for (DirichletBoundaries::iterator
1333 ConstrainDirichlet(*
this,
mesh, time, **i,
1334 AddPrimalConstraint(*
this))
1338 for (
unsigned int qoi_index = 0,
1340 qoi_index != n_qois; ++qoi_index)
1342 for (DirichletBoundaries::iterator
1353 ConstrainDirichlet(*
this,
mesh, time, **i,
1354 AddAdjointConstraint(*
this, qoi_index))
1359 #endif // LIBMESH_ENABLE_DIRICHLET
1366 const Number constraint_rhs,
1367 const bool forbid_constraint_overwrite)
1370 if (forbid_constraint_overwrite)
1372 libmesh_error_msg(
"ERROR: DOF " << dof_number <<
" was already constrained!");
1374 libmesh_assert_less(dof_number, this->
n_dofs());
1376 for (
const auto & pr : constraint_row)
1377 libmesh_assert_less(pr.first, this->n_dofs());
1381 std::pair<DofConstraints::iterator, bool> it =
1384 it.first->second = constraint_row;
1386 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1389 rhs_it.first->second = constraint_rhs;
1396 const Number constraint_rhs,
1397 const bool forbid_constraint_overwrite)
1400 if (forbid_constraint_overwrite)
1403 libmesh_error_msg(
"ERROR: DOF " << dof_number <<
" has no corresponding primal constraint!");
1428 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1432 rhs_it.first->second = constraint_rhs;
1439 bool print_nonlocal)
const
1441 parallel_object_only();
1443 std::string local_constraints =
1448 this->
comm().send(0, local_constraints);
1452 os <<
"Processor 0:\n";
1453 os << local_constraints;
1457 this->
comm().receive(p, local_constraints);
1458 os <<
"Processor " << p <<
":\n";
1459 os << local_constraints;
1466 std::ostringstream os;
1467 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1473 os <<
"Node Constraints:"
1478 const Node * node = pr.first;
1481 if (!print_nonlocal &&
1486 const Point & offset = pr.second.second;
1488 os <<
"Constraints for Node id " << node->
id()
1491 for (
const auto & item : row)
1492 os <<
" (" << item.first->id() <<
"," << item.second <<
")\t";
1494 os <<
"rhs: " << offset;
1498 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1505 os <<
"DoF Constraints:"
1517 DofConstraintValueMap::const_iterator rhsit =
1522 os <<
"Constraints for DoF " << i
1525 for (
const auto & item : row)
1526 os <<
" (" << item.first <<
"," << item.second <<
")\t";
1528 os <<
"rhs: " << rhs;
1532 for (
unsigned int qoi_index = 0,
1534 qoi_index != n_qois; ++qoi_index)
1536 os <<
"Adjoint " << qoi_index <<
" DoF rhs values:"
1539 AdjointDofConstraintValues::const_iterator adjoint_map_it =
1543 for (
const auto & pr : adjoint_map_it->second)
1551 const Number rhs = pr.second;
1553 os <<
"RHS for DoF " << i
1566 std::vector<dof_id_type> & elem_dofs,
1567 bool asymmetric_constraint_rows)
const
1569 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1570 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1582 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
1585 if ((C.
m() == matrix.
m()) &&
1586 (C.
n() == elem_dofs.size()))
1593 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1594 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1595 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1598 for (
unsigned int i=0,
1599 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1600 i != n_elem_dofs; i++)
1609 if (asymmetric_constraint_rows)
1611 DofConstraints::const_iterator
1624 for (
const auto & item : constraint_row)
1625 for (
unsigned int j=0; j != n_elem_dofs; j++)
1626 if (elem_dofs[j] == item.first)
1627 matrix(i,j) = -item.second;
1637 std::vector<dof_id_type> & elem_dofs,
1638 bool asymmetric_constraint_rows)
const
1640 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1641 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1642 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1654 LOG_SCOPE(
"cnstrn_elem_mat_vec()",
"DofMap");
1657 if ((C.
m() == matrix.
m()) &&
1658 (C.
n() == elem_dofs.size()))
1665 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1666 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1667 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1670 for (
unsigned int i=0,
1671 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1672 i != n_elem_dofs; i++)
1684 if (asymmetric_constraint_rows)
1686 DofConstraints::const_iterator
1696 for (
const auto & item : constraint_row)
1697 for (
unsigned int j=0; j != n_elem_dofs; j++)
1698 if (elem_dofs[j] == item.first)
1699 matrix(i,j) = -item.second;
1716 std::vector<dof_id_type> & elem_dofs,
1717 bool asymmetric_constraint_rows,
1718 int qoi_index)
const
1720 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1721 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1722 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1735 LOG_SCOPE(
"hetero_cnstrn_elem_mat_vec()",
"DofMap");
1738 if ((C.
m() == matrix.
m()) &&
1739 (C.
n() == elem_dofs.size()))
1747 const AdjointDofConstraintValues::const_iterator
1750 rhs_values = &it->second;
1766 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1767 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1768 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1770 for (
unsigned int i=0,
1771 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1772 i != n_elem_dofs; i++)
1787 if (asymmetric_constraint_rows)
1789 DofConstraints::const_iterator
1796 for (
const auto & item : constraint_row)
1797 for (
unsigned int j=0; j != n_elem_dofs; j++)
1798 if (elem_dofs[j] == item.first)
1799 matrix(i,j) = -item.second;
1803 const DofConstraintValueMap::const_iterator valpos =
1804 rhs_values->find(dof_id);
1806 rhs(i) = (valpos == rhs_values->end()) ?
1822 std::vector<dof_id_type> & elem_dofs,
1823 bool asymmetric_constraint_rows,
1824 int qoi_index)
const
1826 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1827 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1828 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1841 LOG_SCOPE(
"hetero_cnstrn_elem_vec()",
"DofMap");
1844 if ((C.
m() == matrix.
m()) &&
1845 (C.
n() == elem_dofs.size()))
1853 const AdjointDofConstraintValues::const_iterator
1856 rhs_values = &it->second;
1868 for (
unsigned int i=0,
1869 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1870 i != n_elem_dofs; i++)
1879 if (asymmetric_constraint_rows && rhs_values)
1881 const DofConstraintValueMap::const_iterator valpos =
1882 rhs_values->find(dof_id);
1884 rhs(i) = (valpos == rhs_values->end()) ?
1899 std::vector<dof_id_type> & row_dofs,
1900 std::vector<dof_id_type> & col_dofs,
1901 bool asymmetric_constraint_rows)
const
1903 libmesh_assert_equal_to (row_dofs.size(), matrix.
m());
1904 libmesh_assert_equal_to (col_dofs.size(), matrix.
n());
1917 std::vector<dof_id_type> orig_row_dofs(row_dofs);
1918 std::vector<dof_id_type> orig_col_dofs(col_dofs);
1923 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
1925 row_dofs = orig_row_dofs;
1926 col_dofs = orig_col_dofs;
1928 bool constraint_found =
false;
1932 if ((R.
m() == matrix.
m()) &&
1933 (R.
n() == row_dofs.size()))
1936 constraint_found =
true;
1939 if ((C.
m() == matrix.
n()) &&
1940 (C.
n() == col_dofs.size()))
1943 constraint_found =
true;
1947 if (constraint_found)
1949 libmesh_assert_equal_to (matrix.
m(), row_dofs.size());
1950 libmesh_assert_equal_to (matrix.
n(), col_dofs.size());
1953 for (
unsigned int i=0,
1954 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
1955 i != n_row_dofs; i++)
1960 if (row_dofs[i] != col_dofs[j])
1966 if (asymmetric_constraint_rows)
1968 DofConstraints::const_iterator
1977 for (
const auto & item : constraint_row)
1978 for (
unsigned int j=0,
1979 n_col_dofs = cast_int<unsigned int>(col_dofs.size());
1980 j != n_col_dofs; j++)
1981 if (col_dofs[j] == item.first)
1982 matrix(i,j) = -item.second;
1991 std::vector<dof_id_type> & row_dofs,
1994 libmesh_assert_equal_to (rhs.
size(), row_dofs.size());
2005 LOG_SCOPE(
"constrain_elem_vector()",
"DofMap");
2008 if ((R.
m() == rhs.
size()) &&
2009 (R.
n() == row_dofs.size()))
2015 libmesh_assert_equal_to (row_dofs.size(), rhs.
size());
2017 for (
unsigned int i=0,
2018 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2019 i != n_row_dofs; i++)
2034 std::vector<dof_id_type> & row_dofs,
2037 libmesh_assert_equal_to (v.
size(), row_dofs.size());
2038 libmesh_assert_equal_to (w.
size(), row_dofs.size());
2049 LOG_SCOPE(
"cnstrn_elem_dyad_mat()",
"DofMap");
2052 if ((R.
m() == v.
size()) &&
2053 (R.
n() == row_dofs.size()))
2063 libmesh_assert_equal_to (row_dofs.size(), v.
size());
2064 libmesh_assert_equal_to (row_dofs.size(), w.
size());
2068 for (
unsigned int i=0,
2069 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2070 i != n_row_dofs; i++)
2099 bool homogeneous)
const
2101 parallel_object_only();
2106 LOG_SCOPE(
"enforce_constraints_exactly()",
"DofMap");
2113 std::unique_ptr<NumericVector<Number>> v_built;
2121 i<v_built->last_local_index(); i++)
2122 v_built->set(i, (*v)(i));
2124 v_global = v_built.
get();
2135 v_local = v_built.
get();
2145 libmesh_error_msg(
"ERROR: Unknown v->type() == " << v->
type());
2152 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2165 DofConstraintValueMap::const_iterator rhsit =
2170 for (
const auto & j : constraint_row)
2191 bool homogeneous)
const
2193 parallel_object_only();
2204 std::unique_ptr<NumericVector<Number>> solution_built;
2206 solution_local = solution;
2210 solution_built->init (solution->
size(), solution->
size(),
true,
SERIAL);
2211 solution->
localize(*solution_built);
2212 solution_built->close();
2213 solution_local = solution_built.
get();
2216 libmesh_error_msg(
"ERROR: Unknown solution->type() == " << solution->
type());
2221 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2232 for (
const auto & j : constraint_row)
2233 exact_value -= j.second * (*solution_local)(j.first);
2234 exact_value += (*solution_local)(constrained_dof);
2237 DofConstraintValueMap::const_iterator rhsit =
2250 parallel_object_only();
2258 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2268 for (
const auto & j : constraint_row)
2269 jac->
set(constrained_dof, j.first, -j.second);
2270 jac->
set(constrained_dof, constrained_dof, 1);
2276 unsigned int q)
const
2278 parallel_object_only();
2283 LOG_SCOPE(
"enforce_adjoint_constraints_exactly()",
"DofMap");
2287 std::unique_ptr<NumericVector<Number>> v_built;
2295 i<v_built->last_local_index(); i++)
2296 v_built->set(i, v(i));
2298 v_global = v_built.
get();
2309 v_local = v_built.
get();
2319 libmesh_error_msg(
"ERROR: Unknown v.type() == " << v.
type());
2328 const AdjointDofConstraintValues::const_iterator
2332 nullptr : &adjoint_constraint_map_it->second;
2345 const DofConstraintValueMap::const_iterator
2346 adjoint_constraint_it =
2347 constraint_map->find(constrained_dof);
2348 if (adjoint_constraint_it != constraint_map->end())
2352 for (
const auto & j : constraint_row)
2372 std::pair<Real, Real>
2383 Real max_absolute_error = 0., max_relative_error = 0.;
2387 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2390 std::vector<dof_id_type> local_dof_indices;
2395 std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
2406 libmesh_assert_equal_to (C.
m(), raw_dof_indices.size());
2407 libmesh_assert_equal_to (C.
n(), local_dof_indices.size());
2418 DofConstraints::const_iterator
2425 DofConstraintValueMap::const_iterator rhsit =
2432 if (local_dof_indices[j] != global_dof)
2434 vec(local_dof_indices[j]);
2437 max_absolute_error = std::max(max_absolute_error,
2439 max_relative_error = std::max(max_relative_error,
2446 return std::pair<Real, Real>(max_absolute_error, max_relative_error);
2452 std::vector<dof_id_type> & elem_dofs,
2453 const bool called_recursively)
const
2455 LOG_SCOPE_IF(
"build_constraint_matrix()",
"DofMap", !called_recursively);
2458 typedef std::set<dof_id_type> RCSet;
2461 bool we_have_constraints =
false;
2468 for (
const auto & dof : elem_dofs)
2471 we_have_constraints =
true;
2474 DofConstraints::const_iterator
2484 for (
const auto & item : constraint_row)
2485 dof_set.insert (item.first);
2490 if (!we_have_constraints)
2493 for (
const auto & dof : elem_dofs)
2494 dof_set.erase (dof);
2502 if (!dof_set.empty() ||
2503 !called_recursively)
2505 const unsigned int old_size =
2506 cast_int<unsigned int>(elem_dofs.size());
2509 elem_dofs.insert(elem_dofs.end(),
2510 dof_set.begin(), dof_set.end());
2515 cast_int<unsigned int>(elem_dofs.size()));
2518 for (
unsigned int i=0; i != old_size; i++)
2522 DofConstraints::const_iterator
2532 for (
const auto & item : constraint_row)
2533 for (
unsigned int j=0,
2534 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2535 j != n_elem_dofs; j++)
2536 if (elem_dofs[j] == item.first)
2537 C(i,j) = item.second;
2551 if ((C.
n() == Cnew.
m()) &&
2552 (Cnew.
n() == elem_dofs.size()))
2555 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
2563 std::vector<dof_id_type> & elem_dofs,
2565 const bool called_recursively)
const
2567 LOG_SCOPE_IF(
"build_constraint_matrix_and_vector()",
"DofMap", !called_recursively);
2570 typedef std::set<dof_id_type> RCSet;
2573 bool we_have_constraints =
false;
2580 for (
const auto & dof : elem_dofs)
2583 we_have_constraints =
true;
2586 DofConstraints::const_iterator
2596 for (
const auto & item : constraint_row)
2597 dof_set.insert (item.first);
2602 if (!we_have_constraints)
2605 for (
const auto & dof : elem_dofs)
2606 dof_set.erase (dof);
2614 if (!dof_set.empty() ||
2615 !called_recursively)
2622 const AdjointDofConstraintValues::const_iterator
2625 rhs_values = &it->second;
2628 const unsigned int old_size =
2629 cast_int<unsigned int>(elem_dofs.size());
2632 elem_dofs.insert(elem_dofs.end(),
2633 dof_set.begin(), dof_set.end());
2638 cast_int<unsigned int>(elem_dofs.size()));
2642 for (
unsigned int i=0; i != old_size; i++)
2646 DofConstraints::const_iterator
2656 for (
const auto & item : constraint_row)
2657 for (
unsigned int j=0,
2658 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2659 j != n_elem_dofs; j++)
2660 if (elem_dofs[j] == item.first)
2661 C(i,j) = item.second;
2665 DofConstraintValueMap::const_iterator rhsit =
2666 rhs_values->find(elem_dofs[i]);
2667 if (rhsit != rhs_values->end())
2668 H(i) = rhsit->second;
2685 if ((C.
n() == Cnew.
m()) &&
2686 (Cnew.
n() == elem_dofs.size()))
2695 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
2703 parallel_object_only();
2712 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2714 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
2716 this->
comm().max(has_constraints);
2717 if (!has_constraints)
2722 const unsigned int max_qoi_num =
2730 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
2732 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2733 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
2736 const unsigned int sys_num = this->
sys_number();
2742 const unsigned short n_nodes = elem->n_nodes();
2755 const unsigned int n_vars = elem->n_vars(sys_num);
2756 for (
unsigned int v=0; v !=
n_vars; ++v)
2758 const unsigned int n_comp = elem->n_comp(sys_num,v);
2759 for (
unsigned int c=0; c != n_comp; ++c)
2761 const unsigned int id =
2762 elem->dof_number(sys_num,v,c);
2764 pushed_ids[elem->processor_id()].insert(
id);
2769 for (
unsigned short n = 0; n !=
n_nodes; ++n)
2771 const Node & node = elem->node_ref(n);
2773 for (
unsigned int v=0; v !=
n_vars; ++v)
2775 const unsigned int n_comp = node.
n_comp(sys_num,v);
2776 for (
unsigned int c=0; c != n_comp; ++c)
2778 const unsigned int id =
2781 pushed_ids[elem->processor_id()].insert(
id);
2786 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2787 for (
unsigned short n = 0; n !=
n_nodes; ++n)
2789 pushed_node_ids[elem->processor_id()].insert(elem->node_id(n));
2795 std::map<processor_id_type, std::vector<dof_id_type>>
2796 pushed_id_vecs, received_id_vecs;
2797 for (
auto & p : pushed_ids)
2798 pushed_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2800 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2801 pushed_keys_vals, received_keys_vals;
2802 std::map<processor_id_type, std::vector<std::vector<Number>>> pushed_rhss, received_rhss;
2803 for (
auto & p : pushed_id_vecs)
2805 auto & keys_vals = pushed_keys_vals[p.first];
2806 keys_vals.reserve(p.second.
size());
2808 auto & rhss = pushed_rhss[p.first];
2809 rhss.reserve(p.second.
size());
2810 for (
auto & pushed_id : p.second)
2813 keys_vals.emplace_back(row.begin(), row.end());
2815 rhss.push_back(std::vector<Number>(max_qoi_num+1));
2816 std::vector<Number> & rhs = rhss.back();
2817 DofConstraintValueMap::const_iterator rhsit =
2822 for (
unsigned int q = 0; q != max_qoi_num; ++q)
2824 AdjointDofConstraintValues::const_iterator adjoint_map_it =
2831 adjoint_map_it->second;
2833 DofConstraintValueMap::const_iterator adj_rhsit =
2834 constraint_map.find(pushed_id);
2837 (adj_rhsit == constraint_map.end()) ?
2838 0 : adj_rhsit->second;
2843 auto ids_action_functor =
2844 [& received_id_vecs]
2846 const std::vector<dof_id_type> &
data)
2848 received_id_vecs[pid] =
data;
2851 Parallel::push_parallel_vector_data
2852 (this->
comm(), pushed_id_vecs, ids_action_functor);
2854 auto keys_vals_action_functor =
2855 [& received_keys_vals]
2857 const std::vector<std::vector<std::pair<dof_id_type,Real>>> &
data)
2859 received_keys_vals[pid] =
data;
2862 Parallel::push_parallel_vector_data
2863 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
2865 auto rhss_action_functor =
2868 const std::vector<std::vector<Number>> &
data)
2870 received_rhss[pid] =
data;
2873 Parallel::push_parallel_vector_data
2874 (this->
comm(), pushed_rhss, rhss_action_functor);
2879 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
2880 std::map<processor_id_type, std::vector<dof_id_type>>
2881 pushed_node_id_vecs, received_node_id_vecs;
2882 for (
auto & p : pushed_node_ids)
2883 pushed_node_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2885 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2886 pushed_node_keys_vals, received_node_keys_vals;
2887 std::map<processor_id_type, std::vector<Point>> pushed_offsets, received_offsets;
2889 for (
auto & p : pushed_node_id_vecs)
2891 auto & node_keys_vals = pushed_node_keys_vals[p.first];
2892 node_keys_vals.reserve(p.second.
size());
2894 auto & offsets = pushed_offsets[p.first];
2895 offsets.reserve(p.second.
size());
2897 for (
auto & pushed_node_id : p.second)
2901 const std::size_t row_size = row.size();
2902 node_keys_vals.push_back
2903 (std::vector<std::pair<dof_id_type,Real>>());
2904 std::vector<std::pair<dof_id_type,Real>> & this_node_kv =
2905 node_keys_vals.back();
2906 this_node_kv.reserve(row_size);
2907 for (
const auto & j : row)
2908 this_node_kv.push_back
2909 (std::make_pair(j.first->id(), j.second));
2915 auto node_ids_action_functor =
2916 [& received_node_id_vecs]
2918 const std::vector<dof_id_type> &
data)
2920 received_node_id_vecs[pid] =
data;
2923 Parallel::push_parallel_vector_data
2924 (this->
comm(), pushed_node_id_vecs, node_ids_action_functor);
2926 auto node_keys_vals_action_functor =
2927 [& received_node_keys_vals]
2929 const std::vector<std::vector<std::pair<dof_id_type,Real>>> &
data)
2931 received_node_keys_vals[pid] =
data;
2934 Parallel::push_parallel_vector_data
2935 (this->
comm(), pushed_node_keys_vals,
2936 node_keys_vals_action_functor);
2938 auto node_offsets_action_functor =
2939 [& received_offsets]
2941 const std::vector<Point> &
data)
2943 received_offsets[pid] =
data;
2946 Parallel::push_parallel_vector_data
2947 (this->
comm(), pushed_offsets, node_offsets_action_functor);
2952 for (
auto & p : received_id_vecs)
2955 const auto & pushed_ids_to_me = p.second;
2958 const auto & pushed_keys_vals_to_me = received_keys_vals.at(pid);
2959 const auto & pushed_rhss_to_me = received_rhss.at(pid);
2961 libmesh_assert_equal_to (pushed_ids_to_me.size(),
2962 pushed_keys_vals_to_me.size());
2963 libmesh_assert_equal_to (pushed_ids_to_me.size(),
2964 pushed_rhss_to_me.size());
2975 for (
auto & kv : pushed_keys_vals_to_me[i])
2977 libmesh_assert_less(kv.first, this->n_dofs());
2978 row[kv.first] = kv.second;
2981 const Number primal_rhs = pushed_rhss_to_me[i][max_qoi_num];
2986 if (primal_rhs !=
Number(0))
2991 for (
unsigned int q = 0; q != max_qoi_num; ++q)
2993 AdjointDofConstraintValues::iterator adjoint_map_it =
2996 const Number adj_rhs = pushed_rhss_to_me[i][q];
3007 adjoint_map_it->second;
3009 if (adj_rhs !=
Number(0))
3010 constraint_map[constrained] = adj_rhs;
3012 constraint_map.erase(constrained);
3018 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3020 for (
auto & p : received_node_id_vecs)
3023 const auto & pushed_node_ids_to_me = p.second;
3026 const auto & pushed_node_keys_vals_to_me = received_node_keys_vals.at(pid);
3027 const auto & pushed_offsets_to_me = received_offsets.at(pid);
3029 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
3030 pushed_node_keys_vals_to_me.size());
3031 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
3032 pushed_offsets_to_me.size());
3036 dof_id_type constrained_id = pushed_node_ids_to_me[i];
3044 for (
auto & kv : pushed_node_keys_vals_to_me[i])
3048 row[key_node] = kv.second;
3054 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3061 typedef std::set<dof_id_type> DoF_RCSet;
3062 DoF_RCSet unexpanded_dofs;
3065 unexpanded_dofs.insert(i.first);
3071 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3072 typedef std::set<const Node *> Node_RCSet;
3073 Node_RCSet unexpanded_nodes;
3076 unexpanded_nodes.insert(i.first);
3080 bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
3081 this->
comm().max(unexpanded_set_nonempty);
3085 Parallel::MessageTag range_tag = this->
comm().get_unique_tag();
3087 while (unexpanded_set_nonempty)
3090 parallel_object_only();
3093 Node_RCSet node_request_set;
3096 std::map<processor_id_type, std::vector<dof_id_type>>
3100 std::map<processor_id_type, dof_id_type> node_ids_on_proc;
3103 for (
const auto & i : unexpanded_nodes)
3106 for (
const auto & j : row)
3108 const Node *
const node = j.first;
3114 !_node_constraints.count(node))
3115 node_request_set.insert(node);
3121 unexpanded_nodes.clear();
3124 for (
const auto & node : node_request_set)
3127 libmesh_assert_less (node->processor_id(), this->
n_processors());
3128 node_ids_on_proc[node->processor_id()]++;
3131 for (
auto pair : node_ids_on_proc)
3132 requested_node_ids[pair.first].reserve(pair.second);
3135 for (
const auto & node : node_request_set)
3136 requested_node_ids[node->processor_id()].push_back(node->id());
3138 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
3141 std::vector<Parallel::Request> packed_range_sends;
3143 auto node_row_gather_functor =
3146 & packed_range_sends,
3149 const std::vector<dof_id_type> & ids,
3150 std::vector<row_datum> &
data)
3158 std::set<const Node *> nodes_requested;
3161 const std::size_t query_size = ids.size();
3163 data.resize(query_size);
3164 for (std::size_t i=0; i != query_size; ++i)
3171 std::size_t row_size = row.size();
3172 data[i].reserve(row_size);
3173 for (
const auto & j : row)
3175 const Node * node = j.first;
3176 data[i].push_back(std::make_pair(node->
id(), j.second));
3182 nodes_requested.insert(node);
3207 packed_range_sends.push_back(Parallel::Request());
3208 this->
comm().send_packed_range
3209 (pid, &
mesh, nodes_requested.begin(), nodes_requested.end(),
3210 packed_range_sends.back(), range_tag);
3214 typedef Point node_rhs_datum;
3216 auto node_rhs_gather_functor =
3220 const std::vector<dof_id_type> & ids,
3221 std::vector<node_rhs_datum> &
data)
3224 const std::size_t query_size = ids.
size();
3226 data.resize(query_size);
3227 for (std::size_t i=0; i != query_size; ++i)
3234 data[i](0) = std::numeric_limits<Real>::quiet_NaN();
3238 auto node_row_action_functor =
3244 const std::vector<dof_id_type> & ids,
3245 const std::vector<row_datum> &
data)
3250 this->
comm().receive_packed_range
3252 (
Node**)
nullptr, range_tag);
3255 const std::size_t query_size = ids.size();
3257 for (std::size_t i=0; i != query_size; ++i)
3263 if (
data[i].empty())
3274 for (
auto & pair :
data[i])
3276 const Node * key_node =
3279 row[key_node] = pair.second;
3283 unexpanded_nodes.insert(constrained_node);
3288 auto node_rhs_action_functor =
3292 const std::vector<dof_id_type> & ids,
3293 const std::vector<node_rhs_datum> &
data)
3296 const std::size_t query_size = ids.size();
3298 for (std::size_t i=0; i != query_size; ++i)
3311 row_datum * node_row_ex =
nullptr;
3312 Parallel::pull_parallel_vector_data
3313 (this->
comm(), requested_node_ids, node_row_gather_functor,
3314 node_row_action_functor, node_row_ex);
3317 node_rhs_datum * node_rhs_ex =
nullptr;
3318 Parallel::pull_parallel_vector_data
3319 (this->
comm(), requested_node_ids, node_rhs_gather_functor,
3320 node_rhs_action_functor, node_rhs_ex);
3322 Parallel::wait(packed_range_sends);
3326 unexpanded_set_nonempty = !unexpanded_nodes.empty();
3327 this->
comm().max(unexpanded_set_nonempty);
3329 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3349 typedef std::set<dof_id_type> RCSet;
3350 RCSet unexpanded_set;
3353 unexpanded_set.insert(i.first);
3355 while (!unexpanded_set.empty())
3356 for (RCSet::iterator i = unexpanded_set.begin();
3357 i != unexpanded_set.end(); )
3360 DofConstraints::iterator
3367 DofConstraintValueMap::iterator rhsit =
3372 std::vector<dof_id_type> constraints_to_expand;
3374 for (
const auto & item : constraint_row)
3375 if (item.first != *i && this->is_constrained_dof(item.first))
3377 unexpanded_set.insert(item.first);
3378 constraints_to_expand.push_back(item.first);
3381 for (
const auto & expandable : constraints_to_expand)
3383 const Real this_coef = constraint_row[expandable];
3385 DofConstraints::const_iterator
3392 for (
const auto & item : subconstraint_row)
3396 constraint_row[item.first] += item.second * this_coef;
3399 DofConstraintValueMap::const_iterator subrhsit =
3402 constraint_rhs += subrhsit->second * this_coef;
3404 constraint_row.erase(expandable);
3409 if (constraint_rhs !=
Number(0))
3416 if (constraint_rhs !=
Number(0))
3417 rhsit->second = constraint_rhs;
3422 if (constraints_to_expand.empty())
3423 i = unexpanded_set.erase(i);
3440 #ifdef LIBMESH_ENABLE_CONSTRAINTS
3450 typedef std::set<dof_id_type> RCSet;
3451 RCSet unexpanded_set;
3457 for (
const auto & i : dof_constraints_copy)
3458 unexpanded_set.insert(i.first);
3460 while (!unexpanded_set.empty())
3461 for (RCSet::iterator i = unexpanded_set.begin();
3462 i != unexpanded_set.end(); )
3465 DofConstraints::iterator
3466 pos = dof_constraints_copy.find(*i);
3478 std::vector<dof_id_type> constraints_to_expand;
3480 for (
const auto & item : constraint_row)
3481 if (item.first != *i && this->is_constrained_dof(item.first))
3483 unexpanded_set.insert(item.first);
3484 constraints_to_expand.push_back(item.first);
3487 for (
const auto & expandable : constraints_to_expand)
3489 const Real this_coef = constraint_row[expandable];
3491 DofConstraints::const_iterator
3492 subpos = dof_constraints_copy.find(expandable);
3498 for (
const auto & item : subconstraint_row)
3500 if (item.first == expandable)
3501 libmesh_error_msg(
"Constraint loop detected");
3503 constraint_row[item.first] += item.second * this_coef;
3512 constraint_row.erase(expandable);
3531 if (constraints_to_expand.empty())
3532 i = unexpanded_set.erase(i);
3553 parallel_object_only();
3562 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3564 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3566 this->
comm().max(has_constraints);
3567 if (!has_constraints)
3572 Parallel::MessageTag range_tag = this->
comm().get_unique_tag();
3574 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3575 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
3576 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3578 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
3585 while (constrained >=
_end_df[constrained_proc_id])
3586 constrained_proc_id++;
3592 for (
auto & j : row)
3597 while (constraining >=
_end_df[constraining_proc_id])
3598 constraining_proc_id++;
3601 constraining_proc_id != constrained_proc_id)
3602 pushed_ids[constraining_proc_id].insert(constrained);
3609 std::vector<std::vector<std::pair<dof_id_type, Real>>>>
3610 pushed_keys_vals, pushed_keys_vals_to_me;
3612 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Number>>>
3613 pushed_ids_rhss, pushed_ids_rhss_to_me;
3622 for (
auto & pid_id_pair : pushed_ids)
3625 const std::set<dof_id_type>
3626 & pid_ids = pid_id_pair.second;
3628 const std::size_t ids_size = pid_ids.size();
3629 std::vector<std::vector<std::pair<dof_id_type, Real>>> &
3630 keys_vals = pushed_keys_vals[pid];
3631 std::vector<std::pair<dof_id_type,Number>> &
3632 ids_rhss = pushed_ids_rhss[pid];
3633 keys_vals.resize(ids_size);
3634 ids_rhss.resize(ids_size);
3637 std::set<dof_id_type>::const_iterator it;
3638 for (push_i = 0, it = pid_ids.begin();
3639 it != pid_ids.end(); ++push_i, ++it)
3643 keys_vals[push_i].assign(row.begin(), row.end());
3645 DofConstraintValueMap::const_iterator rhsit =
3647 ids_rhss[push_i].first = constrained;
3648 ids_rhss[push_i].second =
3657 auto ids_rhss_action_functor =
3658 [& pushed_ids_rhss_to_me]
3660 const std::vector<std::pair<dof_id_type, Number>> &
data)
3662 pushed_ids_rhss_to_me[pid] =
data;
3665 auto keys_vals_action_functor =
3666 [& pushed_keys_vals_to_me]
3668 const std::vector<std::vector<std::pair<dof_id_type, Real>>> &
data)
3670 pushed_keys_vals_to_me[pid] =
data;
3673 Parallel::push_parallel_vector_data
3674 (this->
comm(), pushed_ids_rhss, ids_rhss_action_functor);
3675 Parallel::push_parallel_vector_data
3676 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
3679 auto receive_dof_constraints =
3681 & pushed_ids_rhss_to_me,
3682 & pushed_keys_vals_to_me]
3685 for (
auto & pid_id_pair : pushed_ids_rhss_to_me)
3688 const auto & ids_rhss = pid_id_pair.second;
3689 const auto & keys_vals = pushed_keys_vals_to_me[pid];
3691 libmesh_assert_equal_to
3692 (ids_rhss.size(), keys_vals.size());
3704 for (
auto & key_val : keys_vals[i])
3706 libmesh_assert_less(key_val.first, this->n_dofs());
3707 row[key_val.first] = key_val.second;
3709 if (ids_rhss[i].second !=
Number(0))
3719 receive_dof_constraints();
3721 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3725 const Node * constrained = i.first;
3731 for (
auto & j : row)
3733 const Node * constraining = j.first;
3737 pushed_node_ids[constraining->
processor_id()].insert(constrained->
id());
3743 std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3744 pushed_node_keys_vals, pushed_node_keys_vals_to_me;
3745 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Point>>>
3746 pushed_node_ids_offsets, pushed_node_ids_offsets_to_me;
3747 std::map<processor_id_type, std::set<const Node *>> pushed_nodes;
3749 for (
auto & pid_id_pair : pushed_node_ids)
3752 const std::set<dof_id_type>
3753 & pid_ids = pid_id_pair.second;
3755 const std::size_t ids_size = pid_ids.size();
3756 std::vector<std::vector<std::pair<dof_id_type,Real>>> &
3757 keys_vals = pushed_node_keys_vals[pid];
3758 std::vector<std::pair<dof_id_type, Point>> &
3759 ids_offsets = pushed_node_ids_offsets[pid];
3760 keys_vals.resize(ids_size);
3761 ids_offsets.resize(ids_size);
3762 std::set<const Node *> & nodes = pushed_nodes[pid];
3765 std::set<dof_id_type>::const_iterator it;
3766 for (push_i = 0, it = pid_ids.begin();
3767 it != pid_ids.end(); ++push_i, ++it)
3772 nodes.insert(constrained);
3775 std::size_t row_size = row.size();
3776 keys_vals[push_i].reserve(row_size);
3777 for (
const auto & j : row)
3779 const Node * constraining = j.first;
3781 keys_vals[push_i].push_back
3782 (std::make_pair(constraining->
id(), j.second));
3785 nodes.insert(constraining);
3788 ids_offsets[push_i].first = *it;
3793 auto node_ids_offsets_action_functor =
3794 [& pushed_node_ids_offsets_to_me]
3796 const std::vector<std::pair<dof_id_type, Point>> &
data)
3798 pushed_node_ids_offsets_to_me[pid] =
data;
3801 auto node_keys_vals_action_functor =
3802 [& pushed_node_keys_vals_to_me]
3804 const std::vector<std::vector<std::pair<dof_id_type, Real>>> &
data)
3806 pushed_node_keys_vals_to_me[pid] =
data;
3810 Parallel::push_parallel_vector_data
3811 (this->
comm(), pushed_node_ids_offsets, node_ids_offsets_action_functor);
3812 Parallel::push_parallel_vector_data
3813 (this->
comm(), pushed_node_keys_vals, node_keys_vals_action_functor);
3817 std::vector<Parallel::Request> send_requests;
3820 for (
auto & pid_id_pair : pushed_node_ids_offsets)
3823 send_requests.push_back(Parallel::Request());
3824 this->
comm().send_packed_range
3826 pushed_nodes[pid].begin(), pushed_nodes[pid].
end(),
3827 send_requests.back(), range_tag);
3831 for (
auto & pid_id_pair : pushed_node_ids_offsets_to_me)
3834 const auto & ids_offsets = pid_id_pair.second;
3835 const auto & keys_vals = pushed_node_keys_vals_to_me[pid];
3837 libmesh_assert_equal_to
3838 (ids_offsets.size(), keys_vals.size());
3841 this->
comm().receive_packed_range
3843 (
Node**)
nullptr, range_tag);
3848 dof_id_type constrained_id = ids_offsets[i].first;
3856 for (
auto & key_val : keys_vals[i])
3859 row[key_node] = key_val.second;
3862 ids_offsets[i].second;
3867 Parallel::wait(send_requests);
3869 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3882 typedef std::map<dof_id_type, std::set<dof_id_type>> DofConstrainsMap;
3883 DofConstrainsMap dof_id_constrains;
3889 for (
const auto & j : row)
3894 while (constraining >=
_end_df[constraining_proc_id])
3895 constraining_proc_id++;
3898 dof_id_constrains[constraining].insert(constrained);
3909 std::vector<dof_id_type> my_dof_indices;
3912 for (
const auto & dof : my_dof_indices)
3914 DofConstrainsMap::const_iterator dcmi = dof_id_constrains.find(dof);
3915 if (dcmi != dof_id_constrains.end())
3917 for (
const auto & constrained : dcmi->second)
3920 while (constrained >=
_end_df[the_constrained_proc_id])
3921 the_constrained_proc_id++;
3924 if (elemproc != the_constrained_proc_id)
3925 pushed_ids[elemproc].insert(constrained);
3931 pushed_ids_rhss.clear();
3932 pushed_ids_rhss_to_me.clear();
3933 pushed_keys_vals.clear();
3934 pushed_keys_vals_to_me.clear();
3939 Parallel::push_parallel_vector_data
3940 (this->
comm(), pushed_ids_rhss, ids_rhss_action_functor);
3941 Parallel::push_parallel_vector_data
3942 (this->
comm(), pushed_keys_vals, keys_vals_action_functor);
3944 receive_dof_constraints();
3955 std::set<CouplingMatrix*> temporary_coupling_matrices;
3958 (elements_to_couple,
3959 temporary_coupling_matrices,
3967 std::set<dof_id_type> requested_dofs;
3969 for (
const auto & pr : elements_to_couple)
3971 const Elem * elem = pr.first;
3974 std::vector<dof_id_type> element_dofs;
3977 for (
auto dof : element_dofs)
3978 requested_dofs.insert(dof);
3986 std::set<dof_id_type> & unexpanded_dofs,
3989 typedef std::set<dof_id_type> DoF_RCSet;
3993 const unsigned int max_qoi_num =
3999 bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
4000 this->
comm().max(unexpanded_set_nonempty);
4002 while (unexpanded_set_nonempty)
4005 parallel_object_only();
4008 DoF_RCSet dof_request_set;
4011 std::map<processor_id_type, std::vector<dof_id_type>>
4015 std::map<processor_id_type, dof_id_type>
4019 for (
const auto & unexpanded_dof : unexpanded_dofs)
4021 DofConstraints::const_iterator
4030 dof_request_set.insert(unexpanded_dof);
4038 for (
const auto & j : row)
4046 dof_request_set.insert(constraining_dof);
4052 unexpanded_dofs.clear();
4056 for (
const auto & i : dof_request_set)
4060 dof_ids_on_proc[proc_id]++;
4063 for (
auto & pair : dof_ids_on_proc)
4065 requested_dof_ids[pair.first].reserve(pair.second);
4070 for (
const auto & i : dof_request_set)
4074 requested_dof_ids[proc_id].push_back(i);
4077 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
4079 typedef std::vector<Number> rhss_datum;
4081 auto row_gather_functor =
4084 const std::vector<dof_id_type> & ids,
4085 std::vector<row_datum> &
data)
4088 const std::size_t query_size = ids.size();
4090 data.resize(query_size);
4091 for (std::size_t i=0; i != query_size; ++i)
4097 std::size_t row_size = row.size();
4098 data[i].reserve(row_size);
4099 for (
const auto & j : row)
4101 data[i].push_back(j);
4130 auto rhss_gather_functor =
4134 const std::vector<dof_id_type> & ids,
4135 std::vector<rhss_datum> &
data)
4138 const std::size_t query_size = ids.size();
4140 data.resize(query_size);
4141 for (std::size_t i=0; i != query_size; ++i)
4147 DofConstraintValueMap::const_iterator rhsit =
4153 for (
unsigned int q = 0; q != max_qoi_num; ++q)
4155 AdjointDofConstraintValues::const_iterator adjoint_map_it =
4160 data[i].push_back(0);
4165 adjoint_map_it->second;
4167 DofConstraintValueMap::const_iterator adj_rhsit =
4168 constraint_map.find(constrained);
4170 ((adj_rhsit == constraint_map.end()) ?
4171 0 : adj_rhsit->second);
4177 auto row_action_functor =
4181 const std::vector<dof_id_type> & ids,
4182 const std::vector<row_datum> &
data)
4185 const std::size_t query_size = ids.size();
4187 for (std::size_t i=0; i != query_size; ++i)
4193 if (
data[i].empty())
4202 for (
auto & pair :
data[i])
4204 libmesh_assert_less(pair.first, this->n_dofs());
4205 row[pair.first] = pair.second;
4209 unexpanded_dofs.insert(constrained);
4214 auto rhss_action_functor =
4218 const std::vector<dof_id_type> & ids,
4219 const std::vector<rhss_datum> &
data)
4222 const std::size_t query_size = ids.size();
4224 for (std::size_t i=0; i != query_size; ++i)
4226 if (!
data[i].empty())
4234 for (
unsigned int q = 0; q != max_qoi_num; ++q)
4236 AdjointDofConstraintValues::iterator adjoint_map_it =
4248 adjoint_map_it->second;
4251 constraint_map[constrained] =
4254 constraint_map.erase(constrained);
4262 row_datum * row_ex =
nullptr;
4263 Parallel::pull_parallel_vector_data
4264 (this->
comm(), requested_dof_ids, row_gather_functor,
4265 row_action_functor, row_ex);
4268 rhss_datum * rhs_ex =
nullptr;
4269 Parallel::pull_parallel_vector_data
4270 (this->
comm(), requested_dof_ids, rhss_gather_functor,
4271 rhss_action_functor, rhs_ex);
4275 unexpanded_set_nonempty = !unexpanded_dofs.empty();
4276 this->
comm().max(unexpanded_set_nonempty);
4283 parallel_object_only();
4292 this->
comm().max(has_constraints);
4293 if (!has_constraints)
4305 for (
const auto & j : constraint_row)
4320 #endif // LIBMESH_ENABLE_CONSTRAINTS
4323 #ifdef LIBMESH_ENABLE_AMR
4333 libmesh_assert_greater (elem->
p_level(), p);
4334 libmesh_assert_less (s, elem->
n_sides());
4336 const unsigned int sys_num = this->
sys_number();
4337 const unsigned int dim = elem->
dim();
4341 low_p_fe_type.
order = static_cast<Order>(low_p_fe_type.
order + p);
4342 high_p_fe_type.
order = static_cast<Order>(high_p_fe_type.
order +
4346 for (
unsigned int n = 0; n !=
n_nodes; ++n)
4350 const unsigned int low_nc =
4352 const unsigned int high_nc =
4364 for (
unsigned int i = low_nc; i != high_nc; ++i)
4372 const unsigned int total_dofs = node.
n_comp(sys_num, var);
4373 libmesh_assert_greater_equal (total_dofs, high_nc);
4376 for (
unsigned int j = low_nc; j != high_nc; ++j)
4378 const unsigned int i = total_dofs - j - 1;
4386 #endif // LIBMESH_ENABLE_AMR
4389 #ifdef LIBMESH_ENABLE_DIRICHLET
4397 unsigned int qoi_index)
4399 unsigned int old_size = cast_int<unsigned int>
4401 for (
unsigned int i = old_size; i <= qoi_index; ++i)
4429 unsigned int old_size = cast_int<unsigned int>
4431 for (
unsigned int i = old_size; i <= q; ++i)
4442 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
4454 unsigned int qoi_index)
4460 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
4475 for (
auto & item : *
this)
4483 const std::set<boundary_id_type>& dbc_bcids = boundary.
b;
4488 for (
const auto & bc_id : dbc_bcids)
4493 bool found_bcid = (mesh_bcids.find(bc_id) != mesh_bcids.end());
4501 libmesh_error_msg(
"Could not find Dirichlet boundary id " << bc_id <<
" in mesh!");
4505 #endif // LIBMESH_ENABLE_DIRICHLET
4508 #ifdef LIBMESH_ENABLE_PERIODIC
4515 if (existing_boundary ==
nullptr)
4528 existing_boundary->
merge(periodic_boundary);
4533 inverse_boundary->
merge(periodic_boundary);