65 class ComputeConstraints
70 #ifdef LIBMESH_ENABLE_PERIODIC
74 const unsigned int variable_number) :
75 _constraints(constraints),
77 #ifdef LIBMESH_ENABLE_PERIODIC
78 _periodic_boundaries(periodic_boundaries),
81 _variable_number(variable_number)
86 const Variable & var_description = _dof_map.variable(_variable_number);
88 #ifdef LIBMESH_ENABLE_PERIODIC 89 std::unique_ptr<PointLocatorBase> point_locator;
90 const bool have_periodic_boundaries =
91 !_periodic_boundaries.empty();
92 if (have_periodic_boundaries && !range.
empty())
93 point_locator = _mesh.sub_point_locator();
96 for (
const auto & elem : range)
99 #ifdef LIBMESH_ENABLE_AMR 100 FEInterface::compute_constraints (_constraints,
105 #ifdef LIBMESH_ENABLE_PERIODIC 109 if (have_periodic_boundaries)
110 FEInterface::compute_periodic_constraints (_constraints,
112 _periodic_boundaries,
124 #ifdef LIBMESH_ENABLE_PERIODIC 128 const unsigned int _variable_number;
133 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 134 class ComputeNodeConstraints
138 #ifdef LIBMESH_ENABLE_PERIODIC
142 _node_constraints(node_constraints),
143 #ifdef LIBMESH_ENABLE_PERIODIC
144 _periodic_boundaries(periodic_boundaries),
151 #ifdef LIBMESH_ENABLE_PERIODIC 152 std::unique_ptr<PointLocatorBase> point_locator;
153 bool have_periodic_boundaries = !_periodic_boundaries.empty();
154 if (have_periodic_boundaries && !range.
empty())
155 point_locator = _mesh.sub_point_locator();
158 for (
const auto & elem : range)
160 #ifdef LIBMESH_ENABLE_AMR 161 FEBase::compute_node_constraints (_node_constraints, elem);
163 #ifdef LIBMESH_ENABLE_PERIODIC 167 if (have_periodic_boundaries)
168 FEBase::compute_periodic_node_constraints (_node_constraints,
169 _periodic_boundaries,
179 #ifdef LIBMESH_ENABLE_PERIODIC 184 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 187 #ifdef LIBMESH_ENABLE_DIRICHLET 198 AddConstraint(
DofMap & dof_map_in) : dof_map(dof_map_in) {}
202 const Number constraint_rhs)
const = 0;
205 class AddPrimalConstraint :
public AddConstraint
208 AddPrimalConstraint(
DofMap & dof_map_in) : AddConstraint(dof_map_in) {}
212 const Number constraint_rhs)
const 214 if (!dof_map.is_constrained_dof(dof_number))
215 dof_map.add_constraint_row (dof_number, constraint_row,
216 constraint_rhs,
true);
220 class AddAdjointConstraint :
public AddConstraint
223 const unsigned int qoi_index;
226 AddAdjointConstraint(
DofMap & dof_map_in,
unsigned int qoi_index_in)
227 : AddConstraint(dof_map_in), qoi_index(qoi_index_in) {}
231 const Number constraint_rhs)
const 233 dof_map.add_adjoint_constraint_row
234 (qoi_index, dof_number, constraint_row, constraint_rhs,
246 class ConstrainDirichlet
254 const AddConstraint & add_fn;
268 return std::numeric_limits<Real>::quiet_NaN();
285 return std::numeric_limits<Number>::quiet_NaN();
290 template<
typename OutputType>
292 const unsigned int var,
294 const FEType & fe_type)
const 296 typedef OutputType OutputShape;
311 const std::set<boundary_id_type> & b = dirichlet.
b;
314 libmesh_assert(f || f_fem);
315 libmesh_assert(!(f && f_fem));
318 libmesh_assert(!(f && f_system));
319 libmesh_assert(!(f_fem && !f_system));
336 unsigned int n_vec_dim = FEInterface::n_vec_dim(
mesh, fe_type);
338 const unsigned int var_component =
351 const std::vector<std::vector<OutputShape>> & phi = fe->get_phi();
355 const std::vector<std::vector<OutputGradient>> * dphi =
nullptr;
362 libmesh_assert(g || g_fem);
366 libmesh_assert(!(g && g_fem));
367 libmesh_assert(!(f && g_fem));
368 libmesh_assert(!(f_fem && g));
370 const std::vector<std::vector<OutputGradient>> & ref_dphi = fe->get_dphi();
375 const std::vector<Real> & JxW = fe->get_JxW();
378 const std::vector<Point> & xyz_values = fe->get_xyz();
381 std::vector<dof_id_type> dof_indices;
383 std::vector<unsigned int> side_dofs;
388 std::unique_ptr<FEMContext> context;
391 libmesh_assert(f_system);
394 context = libmesh_make_unique<FEMContext>(*f_system);
402 for (
const auto & elem : range)
414 const unsigned short n_sides = elem->n_sides();
415 const unsigned short n_edges = elem->n_edges();
416 const unsigned short n_nodes = elem->n_nodes();
420 std::vector<bool> is_boundary_node(
n_nodes,
false),
421 is_boundary_edge(n_edges,
false),
422 is_boundary_side(n_sides,
false),
423 is_boundary_shellface(2,
false);
426 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
430 bool has_dirichlet_constraint =
false;
434 std::vector<boundary_id_type> ids_vec;
436 for (
unsigned char s = 0; s != n_sides; ++s)
441 bool do_this_side =
false;
442 for (
const auto &
bc_id : ids_vec)
451 is_boundary_side[s] =
true;
452 has_dirichlet_constraint =
true;
455 for (
unsigned int n = 0; n !=
n_nodes; ++n)
456 if (elem->is_node_on_side(n,s))
457 is_boundary_node[n] =
true;
458 for (
unsigned int e = 0; e != n_edges; ++e)
459 if (elem->is_edge_on_side(e,s))
460 is_boundary_edge[e] =
true;
465 for (
unsigned int n=0; n !=
n_nodes; ++n)
467 boundary_info.
boundary_ids (elem->node_ptr(n), ids_vec);
469 for (
const auto &
bc_id : ids_vec)
472 is_boundary_node[n] =
true;
473 is_boundary_nodeset[n] =
true;
474 has_dirichlet_constraint =
true;
480 for (
unsigned short e=0; e != n_edges; ++e)
484 for (
const auto &
bc_id : ids_vec)
487 is_boundary_edge[e] =
true;
488 has_dirichlet_constraint =
true;
494 for (
unsigned short shellface=0; shellface != 2; ++shellface)
498 for (
const auto &
bc_id : ids_vec)
501 is_boundary_shellface[shellface] =
true;
502 has_dirichlet_constraint =
true;
506 if(!has_dirichlet_constraint)
523 if (f_system && context.get())
524 context->pre_fe_reinit(*f_system, elem);
531 const unsigned int n_dofs =
532 cast_int<unsigned int>(dof_indices.size());
535 std::vector<char> dof_is_fixed(n_dofs,
false);
536 std::vector<int> free_dof(n_dofs, 0);
539 const ElemType elem_type = elem->type();
554 unsigned int current_dof = 0;
555 for (
unsigned int n=0; n!=
n_nodes; ++n)
559 const unsigned int nc =
560 FEInterface::n_dofs_at_node (dim, fe_type, elem_type,
562 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
563 !is_boundary_nodeset[n])
570 libmesh_assert_equal_to (nc, 0);
576 libmesh_assert_equal_to (nc, n_vec_dim);
577 for (
unsigned int c = 0; c < n_vec_dim; c++)
580 f_component(f, f_fem, context.get(), var_component+c,
581 elem->point(n), time);
582 dof_is_fixed[current_dof+c] =
true;
584 current_dof += n_vec_dim;
590 f_component(f, f_fem, context.get(), var_component,
591 elem->point(n), time);
592 dof_is_fixed[current_dof] =
true;
595 g_component(g, g_fem, context.get(), var_component,
596 elem->point(n), time);
598 Ue(current_dof) = grad(0);
599 dof_is_fixed[current_dof] =
true;
604 Point nxminus = elem->point(n),
605 nxplus = elem->point(n);
609 g_component(g, g_fem, context.get(), var_component,
612 g_component(g, g_fem, context.get(), var_component,
615 Ue(current_dof) = grad(1);
616 dof_is_fixed[current_dof] =
true;
619 Ue(current_dof) = (gxplus(1) - gxminus(1))
621 dof_is_fixed[current_dof] =
true;
627 Ue(current_dof) = grad(2);
628 dof_is_fixed[current_dof] =
true;
631 Ue(current_dof) = (gxplus(2) - gxminus(2))
633 dof_is_fixed[current_dof] =
true;
636 Point nyminus = elem->point(n),
637 nyplus = elem->point(n);
641 g_component(g, g_fem, context.get(), var_component,
644 g_component(g, g_fem, context.get(), var_component,
647 Ue(current_dof) = (gyplus(2) - gyminus(2))
649 dof_is_fixed[current_dof] =
true;
652 Point nxmym = elem->point(n),
653 nxmyp = elem->point(n),
654 nxpym = elem->point(n),
655 nxpyp = elem->point(n);
665 g_component(g, g_fem, context.get(), var_component,
668 g_component(g, g_fem, context.get(), var_component,
671 g_component(g, g_fem, context.get(), var_component,
674 g_component(g, g_fem, context.get(), var_component,
676 Number gxzplus = (gxpyp(2) - gxmyp(2))
678 Number gxzminus = (gxpym(2) - gxmym(2))
681 Ue(current_dof) = (gxzplus - gxzminus)
683 dof_is_fixed[current_dof] =
true;
691 else if (cont ==
C_ONE)
693 libmesh_assert_equal_to (nc, 1 + dim);
695 f_component(f, f_fem, context.get(), var_component,
696 elem->point(n), time);
697 dof_is_fixed[current_dof] =
true;
700 g_component(g, g_fem, context.get(), var_component,
701 elem->point(n), time);
702 for (
unsigned int i=0; i!= dim; ++i)
704 Ue(current_dof) = grad(i);
705 dof_is_fixed[current_dof] =
true;
710 libmesh_error_msg(
"Unknown continuity cont = " << cont);
715 for (
unsigned int e=0; e != n_edges; ++e)
717 if (!is_boundary_edge[e])
720 FEInterface::dofs_on_edge(elem, dim, fe_type, e,
723 const unsigned int n_side_dofs =
724 cast_int<unsigned int>(side_dofs.size());
728 unsigned int free_dofs = 0;
729 for (
unsigned int i=0; i != n_side_dofs; ++i)
730 if (!dof_is_fixed[side_dofs[i]])
731 free_dof[free_dofs++] = i;
743 fe->attach_quadrature_rule (qedgerule.get());
744 fe->edge_reinit (elem, e);
745 const unsigned int n_qp = qedgerule->n_points();
748 for (
unsigned int qp=0; qp<n_qp; qp++)
751 OutputNumber fineval(0);
754 for (
unsigned int c = 0; c < n_vec_dim; c++)
756 f_component(f, f_fem, context.get(), var_component+c,
757 xyz_values[qp], time);
760 OutputNumberGradient finegrad;
764 switch( FEInterface::field_type( fe_type ) )
777 libmesh_error_msg(
"Unknown field type!");
781 for (
unsigned int c = 0; c < n_vec_dim; c++)
782 for (
unsigned int d = 0; d < g_rank; d++)
783 g_accessor(c + d*dim ) =
784 g_component(g, g_fem, context.get(), var_component,
785 xyz_values[qp], time)(c);
788 for (
unsigned int sidei=0, freei=0; sidei != n_side_dofs; ++sidei)
790 unsigned int i = side_dofs[sidei];
794 for (
unsigned int sidej=0, freej=0; sidej != n_side_dofs; ++sidej)
796 unsigned int j = side_dofs[sidej];
798 Fe(freei) -= phi[i][qp] * phi[j][qp] *
801 Ke(freei,freej) += phi[i][qp] *
802 phi[j][qp] * JxW[qp];
806 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp]) ) *
809 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
812 if (!dof_is_fixed[j])
815 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
817 Fe(freei) += (finegrad.contract( (*dphi)[i][qp]) ) *
826 for (
unsigned int i=0; i != free_dofs; ++i)
828 Number & ui = Ue(side_dofs[free_dof[i]]);
832 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
838 for (
unsigned int s=0; s != n_sides; ++s)
840 if (!is_boundary_side[s])
843 FEInterface::dofs_on_side(elem, dim, fe_type, s,
846 const unsigned int n_side_dofs =
847 cast_int<unsigned int>(side_dofs.size());
851 unsigned int free_dofs = 0;
852 for (
unsigned int i=0; i != n_side_dofs; ++i)
853 if (!dof_is_fixed[side_dofs[i]])
854 free_dof[free_dofs++] = i;
866 fe->attach_quadrature_rule (qsiderule.get());
867 fe->reinit (elem, s);
868 const unsigned int n_qp = qsiderule->n_points();
871 for (
unsigned int qp=0; qp<n_qp; qp++)
874 OutputNumber fineval(0);
877 for (
unsigned int c = 0; c < n_vec_dim; c++)
879 f_component(f, f_fem, context.get(), var_component+c,
880 xyz_values[qp], time);
883 OutputNumberGradient finegrad;
887 switch( FEInterface::field_type( fe_type ) )
900 libmesh_error_msg(
"Unknown field type!");
904 for (
unsigned int c = 0; c < n_vec_dim; c++)
905 for (
unsigned int d = 0; d < g_rank; d++)
906 g_accessor(c + d*dim ) =
907 g_component(g, g_fem, context.get(), var_component,
908 xyz_values[qp], time)(c);
911 for (
unsigned int sidei=0, freei=0; sidei != n_side_dofs; ++sidei)
913 unsigned int i = side_dofs[sidei];
917 for (
unsigned int sidej=0, freej=0; sidej != n_side_dofs; ++sidej)
919 unsigned int j = side_dofs[sidej];
921 Fe(freei) -= phi[i][qp] * phi[j][qp] *
924 Ke(freei,freej) += phi[i][qp] *
925 phi[j][qp] * JxW[qp];
929 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
932 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
935 if (!dof_is_fixed[j])
938 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
940 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
949 for (
unsigned int i=0; i != free_dofs; ++i)
951 Number & ui = Ue(side_dofs[free_dof[i]]);
955 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
961 for (
unsigned int shellface=0; shellface != 2; ++shellface)
963 if (!is_boundary_shellface[shellface])
967 std::vector<unsigned int> shellface_dofs(n_dofs);
968 std::iota(shellface_dofs.begin(), shellface_dofs.end(), 0);
972 unsigned int free_dofs = 0;
973 for (
unsigned int i=0; i != n_dofs; ++i)
974 if (!dof_is_fixed[shellface_dofs[i]])
975 free_dof[free_dofs++] = i;
987 fe->attach_quadrature_rule (qrule.get());
989 const unsigned int n_qp = qrule->n_points();
992 for (
unsigned int qp=0; qp<n_qp; qp++)
995 OutputNumber fineval(0);
998 for (
unsigned int c = 0; c < n_vec_dim; c++)
1000 f_component(f, f_fem, context.get(), var_component+c,
1001 xyz_values[qp], time);
1004 OutputNumberGradient finegrad;
1007 unsigned int g_rank;
1008 switch( FEInterface::field_type( fe_type ) )
1021 libmesh_error_msg(
"Unknown field type!");
1025 for (
unsigned int c = 0; c < n_vec_dim; c++)
1026 for (
unsigned int d = 0; d < g_rank; d++)
1027 g_accessor(c + d*dim ) =
1028 g_component(g, g_fem, context.get(), var_component,
1029 xyz_values[qp], time)(c);
1032 for (
unsigned int shellfacei=0, freei=0;
1033 shellfacei != n_dofs; ++shellfacei)
1035 unsigned int i = shellface_dofs[shellfacei];
1037 if (dof_is_fixed[i])
1039 for (
unsigned int shellfacej=0, freej=0;
1040 shellfacej != n_dofs; ++shellfacej)
1042 unsigned int j = shellface_dofs[shellfacej];
1043 if (dof_is_fixed[j])
1044 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1047 Ke(freei,freej) += phi[i][qp] *
1048 phi[j][qp] * JxW[qp];
1051 if (dof_is_fixed[j])
1052 Fe(freei) -= ((*dphi)[i][qp].contract((*dphi)[j][qp])) *
1055 Ke(freei,freej) += ((*dphi)[i][qp].contract((*dphi)[j][qp]))
1058 if (!dof_is_fixed[j])
1061 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1063 Fe(freei) += (finegrad.contract((*dphi)[i][qp])) *
1072 for (
unsigned int i=0; i != free_dofs; ++i)
1074 Number & ui = Ue(shellface_dofs[free_dof[i]]);
1078 dof_is_fixed[shellface_dofs[free_dof[i]]] =
true;
1086 for (
unsigned int i = 0; i < n_dofs; i++)
1090 add_fn (dof_indices[i], empty_row, Ue(i));
1098 ConstrainDirichlet (
DofMap & dof_map_in,
1102 const AddConstraint & add_in) :
1103 dof_map(dof_map_in),
1106 dirichlet(dirichlet_in),
1109 ConstrainDirichlet (
const ConstrainDirichlet & in) :
1110 dof_map(in.dof_map),
1113 dirichlet(in.dirichlet),
1114 add_fn(in.add_fn) { }
1125 for (
const auto & var : dirichlet.
variables)
1134 switch( FEInterface::field_type( fe_type ) )
1138 this->apply_dirichlet_impl<Real>( range, var, variable, fe_type );
1143 this->apply_dirichlet_impl<RealGradient>( range, var, variable, fe_type );
1147 libmesh_error_msg(
"Unknown field type!");
1156 #endif // LIBMESH_ENABLE_DIRICHLET 1169 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1174 parallel_object_only();
1176 dof_id_type nc_dofs = this->n_local_constrained_dofs();
1177 this->comm().sum(nc_dofs);
1184 const DofConstraints::const_iterator lower =
1185 _dof_constraints.lower_bound(this->first_dof()),
1187 _dof_constraints.upper_bound(this->end_dof()-1);
1189 return cast_int<dof_id_type>(std::distance(lower, upper));
1196 parallel_object_only();
1198 LOG_SCOPE(
"create_dof_constraints()",
"DofMap");
1211 const bool possible_local_constraints =
false 1213 #ifdef LIBMESH_ENABLE_AMR 1216 #ifdef LIBMESH_ENABLE_PERIODIC 1217 || !_periodic_boundaries->empty()
1219 #ifdef LIBMESH_ENABLE_DIRICHLET 1220 || !_dirichlet_boundaries->empty()
1225 bool possible_global_constraints = possible_local_constraints;
1226 #if defined(LIBMESH_ENABLE_PERIODIC) || defined(LIBMESH_ENABLE_DIRICHLET) || defined(LIBMESH_ENABLE_AMR) 1229 this->comm().max(possible_global_constraints);
1232 if (!possible_global_constraints)
1236 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1237 _dof_constraints.clear();
1238 _stashed_dof_constraints.clear();
1239 _primal_constraint_values.clear();
1240 _adjoint_constraint_values.clear();
1242 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1243 _node_constraints.clear();
1267 #ifdef LIBMESH_ENABLE_PERIODIC 1268 bool need_point_locator = !_periodic_boundaries->
empty() && !range.
empty();
1270 this->comm().max(need_point_locator);
1272 if (need_point_locator)
1276 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1278 _node_constraints.clear();
1281 ComputeNodeConstraints (_node_constraints,
1282 #ifdef LIBMESH_ENABLE_PERIODIC
1283 *_periodic_boundaries,
1286 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 1290 _dof_constraints.clear();
1291 _stashed_dof_constraints.clear();
1292 _primal_constraint_values.clear();
1293 _adjoint_constraint_values.clear();
1297 for (
unsigned int variable_number=0; variable_number<this->n_variables();
1298 ++variable_number, range.
reset())
1300 ComputeConstraints (_dof_constraints,
1302 #ifdef LIBMESH_ENABLE_PERIODIC
1303 *_periodic_boundaries,
1308 #ifdef LIBMESH_ENABLE_DIRICHLET 1309 for (DirichletBoundaries::iterator
1310 i = _dirichlet_boundaries->begin();
1311 i != _dirichlet_boundaries->end(); ++i, range.
reset())
1315 this->check_dirichlet_bcid_consistency(
mesh,**i);
1319 ConstrainDirichlet(*
this,
mesh, time, **i,
1320 AddPrimalConstraint(*
this))
1324 for (
unsigned int qoi_index = 0,
1325 n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
1326 qoi_index != n_qois; ++qoi_index)
1328 for (DirichletBoundaries::iterator
1329 i = _adjoint_dirichlet_boundaries[qoi_index]->begin();
1330 i != _adjoint_dirichlet_boundaries[qoi_index]->end();
1335 this->check_dirichlet_bcid_consistency(
mesh,**i);
1339 ConstrainDirichlet(*
this,
mesh, time, **i,
1340 AddAdjointConstraint(*
this, qoi_index))
1345 #endif // LIBMESH_ENABLE_DIRICHLET 1352 const Number constraint_rhs,
1353 const bool forbid_constraint_overwrite)
1356 if (forbid_constraint_overwrite)
1357 if (this->is_constrained_dof(dof_number))
1358 libmesh_error_msg(
"ERROR: DOF " << dof_number <<
" was already constrained!");
1361 std::pair<DofConstraints::iterator, bool> it =
1362 _dof_constraints.insert(std::make_pair(dof_number, constraint_row));
1364 it.first->second = constraint_row;
1366 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1367 _primal_constraint_values.insert(std::make_pair(dof_number, constraint_rhs));
1369 rhs_it.first->second = constraint_rhs;
1373 void DofMap::add_adjoint_constraint_row (
const unsigned int qoi_index,
1376 const Number constraint_rhs,
1377 const bool forbid_constraint_overwrite)
1380 if (forbid_constraint_overwrite)
1382 if (!this->is_constrained_dof(dof_number))
1383 libmesh_error_msg(
"ERROR: DOF " << dof_number <<
" has no corresponding primal constraint!");
1408 std::pair<DofConstraintValueMap::iterator, bool> rhs_it =
1409 _adjoint_constraint_values[qoi_index].insert(std::make_pair(dof_number,
1412 rhs_it.first->second = constraint_rhs;
1418 void DofMap::print_dof_constraints(std::ostream & os,
1419 bool print_nonlocal)
const 1421 parallel_object_only();
1423 std::string local_constraints =
1424 this->get_local_constraints(print_nonlocal);
1426 if (this->processor_id())
1428 this->comm().send(0, local_constraints);
1432 os <<
"Processor 0:\n";
1433 os << local_constraints;
1437 this->comm().receive(p, local_constraints);
1438 os <<
"Processor " << p <<
":\n";
1439 os << local_constraints;
1444 std::string DofMap::get_local_constraints(
bool print_nonlocal)
const 1446 std::ostringstream os;
1447 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 1453 os <<
"Node Constraints:" 1456 for (
const auto & pr : _node_constraints)
1458 const Node * node = pr.first;
1461 if (!print_nonlocal &&
1466 const Point & offset = pr.second.second;
1468 os <<
"Constraints for Node id " << node->
id()
1471 for (
const auto & item : row)
1472 os <<
" (" << item.first->id() <<
"," << item.second <<
")\t";
1474 os <<
"rhs: " << offset;
1478 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 1485 os <<
"DoF Constraints:" 1488 for (
const auto & pr : _dof_constraints)
1493 if (!print_nonlocal && !this->local_index(i))
1497 DofConstraintValueMap::const_iterator rhsit =
1498 _primal_constraint_values.find(i);
1499 const Number rhs = (rhsit == _primal_constraint_values.end()) ?
1502 os <<
"Constraints for DoF " << i
1505 for (
const auto & item : row)
1506 os <<
" (" << item.first <<
"," << item.second <<
")\t";
1508 os <<
"rhs: " << rhs;
1512 for (
unsigned int qoi_index = 0,
1513 n_qois = cast_int<unsigned int>(_adjoint_dirichlet_boundaries.size());
1514 qoi_index != n_qois; ++qoi_index)
1516 os <<
"Adjoint " << qoi_index <<
" DoF rhs values:" 1519 AdjointDofConstraintValues::const_iterator adjoint_map_it =
1520 _adjoint_constraint_values.find(qoi_index);
1522 if (adjoint_map_it != _adjoint_constraint_values.end())
1523 for (
const auto & pr : adjoint_map_it->second)
1528 if (!print_nonlocal && !this->local_index(i))
1531 const Number rhs = pr.second;
1533 os <<
"RHS for DoF " << i
1546 std::vector<dof_id_type> & elem_dofs,
1547 bool asymmetric_constraint_rows)
const 1549 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1550 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1553 if (this->_dof_constraints.empty())
1560 this->build_constraint_matrix (C, elem_dofs);
1562 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
1565 if ((C.
m() == matrix.
m()) &&
1566 (C.
n() == elem_dofs.size()))
1573 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1574 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1575 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1578 for (
unsigned int i=0,
1579 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1580 i != n_elem_dofs; i++)
1582 if (this->is_constrained_dof(elem_dofs[i]))
1584 for (
unsigned int j=0; j<matrix.
n(); j++)
1589 if (asymmetric_constraint_rows)
1591 DofConstraints::const_iterator
1592 pos = _dof_constraints.find(elem_dofs[i]);
1594 libmesh_assert (pos != _dof_constraints.end());
1604 for (
const auto & item : constraint_row)
1605 for (
unsigned int j=0; j != n_elem_dofs; j++)
1606 if (elem_dofs[j] == item.first)
1607 matrix(i,j) = -item.second;
1617 std::vector<dof_id_type> & elem_dofs,
1618 bool asymmetric_constraint_rows)
const 1620 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1621 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1622 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1625 if (this->_dof_constraints.empty())
1632 this->build_constraint_matrix (C, elem_dofs);
1634 LOG_SCOPE(
"cnstrn_elem_mat_vec()",
"DofMap");
1637 if ((C.
m() == matrix.
m()) &&
1638 (C.
n() == elem_dofs.size()))
1645 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1646 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1647 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1650 for (
unsigned int i=0,
1651 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1652 i != n_elem_dofs; i++)
1653 if (this->is_constrained_dof(elem_dofs[i]))
1655 for (
unsigned int j=0; j<matrix.
n(); j++)
1664 if (asymmetric_constraint_rows)
1666 DofConstraints::const_iterator
1667 pos = _dof_constraints.find(elem_dofs[i]);
1669 libmesh_assert (pos != _dof_constraints.end());
1676 for (
const auto & item : constraint_row)
1677 for (
unsigned int j=0; j != n_elem_dofs; j++)
1678 if (elem_dofs[j] == item.first)
1679 matrix(i,j) = -item.second;
1696 std::vector<dof_id_type> & elem_dofs,
1697 bool asymmetric_constraint_rows,
1698 int qoi_index)
const 1700 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1701 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1702 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1705 if (this->_dof_constraints.empty())
1713 this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
1715 LOG_SCOPE(
"hetero_cnstrn_elem_mat_vec()",
"DofMap");
1718 if ((C.
m() == matrix.
m()) &&
1719 (C.
n() == elem_dofs.size()))
1724 rhs_values = &_primal_constraint_values;
1727 const AdjointDofConstraintValues::const_iterator
1728 it = _adjoint_constraint_values.find(qoi_index);
1729 if (it != _adjoint_constraint_values.end())
1730 rhs_values = &it->second;
1746 libmesh_assert_equal_to (matrix.
m(), matrix.
n());
1747 libmesh_assert_equal_to (matrix.
m(), elem_dofs.size());
1748 libmesh_assert_equal_to (matrix.
n(), elem_dofs.size());
1750 for (
unsigned int i=0,
1751 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1752 i != n_elem_dofs; i++)
1756 if (this->is_constrained_dof(
dof_id))
1758 for (
unsigned int j=0; j<matrix.
n(); j++)
1767 if (asymmetric_constraint_rows)
1769 DofConstraints::const_iterator
1770 pos = _dof_constraints.find(
dof_id);
1772 libmesh_assert (pos != _dof_constraints.end());
1776 for (
const auto & item : constraint_row)
1777 for (
unsigned int j=0; j != n_elem_dofs; j++)
1778 if (elem_dofs[j] == item.first)
1779 matrix(i,j) = -item.second;
1783 const DofConstraintValueMap::const_iterator valpos =
1784 rhs_values->find(
dof_id);
1786 rhs(i) = (valpos == rhs_values->end()) ?
1802 std::vector<dof_id_type> & elem_dofs,
1803 bool asymmetric_constraint_rows,
1804 int qoi_index)
const 1806 libmesh_assert_equal_to (elem_dofs.size(), matrix.
m());
1807 libmesh_assert_equal_to (elem_dofs.size(), matrix.
n());
1808 libmesh_assert_equal_to (elem_dofs.size(), rhs.
size());
1811 if (this->_dof_constraints.empty())
1819 this->build_constraint_matrix_and_vector (C, H, elem_dofs, qoi_index);
1821 LOG_SCOPE(
"hetero_cnstrn_elem_vec()",
"DofMap");
1824 if ((C.
m() == matrix.
m()) &&
1825 (C.
n() == elem_dofs.size()))
1830 rhs_values = &_primal_constraint_values;
1833 const AdjointDofConstraintValues::const_iterator
1834 it = _adjoint_constraint_values.find(qoi_index);
1835 if (it != _adjoint_constraint_values.end())
1836 rhs_values = &it->second;
1848 for (
unsigned int i=0,
1849 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
1850 i != n_elem_dofs; i++)
1854 if (this->is_constrained_dof(
dof_id))
1859 if (asymmetric_constraint_rows && rhs_values)
1861 const DofConstraintValueMap::const_iterator valpos =
1862 rhs_values->find(
dof_id);
1864 rhs(i) = (valpos == rhs_values->end()) ?
1879 std::vector<dof_id_type> & row_dofs,
1880 std::vector<dof_id_type> & col_dofs,
1881 bool asymmetric_constraint_rows)
const 1883 libmesh_assert_equal_to (row_dofs.size(), matrix.
m());
1884 libmesh_assert_equal_to (col_dofs.size(), matrix.
n());
1887 if (this->_dof_constraints.empty())
1897 std::vector<dof_id_type> orig_row_dofs(row_dofs);
1898 std::vector<dof_id_type> orig_col_dofs(col_dofs);
1900 this->build_constraint_matrix (R, orig_row_dofs);
1901 this->build_constraint_matrix (C, orig_col_dofs);
1903 LOG_SCOPE(
"constrain_elem_matrix()",
"DofMap");
1905 row_dofs = orig_row_dofs;
1906 col_dofs = orig_col_dofs;
1908 bool constraint_found =
false;
1912 if ((R.
m() == matrix.
m()) &&
1913 (R.
n() == row_dofs.size()))
1916 constraint_found =
true;
1919 if ((C.
m() == matrix.
n()) &&
1920 (C.
n() == col_dofs.size()))
1923 constraint_found =
true;
1927 if (constraint_found)
1929 libmesh_assert_equal_to (matrix.
m(), row_dofs.size());
1930 libmesh_assert_equal_to (matrix.
n(), col_dofs.size());
1933 for (
unsigned int i=0,
1934 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
1935 i != n_row_dofs; i++)
1936 if (this->is_constrained_dof(row_dofs[i]))
1938 for (
unsigned int j=0; j<matrix.
n(); j++)
1940 if (row_dofs[i] != col_dofs[j])
1946 if (asymmetric_constraint_rows)
1948 DofConstraints::const_iterator
1949 pos = _dof_constraints.find(row_dofs[i]);
1951 libmesh_assert (pos != _dof_constraints.end());
1955 libmesh_assert (!constraint_row.empty());
1957 for (
const auto & item : constraint_row)
1958 for (
unsigned int j=0,
1959 n_col_dofs = cast_int<unsigned int>(col_dofs.size());
1960 j != n_col_dofs; j++)
1961 if (col_dofs[j] == item.first)
1962 matrix(i,j) = -item.second;
1971 std::vector<dof_id_type> & row_dofs,
1974 libmesh_assert_equal_to (rhs.
size(), row_dofs.size());
1977 if (this->_dof_constraints.empty())
1983 this->build_constraint_matrix (R, row_dofs);
1985 LOG_SCOPE(
"constrain_elem_vector()",
"DofMap");
1988 if ((R.
m() == rhs.
size()) &&
1989 (R.
n() == row_dofs.size()))
1995 libmesh_assert_equal_to (row_dofs.size(), rhs.
size());
1997 for (
unsigned int i=0,
1998 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
1999 i != n_row_dofs; i++)
2000 if (this->is_constrained_dof(row_dofs[i]))
2003 libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
2014 std::vector<dof_id_type> & row_dofs,
2017 libmesh_assert_equal_to (v.
size(), row_dofs.size());
2018 libmesh_assert_equal_to (w.
size(), row_dofs.size());
2021 if (this->_dof_constraints.empty())
2027 this->build_constraint_matrix (R, row_dofs);
2029 LOG_SCOPE(
"cnstrn_elem_dyad_mat()",
"DofMap");
2032 if ((R.
m() == v.
size()) &&
2033 (R.
n() == row_dofs.size()))
2043 libmesh_assert_equal_to (row_dofs.size(), v.
size());
2044 libmesh_assert_equal_to (row_dofs.size(), w.
size());
2048 for (
unsigned int i=0,
2049 n_row_dofs = cast_int<unsigned int>(row_dofs.size());
2050 i != n_row_dofs; i++)
2051 if (this->is_constrained_dof(row_dofs[i]))
2054 libmesh_assert (_dof_constraints.find(row_dofs[i]) != _dof_constraints.end());
2063 void DofMap::constrain_nothing (std::vector<dof_id_type> & dofs)
const 2066 if (this->_dof_constraints.empty())
2072 this->build_constraint_matrix (R, dofs);
2077 void DofMap::enforce_constraints_exactly (
const System & system,
2079 bool homogeneous)
const 2081 parallel_object_only();
2083 if (!this->n_constrained_dofs())
2086 LOG_SCOPE(
"enforce_constraints_exactly()",
"DofMap");
2093 std::unique_ptr<NumericVector<Number>> v_built;
2097 v_built->init(this->n_dofs(), this->n_local_dofs(),
true,
PARALLEL);
2101 i<v_built->last_local_index(); i++)
2102 v_built->set(i, (*v)(i));
2104 v_global = v_built.
get();
2107 libmesh_assert (v_local->
closed());
2115 v_local = v_built.
get();
2125 libmesh_error_msg(
"ERROR: Unknown v->type() == " << v->
type());
2130 libmesh_assert(v_local);
2131 libmesh_assert(v_global);
2132 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2134 for (
const auto & pr : _dof_constraints)
2137 if (!this->local_index(constrained_dof))
2145 DofConstraintValueMap::const_iterator rhsit =
2146 _primal_constraint_values.find(constrained_dof);
2147 if (rhsit != _primal_constraint_values.end())
2148 exact_value = rhsit->second;
2150 for (
const auto & j : constraint_row)
2151 exact_value += j.second * (*v_local)(j.first);
2153 v_global->
set(constrained_dof, exact_value);
2171 unsigned int q)
const 2173 parallel_object_only();
2175 if (!this->n_constrained_dofs())
2178 LOG_SCOPE(
"enforce_adjoint_constraints_exactly()",
"DofMap");
2182 std::unique_ptr<NumericVector<Number>> v_built;
2186 v_built->init(this->n_dofs(), this->n_local_dofs(),
true,
PARALLEL);
2190 i<v_built->last_local_index(); i++)
2191 v_built->set(i, v(i));
2193 v_global = v_built.
get();
2196 libmesh_assert (v_local->
closed());
2204 v_local = v_built.
get();
2214 libmesh_error_msg(
"ERROR: Unknown v.type() == " << v.
type());
2219 libmesh_assert(v_local);
2220 libmesh_assert(v_global);
2223 const AdjointDofConstraintValues::const_iterator
2224 adjoint_constraint_map_it = _adjoint_constraint_values.find(q);
2226 (adjoint_constraint_map_it == _adjoint_constraint_values.end()) ?
2227 nullptr : &adjoint_constraint_map_it->second;
2229 for (
const auto & pr : _dof_constraints)
2232 if (!this->local_index(constrained_dof))
2240 const DofConstraintValueMap::const_iterator
2241 adjoint_constraint_it =
2242 constraint_map->find(constrained_dof);
2243 if (adjoint_constraint_it != constraint_map->end())
2244 exact_value = adjoint_constraint_it->second;
2247 for (
const auto & j : constraint_row)
2248 exact_value += j.second * (*v_local)(j.first);
2250 v_global->
set(constrained_dof, exact_value);
2267 std::pair<Real, Real>
2268 DofMap::max_constraint_error (
const System & system,
2276 libmesh_assert (vec.
closed());
2278 Real max_absolute_error = 0., max_relative_error = 0.;
2282 libmesh_assert_equal_to (
this, &(system.
get_dof_map()));
2285 std::vector<dof_id_type> local_dof_indices;
2289 this->dof_indices(elem, local_dof_indices);
2290 std::vector<dof_id_type> raw_dof_indices = local_dof_indices;
2295 this->build_constraint_matrix (C, local_dof_indices);
2301 libmesh_assert_equal_to (C.
m(), raw_dof_indices.size());
2302 libmesh_assert_equal_to (C.
n(), local_dof_indices.size());
2304 for (
unsigned int i=0; i!=C.
m(); ++i)
2308 if (this->is_constrained_dof(global_dof) &&
2313 DofConstraints::const_iterator
2314 pos = _dof_constraints.find(global_dof);
2316 libmesh_assert (pos != _dof_constraints.end());
2320 DofConstraintValueMap::const_iterator rhsit =
2321 _primal_constraint_values.find(global_dof);
2322 if (rhsit != _primal_constraint_values.end())
2323 exact_value = rhsit->second;
2325 for (
unsigned int j=0; j!=C.
n(); ++j)
2327 if (local_dof_indices[j] != global_dof)
2328 exact_value += C(i,j) *
2329 vec(local_dof_indices[j]);
2332 max_absolute_error =
std::max(max_absolute_error,
2333 std::abs(vec(global_dof) - exact_value));
2334 max_relative_error =
std::max(max_relative_error,
2335 std::abs(vec(global_dof) - exact_value)
2341 return std::pair<Real, Real>(max_absolute_error, max_relative_error);
2347 std::vector<dof_id_type> & elem_dofs,
2348 const bool called_recursively)
const 2350 LOG_SCOPE_IF(
"build_constraint_matrix()",
"DofMap", !called_recursively);
2353 typedef std::set<dof_id_type> RCSet;
2356 bool we_have_constraints =
false;
2363 for (
const auto & dof : elem_dofs)
2364 if (this->is_constrained_dof(dof))
2366 we_have_constraints =
true;
2369 DofConstraints::const_iterator
2370 pos = _dof_constraints.find(dof);
2372 libmesh_assert (pos != _dof_constraints.end());
2379 for (
const auto & item : constraint_row)
2380 dof_set.insert (item.first);
2385 if (!we_have_constraints)
2388 for (
const auto & dof : elem_dofs)
2389 dof_set.erase (dof);
2397 if (!dof_set.empty() ||
2398 !called_recursively)
2400 const unsigned int old_size =
2401 cast_int<unsigned int>(elem_dofs.size());
2404 elem_dofs.insert(elem_dofs.end(),
2405 dof_set.begin(), dof_set.end());
2410 cast_int<unsigned int>(elem_dofs.size()));
2413 for (
unsigned int i=0; i != old_size; i++)
2414 if (this->is_constrained_dof(elem_dofs[i]))
2417 DofConstraints::const_iterator
2418 pos = _dof_constraints.find(elem_dofs[i]);
2420 libmesh_assert (pos != _dof_constraints.end());
2427 for (
const auto & item : constraint_row)
2428 for (
unsigned int j=0,
2429 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2430 j != n_elem_dofs; j++)
2431 if (elem_dofs[j] == item.first)
2432 C(i,j) = item.second;
2444 this->build_constraint_matrix (Cnew, elem_dofs,
true);
2446 if ((C.
n() == Cnew.
m()) &&
2447 (Cnew.
n() == elem_dofs.size()))
2450 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
2458 std::vector<dof_id_type> & elem_dofs,
2460 const bool called_recursively)
const 2462 LOG_SCOPE_IF(
"build_constraint_matrix_and_vector()",
"DofMap", !called_recursively);
2465 typedef std::set<dof_id_type> RCSet;
2468 bool we_have_constraints =
false;
2475 for (
const auto & dof : elem_dofs)
2476 if (this->is_constrained_dof(dof))
2478 we_have_constraints =
true;
2481 DofConstraints::const_iterator
2482 pos = _dof_constraints.find(dof);
2484 libmesh_assert (pos != _dof_constraints.end());
2491 for (
const auto & item : constraint_row)
2492 dof_set.insert (item.first);
2497 if (!we_have_constraints)
2500 for (
const auto & dof : elem_dofs)
2501 dof_set.erase (dof);
2509 if (!dof_set.empty() ||
2510 !called_recursively)
2514 rhs_values = &_primal_constraint_values;
2517 const AdjointDofConstraintValues::const_iterator
2518 it = _adjoint_constraint_values.find(qoi_index);
2519 if (it != _adjoint_constraint_values.end())
2520 rhs_values = &it->second;
2523 const unsigned int old_size =
2524 cast_int<unsigned int>(elem_dofs.size());
2527 elem_dofs.insert(elem_dofs.end(),
2528 dof_set.begin(), dof_set.end());
2533 cast_int<unsigned int>(elem_dofs.size()));
2537 for (
unsigned int i=0; i != old_size; i++)
2538 if (this->is_constrained_dof(elem_dofs[i]))
2541 DofConstraints::const_iterator
2542 pos = _dof_constraints.find(elem_dofs[i]);
2544 libmesh_assert (pos != _dof_constraints.end());
2551 for (
const auto & item : constraint_row)
2552 for (
unsigned int j=0,
2553 n_elem_dofs = cast_int<unsigned int>(elem_dofs.size());
2554 j != n_elem_dofs; j++)
2555 if (elem_dofs[j] == item.first)
2556 C(i,j) = item.second;
2560 DofConstraintValueMap::const_iterator rhsit =
2561 rhs_values->find(elem_dofs[i]);
2562 if (rhsit != rhs_values->end())
2563 H(i) = rhsit->second;
2577 this->build_constraint_matrix_and_vector (Cnew, Hnew, elem_dofs,
2580 if ((C.
n() == Cnew.
m()) &&
2581 (Cnew.
n() == elem_dofs.size()))
2590 libmesh_assert_equal_to (C.
n(), elem_dofs.size());
2598 parallel_object_only();
2601 if (this->n_processors() == 1)
2606 unsigned int has_constraints = !_dof_constraints.empty()
2607 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2608 || !_node_constraints.empty()
2609 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 2611 this->comm().max(has_constraints);
2612 if (!has_constraints)
2617 const unsigned int max_qoi_num =
2618 _adjoint_constraint_values.empty() ?
2619 0 : _adjoint_constraint_values.rbegin()->first;
2625 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
2627 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2628 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
2631 const unsigned int sys_num = this->sys_number();
2637 const unsigned short n_nodes = elem->n_nodes();
2650 const unsigned int n_vars = elem->n_vars(sys_num);
2651 for (
unsigned int v=0; v !=
n_vars; ++v)
2653 const unsigned int n_comp = elem->n_comp(sys_num,v);
2654 for (
unsigned int c=0; c != n_comp; ++c)
2656 const unsigned int id =
2657 elem->dof_number(sys_num,v,c);
2658 if (this->is_constrained_dof(
id))
2659 pushed_ids[elem->processor_id()].insert(
id);
2664 for (
unsigned short n = 0; n !=
n_nodes; ++n)
2666 const Node & node = elem->node_ref(n);
2668 for (
unsigned int v=0; v !=
n_vars; ++v)
2670 const unsigned int n_comp = node.
n_comp(sys_num,v);
2671 for (
unsigned int c=0; c != n_comp; ++c)
2673 const unsigned int id =
2675 if (this->is_constrained_dof(
id))
2676 pushed_ids[elem->processor_id()].insert(
id);
2681 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2682 for (
unsigned short n = 0; n !=
n_nodes; ++n)
2683 if (this->is_constrained_node(elem->node_ptr(n)))
2684 pushed_node_ids[elem->processor_id()].insert(elem->node_id(n));
2690 std::map<processor_id_type, std::vector<dof_id_type>>
2691 pushed_id_vecs, received_id_vecs;
2692 for (
auto & p : pushed_ids)
2693 pushed_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2695 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2696 pushed_keys_vals, received_keys_vals;
2697 std::map<processor_id_type, std::vector<std::vector<Number>>> pushed_rhss, received_rhss;
2698 for (
auto & p : pushed_id_vecs)
2700 auto & keys_vals = pushed_keys_vals[p.first];
2701 keys_vals.reserve(p.second.
size());
2703 auto & rhss = pushed_rhss[p.first];
2704 rhss.reserve(p.second.
size());
2705 for (
auto & pushed_id : p.second)
2708 keys_vals.emplace_back(row.begin(), row.end());
2710 rhss.push_back(std::vector<Number>(max_qoi_num+1));
2711 std::vector<Number> & rhs = rhss.back();
2712 DofConstraintValueMap::const_iterator rhsit =
2713 _primal_constraint_values.find(pushed_id);
2715 (rhsit == _primal_constraint_values.end()) ?
2717 for (
unsigned int q = 0; q != max_qoi_num; ++q)
2719 AdjointDofConstraintValues::const_iterator adjoint_map_it =
2720 _adjoint_constraint_values.find(q);
2722 if (adjoint_map_it == _adjoint_constraint_values.end())
2726 adjoint_map_it->second;
2728 DofConstraintValueMap::const_iterator adj_rhsit =
2729 constraint_map.find(pushed_id);
2732 (adj_rhsit == constraint_map.end()) ?
2733 0 : adj_rhsit->second;
2738 auto ids_action_functor =
2739 [& received_id_vecs]
2741 const std::vector<dof_id_type> &
data)
2743 received_id_vecs[pid] =
data;
2747 (this->comm(), pushed_id_vecs, ids_action_functor);
2749 auto keys_vals_action_functor =
2750 [& received_keys_vals]
2752 const std::vector<std::vector<std::pair<dof_id_type,Real>>> &
data)
2754 received_keys_vals[pid] =
data;
2758 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
2760 auto rhss_action_functor =
2763 const std::vector<std::vector<Number>> &
data)
2765 received_rhss[pid] =
data;
2769 (this->comm(), pushed_rhss, rhss_action_functor);
2774 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2775 std::map<processor_id_type, std::vector<dof_id_type>>
2776 pushed_node_id_vecs, received_node_id_vecs;
2777 for (
auto & p : pushed_node_ids)
2778 pushed_node_id_vecs[p.first].assign(p.second.begin(), p.second.end());
2780 std::map<processor_id_type, std::vector<std::vector<std::pair<dof_id_type,Real>>>>
2781 pushed_node_keys_vals, received_node_keys_vals;
2782 std::map<processor_id_type, std::vector<Point>> pushed_offsets, received_offsets;
2784 for (
auto & p : pushed_node_id_vecs)
2786 auto & node_keys_vals = pushed_node_keys_vals[p.first];
2787 node_keys_vals.reserve(p.second.
size());
2789 auto & offsets = pushed_offsets[p.first];
2790 offsets.reserve(p.second.
size());
2792 for (
auto & pushed_node_id : p.second)
2796 const std::size_t row_size = row.
size();
2797 node_keys_vals.push_back
2798 (std::vector<std::pair<dof_id_type,Real>>());
2799 std::vector<std::pair<dof_id_type,Real>> & this_node_kv =
2800 node_keys_vals.back();
2801 this_node_kv.reserve(row_size);
2802 for (
const auto & j : row)
2803 this_node_kv.push_back
2804 (std::make_pair(j.first->id(), j.second));
2806 offsets.push_back(_node_constraints[node].second);
2810 auto node_ids_action_functor =
2811 [& received_node_id_vecs]
2813 const std::vector<dof_id_type> &
data)
2815 received_node_id_vecs[pid] =
data;
2819 (this->comm(), pushed_node_id_vecs, node_ids_action_functor);
2821 auto node_keys_vals_action_functor =
2822 [& received_node_keys_vals]
2824 const std::vector<std::vector<std::pair<dof_id_type,Real>>> &
data)
2826 received_node_keys_vals[pid] =
data;
2830 (this->comm(), pushed_node_keys_vals,
2831 node_keys_vals_action_functor);
2833 auto node_offsets_action_functor =
2834 [& received_offsets]
2836 const std::vector<Point> &
data)
2838 received_offsets[pid] =
data;
2842 (this->comm(), pushed_offsets, node_offsets_action_functor);
2847 for (
auto & p : received_id_vecs)
2850 const auto & pushed_ids_to_me = p.second;
2851 libmesh_assert(received_keys_vals.count(pid));
2852 libmesh_assert(received_rhss.count(pid));
2853 const auto & pushed_keys_vals_to_me = received_keys_vals.at(pid);
2854 const auto & pushed_rhss_to_me = received_rhss.at(pid);
2856 libmesh_assert_equal_to (pushed_ids_to_me.size(),
2857 pushed_keys_vals_to_me.size());
2858 libmesh_assert_equal_to (pushed_ids_to_me.size(),
2859 pushed_rhss_to_me.size());
2867 if (!this->is_constrained_dof(constrained))
2870 for (
auto & kv : pushed_keys_vals_to_me[i])
2871 row[kv.first] = kv.second;
2873 const Number primal_rhs = pushed_rhss_to_me[i][max_qoi_num];
2876 libmesh_assert(pushed_keys_vals_to_me[i].empty());
2878 if (primal_rhs !=
Number(0))
2879 _primal_constraint_values[constrained] = primal_rhs;
2881 _primal_constraint_values.erase(constrained);
2883 for (
unsigned int q = 0; q != max_qoi_num; ++q)
2885 AdjointDofConstraintValues::iterator adjoint_map_it =
2886 _adjoint_constraint_values.find(q);
2888 const Number adj_rhs = pushed_rhss_to_me[i][q];
2890 if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
2894 if (adjoint_map_it == _adjoint_constraint_values.end())
2895 adjoint_map_it = _adjoint_constraint_values.insert
2899 adjoint_map_it->second;
2901 if (adj_rhs !=
Number(0))
2902 constraint_map[constrained] = adj_rhs;
2904 constraint_map.erase(constrained);
2910 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2912 for (
auto & p : received_node_id_vecs)
2915 const auto & pushed_node_ids_to_me = p.second;
2916 libmesh_assert(received_node_keys_vals.count(pid));
2917 libmesh_assert(received_offsets.count(pid));
2918 const auto & pushed_node_keys_vals_to_me = received_node_keys_vals.at(pid);
2919 const auto & pushed_offsets_to_me = received_offsets.at(pid);
2921 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
2922 pushed_node_keys_vals_to_me.size());
2923 libmesh_assert_equal_to (pushed_node_ids_to_me.size(),
2924 pushed_offsets_to_me.size());
2928 dof_id_type constrained_id = pushed_node_ids_to_me[i];
2933 if (!this->is_constrained_node(constrained))
2936 for (
auto & kv : pushed_node_keys_vals_to_me[i])
2939 libmesh_assert(key_node);
2940 row[key_node] = kv.second;
2942 _node_constraints[constrained].second = pushed_offsets_to_me[i];
2946 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 2953 typedef std::set<dof_id_type> DoF_RCSet;
2954 DoF_RCSet unexpanded_dofs;
2956 for (
const auto & i : _dof_constraints)
2957 unexpanded_dofs.insert(i.first);
2960 this->gather_constraints(
mesh, unexpanded_dofs,
false);
2963 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 2964 typedef std::set<const Node *> Node_RCSet;
2965 Node_RCSet unexpanded_nodes;
2967 for (
const auto & i : _node_constraints)
2968 unexpanded_nodes.insert(i.first);
2972 bool unexpanded_set_nonempty = !unexpanded_nodes.empty();
2973 this->comm().max(unexpanded_set_nonempty);
2979 while (unexpanded_set_nonempty)
2982 parallel_object_only();
2985 Node_RCSet node_request_set;
2988 std::map<processor_id_type, std::vector<dof_id_type>>
2992 std::map<processor_id_type, dof_id_type> node_ids_on_proc;
2995 for (
const auto & i : unexpanded_nodes)
2998 for (
const auto & j : row)
3000 const Node *
const node = j.first;
3001 libmesh_assert(node);
3006 !_node_constraints.count(node))
3007 node_request_set.insert(node);
3013 unexpanded_nodes.clear();
3016 for (
const auto & node : node_request_set)
3018 libmesh_assert(node);
3019 libmesh_assert_less (node->processor_id(), this->n_processors());
3020 node_ids_on_proc[node->processor_id()]++;
3024 if (node_ids_on_proc.count(p))
3025 requested_node_ids[p].reserve(node_ids_on_proc[p]);
3028 for (
const auto & node : node_request_set)
3029 requested_node_ids[node->processor_id()].push_back(node->id());
3031 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
3034 std::vector<Parallel::Request> packed_range_sends;
3036 auto node_row_gather_functor =
3039 & packed_range_sends,
3042 const std::vector<dof_id_type> & ids,
3043 std::vector<row_datum> &
data)
3051 std::set<const Node *> nodes_requested;
3054 const std::size_t query_size = ids.size();
3056 data.resize(query_size);
3057 for (std::size_t i=0; i != query_size; ++i)
3061 if (_node_constraints.count(constrained_node))
3064 std::size_t row_size = row.
size();
3065 data[i].reserve(row_size);
3066 for (
const auto & j : row)
3068 const Node * node = j.first;
3069 data[i].push_back(std::make_pair(node->
id(), j.second));
3075 nodes_requested.insert(node);
3091 (std::make_pair(DofObject::invalid_id,
Real(0)));
3101 this->comm().send_packed_range
3102 (pid, &
mesh, nodes_requested.begin(), nodes_requested.end(),
3103 packed_range_sends.back(), range_tag);
3107 typedef Point node_rhs_datum;
3109 auto node_rhs_gather_functor =
3113 const std::vector<dof_id_type> & ids,
3114 std::vector<node_rhs_datum> &
data)
3117 const std::size_t query_size = ids.
size();
3119 data.resize(query_size);
3120 for (std::size_t i=0; i != query_size; ++i)
3124 if (_node_constraints.count(constrained_node))
3125 data[i] = _node_constraints[constrained_node].second;
3127 data[i](0) = std::numeric_limits<Real>::quiet_NaN();
3131 auto node_row_action_functor =
3137 const std::vector<dof_id_type> & ids,
3138 const std::vector<row_datum> &
data)
3143 this->comm().receive_packed_range
3145 (
Node**)
nullptr, range_tag);
3148 const std::size_t query_size = ids.size();
3150 for (std::size_t i=0; i != query_size; ++i)
3156 if (
data[i].empty())
3162 else if (
data[i][0].first != DofObject::invalid_id)
3167 for (
auto & pair :
data[i])
3169 const Node * key_node =
3171 libmesh_assert(key_node);
3172 row[key_node] = pair.second;
3176 unexpanded_nodes.insert(constrained_node);
3181 auto node_rhs_action_functor =
3185 const std::vector<dof_id_type> & ids,
3186 const std::vector<node_rhs_datum> &
data)
3189 const std::size_t query_size = ids.size();
3191 for (std::size_t i=0; i != query_size; ++i)
3197 _node_constraints[constrained_node].second =
data[i];
3199 _node_constraints.erase(constrained_node);
3204 row_datum * node_row_ex =
nullptr;
3206 (this->comm(), requested_node_ids, node_row_gather_functor,
3207 node_row_action_functor, node_row_ex);
3210 node_rhs_datum * node_rhs_ex =
nullptr;
3212 (this->comm(), requested_node_ids, node_rhs_gather_functor,
3213 node_rhs_action_functor, node_rhs_ex);
3219 unexpanded_set_nonempty = !unexpanded_nodes.empty();
3220 this->comm().max(unexpanded_set_nonempty);
3222 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 3231 this->allgather_recursive_constraints(
mesh);
3233 if(_error_on_cyclic_constraint)
3238 check_for_cyclic_constraints();
3242 typedef std::set<dof_id_type> RCSet;
3243 RCSet unexpanded_set;
3245 for (
const auto & i : _dof_constraints)
3246 unexpanded_set.insert(i.first);
3248 while (!unexpanded_set.empty())
3249 for (RCSet::iterator i = unexpanded_set.begin();
3250 i != unexpanded_set.end(); )
3253 DofConstraints::iterator
3254 pos = _dof_constraints.find(*i);
3256 libmesh_assert (pos != _dof_constraints.end());
3260 DofConstraintValueMap::iterator rhsit =
3261 _primal_constraint_values.find(*i);
3262 Number constraint_rhs = (rhsit == _primal_constraint_values.end()) ?
3265 std::vector<dof_id_type> constraints_to_expand;
3267 for (
const auto & item : constraint_row)
3268 if (item.first != *i && this->is_constrained_dof(item.first))
3270 unexpanded_set.insert(item.first);
3271 constraints_to_expand.push_back(item.first);
3274 for (
const auto & expandable : constraints_to_expand)
3276 const Real this_coef = constraint_row[expandable];
3278 DofConstraints::const_iterator
3279 subpos = _dof_constraints.find(expandable);
3281 libmesh_assert (subpos != _dof_constraints.end());
3285 for (
const auto & item : subconstraint_row)
3288 libmesh_assert(item.first != expandable);
3289 constraint_row[item.first] += item.second * this_coef;
3292 DofConstraintValueMap::const_iterator subrhsit =
3293 _primal_constraint_values.find(expandable);
3294 if (subrhsit != _primal_constraint_values.end())
3295 constraint_rhs += subrhsit->second * this_coef;
3297 constraint_row.erase(expandable);
3300 if (rhsit == _primal_constraint_values.end())
3302 if (constraint_rhs !=
Number(0))
3303 _primal_constraint_values[*i] = constraint_rhs;
3305 _primal_constraint_values.erase(*i);
3309 if (constraint_rhs !=
Number(0))
3310 rhsit->second = constraint_rhs;
3312 _primal_constraint_values.erase(rhsit);
3315 if (constraints_to_expand.empty())
3316 i = unexpanded_set.erase(i);
3325 this->scatter_constraints(
mesh);
3329 this->add_constraints_to_send_list();
3333 #ifdef LIBMESH_ENABLE_CONSTRAINTS 3334 void DofMap::check_for_cyclic_constraints()
3337 typedef std::set<dof_id_type> RCSet;
3338 RCSet unexpanded_set;
3344 for (
const auto & i : dof_constraints_copy)
3345 unexpanded_set.insert(i.first);
3347 while (!unexpanded_set.empty())
3348 for (RCSet::iterator i = unexpanded_set.begin();
3349 i != unexpanded_set.end(); )
3352 DofConstraints::iterator
3353 pos = dof_constraints_copy.find(*i);
3355 libmesh_assert (pos != dof_constraints_copy.end());
3365 std::vector<dof_id_type> constraints_to_expand;
3367 for (
const auto & item : constraint_row)
3368 if (item.first != *i && this->is_constrained_dof(item.first))
3370 unexpanded_set.insert(item.first);
3371 constraints_to_expand.push_back(item.first);
3374 for (
const auto & expandable : constraints_to_expand)
3376 const Real this_coef = constraint_row[expandable];
3378 DofConstraints::const_iterator
3379 subpos = dof_constraints_copy.find(expandable);
3381 libmesh_assert (subpos != dof_constraints_copy.end());
3385 for (
const auto & item : subconstraint_row)
3387 if (item.first == expandable)
3388 libmesh_error_msg(
"Cyclic constraint detected");
3390 constraint_row[item.first] += item.second * this_coef;
3399 constraint_row.erase(expandable);
3418 if (constraints_to_expand.empty())
3419 i = unexpanded_set.erase(i);
3425 void DofMap::check_for_cyclic_constraints()
3439 parallel_object_only();
3442 if (this->n_processors() == 1)
3447 unsigned int has_constraints = !_dof_constraints.empty()
3448 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3449 || !_node_constraints.empty()
3450 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 3452 this->comm().max(has_constraints);
3453 if (!has_constraints)
3460 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3461 std::map<processor_id_type, std::set<dof_id_type>> pushed_node_ids;
3462 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 3464 std::map<processor_id_type, std::set<dof_id_type>> pushed_ids;
3468 for (
auto & i : _dof_constraints)
3471 while (constrained >= _end_df[constrained_proc_id])
3472 constrained_proc_id++;
3474 if (constrained_proc_id != this->processor_id())
3478 for (
auto & j : row)
3483 while (constraining >= _end_df[constraining_proc_id])
3484 constraining_proc_id++;
3486 if (constraining_proc_id != this->processor_id() &&
3487 constraining_proc_id != constrained_proc_id)
3488 pushed_ids[constraining_proc_id].insert(constrained);
3495 std::vector<std::vector<std::pair<dof_id_type, Real>>>>
3496 pushed_keys_vals, pushed_keys_vals_to_me;
3498 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Number>>>
3499 pushed_ids_rhss, pushed_ids_rhss_to_me;
3508 for (
auto & pid_id_pair : pushed_ids)
3511 const std::set<dof_id_type>
3512 & pid_ids = pid_id_pair.second;
3514 const std::size_t ids_size = pid_ids.size();
3515 std::vector<std::vector<std::pair<dof_id_type, Real>>> &
3516 keys_vals = pushed_keys_vals[pid];
3517 std::vector<std::pair<dof_id_type,Number>> &
3518 ids_rhss = pushed_ids_rhss[pid];
3519 keys_vals.resize(ids_size);
3520 ids_rhss.resize(ids_size);
3523 std::set<dof_id_type>::const_iterator it;
3524 for (push_i = 0, it = pid_ids.begin();
3525 it != pid_ids.end(); ++push_i, ++it)
3529 keys_vals[push_i].assign(row.begin(), row.end());
3531 DofConstraintValueMap::const_iterator rhsit =
3532 _primal_constraint_values.find(constrained);
3533 ids_rhss[push_i].first = constrained;
3534 ids_rhss[push_i].second =
3535 (rhsit == _primal_constraint_values.end()) ?
3543 auto ids_rhss_action_functor =
3544 [& pushed_ids_rhss_to_me]
3546 const std::vector<std::pair<dof_id_type, Number>> &
data)
3548 pushed_ids_rhss_to_me[pid] =
data;
3551 auto keys_vals_action_functor =
3552 [& pushed_keys_vals_to_me]
3554 const std::vector<std::vector<std::pair<dof_id_type, Real>>> &
data)
3556 pushed_keys_vals_to_me[pid] =
data;
3561 (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
3563 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
3566 auto receive_dof_constraints =
3568 & pushed_ids_rhss_to_me,
3569 & pushed_keys_vals_to_me]
3572 for (
auto & pid_id_pair : pushed_ids_rhss_to_me)
3575 const auto & ids_rhss = pid_id_pair.second;
3576 const auto & keys_vals = pushed_keys_vals_to_me[pid];
3578 libmesh_assert_equal_to
3579 (ids_rhss.size(), keys_vals.size());
3588 if (!this->is_constrained_dof(constrained))
3591 for (
auto & key_val : keys_vals[i])
3593 row[key_val.first] = key_val.second;
3595 if (ids_rhss[i].second !=
Number(0))
3596 _primal_constraint_values[constrained] =
3599 _primal_constraint_values.erase(constrained);
3605 receive_dof_constraints();
3607 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS 3609 for (
auto & i : _node_constraints)
3611 const Node * constrained = i.first;
3613 if (constrained->
processor_id() != this->processor_id())
3617 for (
auto & j : row)
3619 const Node * constraining = j.first;
3621 if (constraining->
processor_id() != this->processor_id() &&
3623 pushed_node_ids[constraining->
processor_id()].insert(constrained->
id());
3629 std::vector<std::vector<std::pair<dof_id_type,Real>>>>
3630 pushed_node_keys_vals, pushed_node_keys_vals_to_me;
3631 std::map<processor_id_type, std::vector<std::pair<dof_id_type, Point>>>
3632 pushed_node_ids_offsets, pushed_node_ids_offsets_to_me;
3633 std::map<processor_id_type, std::set<const Node *>> pushed_nodes;
3635 for (
auto & pid_id_pair : pushed_node_ids)
3638 const std::set<dof_id_type>
3639 & pid_ids = pid_id_pair.second;
3641 const std::size_t ids_size = pid_ids.size();
3642 std::vector<std::vector<std::pair<dof_id_type,Real>>> &
3643 keys_vals = pushed_node_keys_vals[pid];
3644 std::vector<std::pair<dof_id_type, Point>> &
3645 ids_offsets = pushed_node_ids_offsets[pid];
3646 keys_vals.resize(ids_size);
3647 ids_offsets.resize(ids_size);
3648 std::set<const Node *> & nodes = pushed_nodes[pid];
3651 std::set<dof_id_type>::const_iterator it;
3652 for (push_i = 0, it = pid_ids.begin();
3653 it != pid_ids.end(); ++push_i, ++it)
3658 nodes.insert(constrained);
3661 std::size_t row_size = row.
size();
3662 keys_vals[push_i].reserve(row_size);
3663 for (
const auto & j : row)
3665 const Node * constraining = j.first;
3667 keys_vals[push_i].push_back
3668 (std::make_pair(constraining->
id(), j.second));
3671 nodes.insert(constraining);
3674 ids_offsets[push_i].first = *it;
3675 ids_offsets[push_i].second = _node_constraints[constrained].second;
3679 auto node_ids_offsets_action_functor =
3680 [& pushed_node_ids_offsets_to_me]
3682 const std::vector<std::pair<dof_id_type, Point>> &
data)
3684 pushed_node_ids_offsets_to_me[pid] =
data;
3687 auto node_keys_vals_action_functor =
3688 [& pushed_node_keys_vals_to_me]
3690 const std::vector<std::vector<std::pair<dof_id_type, Real>>> &
data)
3692 pushed_node_keys_vals_to_me[pid] =
data;
3697 (this->comm(), pushed_node_ids_offsets, node_ids_offsets_action_functor);
3699 (this->comm(), pushed_node_keys_vals, node_keys_vals_action_functor);
3703 std::vector<Parallel::Request> send_requests;
3706 for (
auto & pid_id_pair : pushed_node_ids_offsets)
3710 this->comm().send_packed_range
3712 pushed_nodes[pid].begin(), pushed_nodes[pid].
end(),
3713 send_requests.back(), range_tag);
3717 for (
auto & pid_id_pair : pushed_node_ids_offsets_to_me)
3720 const auto & ids_offsets = pid_id_pair.second;
3721 const auto & keys_vals = pushed_node_keys_vals_to_me[pid];
3723 libmesh_assert_equal_to
3724 (ids_offsets.size(), keys_vals.size());
3727 this->comm().receive_packed_range
3729 (
Node**)
nullptr, range_tag);
3734 dof_id_type constrained_id = ids_offsets[i].first;
3739 if (!this->is_constrained_node(constrained))
3742 for (
auto & key_val : keys_vals[i])
3745 row[key_node] = key_val.second;
3747 _node_constraints[constrained].second =
3748 ids_offsets[i].second;
3755 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS 3768 typedef std::map<dof_id_type, std::set<dof_id_type>> DofConstrainsMap;
3769 DofConstrainsMap dof_id_constrains;
3771 for (
auto & i : _dof_constraints)
3775 for (
const auto & j : row)
3780 while (constraining >= _end_df[constraining_proc_id])
3781 constraining_proc_id++;
3783 if (constraining_proc_id == this->processor_id())
3784 dof_id_constrains[constraining].insert(constrained);
3795 std::vector<dof_id_type> my_dof_indices;
3796 this->dof_indices (elem, my_dof_indices);
3798 for (
const auto & dof : my_dof_indices)
3800 DofConstrainsMap::const_iterator dcmi = dof_id_constrains.find(dof);
3801 if (dcmi != dof_id_constrains.end())
3803 for (
const auto & constrained : dcmi->second)
3806 while (constrained >= _end_df[the_constrained_proc_id])
3807 the_constrained_proc_id++;
3810 if (elemproc != the_constrained_proc_id)
3811 pushed_ids[elemproc].insert(constrained);
3817 pushed_ids_rhss.clear();
3818 pushed_ids_rhss_to_me.clear();
3819 pushed_keys_vals.clear();
3820 pushed_keys_vals_to_me.clear();
3826 (this->comm(), pushed_ids_rhss, ids_rhss_action_functor);
3828 (this->comm(), pushed_keys_vals, keys_vals_action_functor);
3830 receive_dof_constraints();
3841 std::set<CouplingMatrix*> temporary_coupling_matrices;
3843 this->merge_ghost_functor_outputs
3844 (elements_to_couple,
3845 temporary_coupling_matrices,
3846 this->coupling_functors_begin(),
3847 this->coupling_functors_end(),
3850 this->processor_id());
3853 std::set<dof_id_type> requested_dofs;
3855 for (
const auto & pr : elements_to_couple)
3857 const Elem * elem = pr.first;
3860 std::vector<dof_id_type> element_dofs;
3861 this->dof_indices(elem, element_dofs);
3863 for (
auto dof : element_dofs)
3864 requested_dofs.insert(dof);
3867 this->gather_constraints(
mesh, requested_dofs,
false);
3872 std::set<dof_id_type> & unexpanded_dofs,
3875 typedef std::set<dof_id_type> DoF_RCSet;
3879 const unsigned int max_qoi_num =
3880 _adjoint_constraint_values.empty() ?
3881 0 : _adjoint_constraint_values.rbegin()->first;
3885 bool unexpanded_set_nonempty = !unexpanded_dofs.empty();
3886 this->comm().max(unexpanded_set_nonempty);
3888 while (unexpanded_set_nonempty)
3891 parallel_object_only();
3894 DoF_RCSet dof_request_set;
3897 std::map<processor_id_type, std::vector<dof_id_type>>
3901 std::map<processor_id_type, dof_id_type>
3905 for (
const auto & unexpanded_dof : unexpanded_dofs)
3907 DofConstraints::const_iterator
3908 pos = _dof_constraints.find(unexpanded_dof);
3912 if (pos == _dof_constraints.end())
3914 if (!this->local_index(unexpanded_dof) &&
3915 !_dof_constraints.count(unexpanded_dof) )
3916 dof_request_set.insert(unexpanded_dof);
3924 for (
const auto & j : row)
3930 if (!this->local_index(constraining_dof) &&
3931 !_dof_constraints.count(constraining_dof))
3932 dof_request_set.insert(constraining_dof);
3938 unexpanded_dofs.clear();
3942 for (
const auto & i : dof_request_set)
3944 while (i >= _end_df[proc_id])
3946 dof_ids_on_proc[proc_id]++;
3949 for (
auto & pair : dof_ids_on_proc)
3951 requested_dof_ids[pair.first].reserve(pair.second);
3956 for (
const auto & i : dof_request_set)
3958 while (i >= _end_df[proc_id])
3960 requested_dof_ids[proc_id].push_back(i);
3963 typedef std::vector<std::pair<dof_id_type, Real>> row_datum;
3965 typedef std::vector<Number> rhss_datum;
3967 auto row_gather_functor =
3970 const std::vector<dof_id_type> & ids,
3971 std::vector<row_datum> &
data)
3974 const std::size_t query_size = ids.size();
3976 data.resize(query_size);
3977 for (std::size_t i=0; i != query_size; ++i)
3980 if (_dof_constraints.count(constrained))
3983 std::size_t row_size = row.size();
3984 data[i].reserve(row_size);
3985 for (
const auto & j : row)
3987 data[i].push_back(j);
3991 libmesh_assert(j.first != DofObject::invalid_id);
4011 (std::make_pair(DofObject::invalid_id,
Real(0)));
4016 auto rhss_gather_functor =
4020 const std::vector<dof_id_type> & ids,
4021 std::vector<rhss_datum> &
data)
4024 const std::size_t query_size = ids.size();
4026 data.resize(query_size);
4027 for (std::size_t i=0; i != query_size; ++i)
4031 if (_dof_constraints.count(constrained))
4033 DofConstraintValueMap::const_iterator rhsit =
4034 _primal_constraint_values.find(constrained);
4036 ((rhsit == _primal_constraint_values.end()) ?
4039 for (
unsigned int q = 0; q != max_qoi_num; ++q)
4041 AdjointDofConstraintValues::const_iterator adjoint_map_it =
4042 _adjoint_constraint_values.find(q);
4044 if (adjoint_map_it == _adjoint_constraint_values.end())
4046 data[i].push_back(0);
4051 adjoint_map_it->second;
4053 DofConstraintValueMap::const_iterator adj_rhsit =
4054 constraint_map.find(constrained);
4056 ((adj_rhsit == constraint_map.end()) ?
4057 0 : adj_rhsit->second);
4063 auto row_action_functor =
4067 const std::vector<dof_id_type> & ids,
4068 const std::vector<row_datum> &
data)
4071 const std::size_t query_size = ids.size();
4073 for (std::size_t i=0; i != query_size; ++i)
4079 if (
data[i].empty())
4084 else if (
data[i][0].first != DofObject::invalid_id)
4088 for (
auto & pair :
data[i])
4089 row[pair.first] = pair.second;
4092 unexpanded_dofs.insert(constrained);
4097 auto rhss_action_functor =
4101 const std::vector<dof_id_type> & ids,
4102 const std::vector<rhss_datum> &
data)
4105 const std::size_t query_size = ids.size();
4107 for (std::size_t i=0; i != query_size; ++i)
4109 if (!
data[i].empty())
4113 _primal_constraint_values[constrained] =
data[i][0];
4115 _primal_constraint_values.erase(constrained);
4117 for (
unsigned int q = 0; q != max_qoi_num; ++q)
4119 AdjointDofConstraintValues::iterator adjoint_map_it =
4120 _adjoint_constraint_values.find(q);
4122 if ((adjoint_map_it == _adjoint_constraint_values.end()) &&
4126 if (adjoint_map_it == _adjoint_constraint_values.end())
4127 adjoint_map_it = _adjoint_constraint_values.insert
4131 adjoint_map_it->second;
4134 constraint_map[constrained] =
4137 constraint_map.erase(constrained);
4145 row_datum * row_ex =
nullptr;
4147 (this->comm(), requested_dof_ids, row_gather_functor,
4148 row_action_functor, row_ex);
4151 rhss_datum * rhs_ex =
nullptr;
4153 (this->comm(), requested_dof_ids, rhss_gather_functor,
4154 rhss_action_functor, rhs_ex);
4158 unexpanded_set_nonempty = !unexpanded_dofs.empty();
4159 this->comm().max(unexpanded_set_nonempty);
4163 void DofMap::add_constraints_to_send_list()
4166 parallel_object_only();
4169 if (this->n_processors() == 1)
4174 unsigned int has_constraints = !_dof_constraints.empty();
4175 this->comm().max(has_constraints);
4176 if (!has_constraints)
4179 for (
const auto & i : _dof_constraints)
4184 if (!this->local_index(constrained_dof))
4188 for (
const auto & j : constraint_row)
4193 if (this->local_index(constraint_dependency))
4196 _send_list.push_back(constraint_dependency);
4203 #endif // LIBMESH_ENABLE_CONSTRAINTS 4206 #ifdef LIBMESH_ENABLE_AMR 4208 void DofMap::constrain_p_dofs (
unsigned int var,
4216 libmesh_assert_greater (elem->
p_level(), p);
4217 libmesh_assert_less (s, elem->
n_sides());
4219 const unsigned int sys_num = this->sys_number();
4220 const unsigned int dim = elem->
dim();
4222 FEType low_p_fe_type = this->variable_type(var);
4223 FEType high_p_fe_type = this->variable_type(var);
4229 for (
unsigned int n = 0; n !=
n_nodes; ++n)
4233 const unsigned int low_nc =
4234 FEInterface::n_dofs_at_node (dim, low_p_fe_type, type, n);
4235 const unsigned int high_nc =
4236 FEInterface::n_dofs_at_node (dim, high_p_fe_type, type, n);
4247 for (
unsigned int i = low_nc; i != high_nc; ++i)
4249 _dof_constraints[node.
dof_number(sys_num,var,i)].clear();
4250 _primal_constraint_values.erase(node.
dof_number(sys_num,var,i));
4255 const unsigned int total_dofs = node.
n_comp(sys_num, var);
4256 libmesh_assert_greater_equal (total_dofs, high_nc);
4259 for (
unsigned int j = low_nc; j != high_nc; ++j)
4261 const unsigned int i = total_dofs - j - 1;
4262 _dof_constraints[node.
dof_number(sys_num,var,i)].clear();
4263 _primal_constraint_values.erase(node.
dof_number(sys_num,var,i));
4269 #endif // LIBMESH_ENABLE_AMR 4272 #ifdef LIBMESH_ENABLE_DIRICHLET 4280 unsigned int qoi_index)
4282 unsigned int old_size = cast_int<unsigned int>
4283 (_adjoint_dirichlet_boundaries.size());
4284 for (
unsigned int i = old_size; i <= qoi_index; ++i)
4287 _adjoint_dirichlet_boundaries[qoi_index]->push_back
4292 bool DofMap::has_adjoint_dirichlet_boundaries(
unsigned int q)
const 4294 if (_adjoint_dirichlet_boundaries.size() > q)
4302 DofMap::get_adjoint_dirichlet_boundaries(
unsigned int q)
const 4304 libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),q);
4305 return _adjoint_dirichlet_boundaries[q];
4310 DofMap::get_adjoint_dirichlet_boundaries(
unsigned int q)
4312 unsigned int old_size = cast_int<unsigned int>
4313 (_adjoint_dirichlet_boundaries.size());
4314 for (
unsigned int i = old_size; i <= q; ++i)
4317 return _adjoint_dirichlet_boundaries[q];
4325 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
4327 auto it = std::find_if(_dirichlet_boundaries->begin(), _dirichlet_boundaries->end(), lam);
4330 libmesh_assert (it != _dirichlet_boundaries->end());
4332 _dirichlet_boundaries->erase(it);
4337 unsigned int qoi_index)
4339 libmesh_assert_greater(_adjoint_dirichlet_boundaries.size(),
4343 {
return bdy->b == boundary_to_remove.
b && bdy->variables == boundary_to_remove.
variables;};
4345 auto it = std::find_if(_adjoint_dirichlet_boundaries[qoi_index]->begin(),
4346 _adjoint_dirichlet_boundaries[qoi_index]->
end(),
4350 libmesh_assert (it != _adjoint_dirichlet_boundaries[qoi_index]->
end());
4352 _adjoint_dirichlet_boundaries[qoi_index]->erase(it);
4356 DirichletBoundaries::~DirichletBoundaries()
4358 for (
auto & item : *
this)
4366 const std::set<boundary_id_type>& dbc_bcids = boundary.
b;
4371 for (
const auto &
bc_id : dbc_bcids)
4376 bool found_bcid = (mesh_bcids.find(
bc_id) != mesh_bcids.end());
4384 libmesh_error_msg(
"Could not find Dirichlet boundary id " <<
bc_id <<
" in mesh!");
4388 #endif // LIBMESH_ENABLE_DIRICHLET 4391 #ifdef LIBMESH_ENABLE_PERIODIC 4398 if (existing_boundary ==
nullptr)
4405 _periodic_boundaries->insert(std::make_pair(boundary->
myboundary, boundary));
4406 _periodic_boundaries->insert(std::make_pair(inverse_boundary->
myboundary, inverse_boundary));
4411 existing_boundary->
merge(periodic_boundary);
4415 libmesh_assert(inverse_boundary);
4416 inverse_boundary->
merge(periodic_boundary);
4444 _periodic_boundaries->insert(std::make_pair(p_boundary->
myboundary, p_boundary));
4445 _periodic_boundaries->insert(std::make_pair(p_inverse_boundary->
myboundary, p_inverse_boundary));
std::unique_ptr< FEMFunctionBase< Gradient > > g_fem
Manages the family, order, etc. parameters for a given FE.
virtual unsigned int size() const override
void wait(std::vector< Request > &r)
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.)
A geometric point in (x,y,z) space associated with a DOF.
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
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void parallel_for(const Range &range, const Body &body)
Maps between boundary ids and PeriodicBoundaryBase objects.
virtual element_iterator local_elements_begin()=0
virtual numeric_index_type size() const =0
void resize(const unsigned int n)
The base class for all geometric element types.
boundary_id_type pairedboundary
IntRange< std::size_t > index_range(const std::vector< T > &vec)
uint8_t processor_id_type
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
Class for specifying Dirichlet boundary conditions as constraints.
const Parallel::Communicator & comm() const
unsigned int p_level() const
std::vector< unsigned int > variables
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
static const Real TOLERANCE
Utility class for defining generic ranges for threading.
const unsigned int n_vars
const BoundaryInfo & get_boundary_info() const
long double max(long double a, double b)
const MeshBase & get_mesh() const
void iota(ForwardIter first, ForwardIter last, T value)
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
void merge(const PeriodicBoundaryBase &pb)
std::vector< boundary_id_type > boundary_ids(const Node *node) const
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
Manages the degrees of freedom (DOFs) in a simulation.
std::unique_ptr< FEMFunctionBase< Number > > f_fem
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
unsigned int first_scalar_number() const
virtual bool is_serial() const
boundary_id_type myboundary
const dof_id_type n_nodes
A variable which is solved for in a System of equations.
const Variable & variable(const unsigned int c) const
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
const Node & node_ref(const unsigned int i) const
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, RequestContainer &reqs, GatherFunctor &gather_data, ActionFunctor &act_on_data, const datum *example)
virtual unsigned int n_nodes() const =0
virtual element_iterator active_local_elements_begin()=0
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Manages consistently variables, degrees of freedom, and coefficient vectors.
virtual void right_multiply(const DenseMatrixBase< T > &M2) override
virtual void init_context(const FEMContext &)
std::unique_ptr< NumericVector< Number > > solution
Used by the Mesh to keep track of boundary nodes and elements.
SimpleRange< I > as_range(const std::pair< I, I > &p)
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
virtual element_iterator local_elements_end()=0
bool active_on_subdomain(subdomain_id_type sid) const
virtual std::unique_ptr< PeriodicBoundaryBase > clone(TransformationType t=FORWARD) const =0
An output iterator for use with packed_range functions.
virtual bool closed() const
const std::set< boundary_id_type > & get_boundary_ids() const
virtual numeric_index_type first_local_index() const =0
virtual unsigned int n_sides() const =0
ParallelType type() const
virtual element_iterator active_not_local_elements_end()=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void left_multiply_transpose(const DenseMatrix< T > &A)
std::unique_ptr< FunctionBase< Gradient > > g
StoredRange< iterator_type, object_type > & reset(const iterator_type &first, const iterator_type &last)
virtual unsigned short dim() const =0
bool libmesh_isnan(float a)
virtual bool is_vertex(const unsigned int i) const =0
virtual void zero() override
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)
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
unsigned int mesh_dimension() const
std::unique_ptr< NumericVector< Number > > current_local_solution
virtual element_iterator active_not_local_elements_begin()=0
Base class for all PeriodicBoundary implementations.
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
virtual void set(const numeric_index_type i, const T value)=0
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
void push_parallel_vector_data(const Communicator &comm, const MapToVectors &data, RequestContainer &reqs, ActionFunctor &act_on_data)
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
A matrix object used for finite element assembly and numerics.
const DofMap & get_dof_map() const
processor_id_type processor_id() const
virtual element_iterator active_local_elements_end()=0
virtual ElemType type() const =0
A geometric point in (x,y,z) space.
virtual numeric_index_type last_local_index() const =0
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
virtual void zero() override
const FEType & type() const
std::vector< boundary_id_type > edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
virtual void localize(std::vector< T > &v_local) const =0
bool verify(const T &r) const