21 #include "libmesh/dof_map.h"
24 #include "libmesh/coupling_matrix.h"
25 #include "libmesh/default_coupling.h"
26 #include "libmesh/dense_matrix.h"
27 #include "libmesh/dense_vector_base.h"
28 #include "libmesh/dirichlet_boundaries.h"
29 #include "libmesh/elem.h"
30 #include "libmesh/enum_to_string.h"
31 #include "libmesh/fe_interface.h"
32 #include "libmesh/fe_type.h"
33 #include "libmesh/fe_base.h"
34 #include "libmesh/ghosting_functor.h"
35 #include "libmesh/int_range.h"
36 #include "libmesh/libmesh_logging.h"
37 #include "libmesh/mesh_base.h"
38 #include "libmesh/mesh_subdivision_support.h"
39 #include "libmesh/mesh_tools.h"
40 #include "libmesh/numeric_vector.h"
41 #include "libmesh/periodic_boundary_base.h"
42 #include "libmesh/periodic_boundaries.h"
43 #include "libmesh/sparse_matrix.h"
44 #include "libmesh/sparsity_pattern.h"
45 #include "libmesh/threads.h"
48 #include "timpi/parallel_implementation.h"
49 #include "timpi/parallel_sync.h"
56 #include <unordered_map>
63 std::unique_ptr<SparsityPattern::Build>
65 bool calculate_constrained)
const
67 libmesh_assert (mesh.is_prepared());
69 LOG_SCOPE(
"build_sparsity()",
"DofMap");
92 auto sp = std::make_unique<SparsityPattern::Build>
96 implicit_neighbor_dofs,
98 calculate_constrained);
100 Threads::parallel_reduce (ConstElemRange (mesh.active_local_elements_begin(),
101 mesh.active_local_elements_end()), *sp);
110 libmesh_assert_equal_to (sp->get_sparsity_pattern().size(), n_dofs_on_proc);
118 libMesh::out <<
"WARNING: You have specified both an extra sparsity function and object.\n"
119 <<
" Are you sure this is what you meant to do??"
137 ParallelObject (mesh.comm()),
138 _dof_coupling(nullptr),
139 _error_on_constraint_loop(false),
140 _constrained_sparsity_construction(false),
143 _variable_group_numbers(),
151 _augment_sparsity_pattern(nullptr),
152 _extra_sparsity_function(nullptr),
153 _extra_sparsity_context(nullptr),
154 _augment_send_list(nullptr),
155 _extra_send_list_function(nullptr),
156 _extra_send_list_context(nullptr),
157 _default_coupling(std::make_unique<DefaultCoupling>()),
158 _default_evaluating(std::make_unique<DefaultCoupling>()),
159 need_full_sparsity_pattern(false),
162 #ifdef LIBMESH_ENABLE_AMR
166 _first_old_scalar_df()
168 #ifdef LIBMESH_ENABLE_CONSTRAINTS
170 , _stashed_dof_constraints()
171 , _primal_constraint_values()
172 , _adjoint_constraint_values()
174 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
175 , _node_constraints()
177 #ifdef LIBMESH_ENABLE_PERIODIC
180 #ifdef LIBMESH_ENABLE_DIRICHLET
182 , _adjoint_dirichlet_boundaries()
184 , _implicit_neighbor_dofs_initialized(false),
185 _implicit_neighbor_dofs(false),
186 _verify_dirichlet_bc_consistency(true)
194 #ifdef LIBMESH_ENABLE_PERIODIC
217 #ifdef LIBMESH_ENABLE_PERIODIC
263 for (
auto var : make_range(new_var_group.
n_variables()))
265 auto var_instance = new_var_group(var);
266 const auto vn = var_instance.number();
267 _variables.push_back (std::move(var_instance));
280 parallel_object_only();
299 (!
_sp->get_n_nz().empty() ||
300 !
_sp->get_n_oz().empty());
301 this->comm().max(computed_sparsity_already);
316 libmesh_assert(
_sp.get());
343 return mesh.node_ptr(i);
350 return mesh.elem_ptr(i);
355 template <
typename iterator_type>
357 iterator_type objects_end,
359 dofobject_accessor objects)
362 parallel_object_only();
366 std::unordered_map<processor_id_type, dof_id_type> ghost_objects_from_proc;
368 iterator_type it = objects_begin;
370 for (; it != objects_end; ++it)
379 ghost_objects_from_proc[obj_procid]++;
384 std::map<processor_id_type, std::vector<dof_id_type>>
389 for (
auto [p, size] : ghost_objects_from_proc)
391 if (p != this->processor_id())
392 requested_ids[p].reserve(size);
395 for (it = objects_begin; it != objects_end; ++it)
402 for (
auto p : make_range(this->n_processors()))
404 if (ghost_objects_from_proc.count(p))
405 libmesh_assert_equal_to (requested_ids[p].size(), ghost_objects_from_proc[p]);
407 libmesh_assert(!requested_ids.count(p));
411 typedef std::vector<dof_id_type> datum;
413 auto gather_functor =
414 [
this, &mesh, &objects]
416 const std::vector<dof_id_type> & ids,
417 std::vector<datum> & data)
424 const std::size_t query_size = ids.size();
426 data.resize(query_size);
427 for (
auto & d : data)
428 d.resize(2 * n_var_groups);
430 for (std::size_t i=0; i != query_size; ++i)
432 DofObject * requested = (this->*objects)(mesh, ids[i]);
433 libmesh_assert(requested);
434 libmesh_assert_equal_to (requested->
processor_id(), this->processor_id());
435 libmesh_assert_equal_to (requested->
n_var_groups(sys_num), n_var_groups);
436 for (
unsigned int vg=0; vg != n_var_groups; ++vg)
438 unsigned int n_comp_g =
440 data[i][vg] = n_comp_g;
444 data[i][n_var_groups+vg] = my_first_dof;
449 auto action_functor =
450 [
this, &mesh, &objects]
451 (processor_id_type libmesh_dbg_var(pid),
452 const std::vector<dof_id_type> & ids,
453 const std::vector<datum> & data)
460 for (
auto i : index_range(ids))
462 DofObject * requested = (this->*objects)(mesh, ids[i]);
463 libmesh_assert(requested);
464 libmesh_assert_equal_to (requested->
processor_id(), pid);
465 for (
unsigned int vg=0; vg != n_var_groups; ++vg)
467 unsigned int n_comp_g =
468 cast_int<unsigned int>(data[i][vg]);
472 dof_id_type my_first_dof = data[i][n_var_groups+vg];
475 (sys_num, vg, my_first_dof);
481 datum * ex =
nullptr;
482 Parallel::pull_parallel_vector_data
483 (this->comm(), requested_ids, gather_functor, action_functor, ex);
487 for (it = objects_begin; it != objects_end; ++it)
490 libmesh_assert (obj);
492 for (
unsigned int v=0; v != num_variables; ++v)
494 unsigned int n_comp =
508 libmesh_assert (mesh.is_prepared());
510 LOG_SCOPE(
"reinit()",
"DofMap");
525 unsigned int standard_n_levels =
541 std::vector<unsigned int> n_vars_per_group; n_vars_per_group.reserve (n_var_groups);
543 for (
unsigned int vg=0; vg<n_var_groups; vg++)
544 n_vars_per_group.push_back (this->variable_group(vg).n_variables());
546 #ifdef LIBMESH_ENABLE_AMR
551 for (
auto & node : mesh.node_ptr_range())
553 node->clear_old_dof_object();
554 libmesh_assert (!node->get_old_dof_object());
557 for (
auto & elem : mesh.element_ptr_range())
559 elem->clear_old_dof_object();
560 libmesh_assert (!elem->get_old_dof_object());
568 for (
auto & elem : mesh.element_ptr_range())
571 if (elem->refinement_flag() == Elem::JUST_REFINED)
574 for (Node & node : elem->node_ref_range())
575 if (node.get_old_dof_object() ==
nullptr)
576 if (node.has_dofs(sys_num))
577 node.set_old_dof_object();
579 libmesh_assert (!elem->get_old_dof_object());
581 if (elem->has_dofs(sys_num))
582 elem->set_old_dof_object();
585 #endif // #ifdef LIBMESH_ENABLE_AMR
594 for (
auto & node : mesh.node_ptr_range())
595 node->set_n_vars_per_group(sys_num, n_vars_per_group);
598 for (
auto & elem : mesh.element_ptr_range())
599 elem->set_n_vars_per_group(sys_num, n_vars_per_group);
606 for (
unsigned int vg=0; vg<n_var_groups; vg++)
610 const unsigned int n_var_in_group = vg_description.
n_variables();
611 const FEType & base_fe_type = vg_description.
type();
613 const bool add_p_level =
614 #ifdef LIBMESH_ENABLE_AMR
622 if (base_fe_type.family == SCALAR)
624 this->
_n_SCALAR_dofs += base_fe_type.order.get_order()*n_var_in_group;
629 const bool extra_hanging_dofs =
630 FEInterface::extra_hanging_dofs(base_fe_type);
633 for (
auto & elem : mesh.active_element_ptr_range())
635 libmesh_assert(elem);
642 FEType fe_type = base_fe_type;
644 const ElemType type = elem->type();
646 libmesh_error_msg_if(base_fe_type.order.get_order() >
647 int(FEInterface::max_order(base_fe_type,type)),
648 "ERROR: Finite element "
649 << Utility::enum_to_string(base_fe_type.family)
650 <<
" on geometric element "
651 << Utility::enum_to_string(type)
652 <<
"\nonly supports FEInterface::max_order = "
653 << FEInterface::max_order(base_fe_type,type)
654 <<
", not fe_type.order = "
655 << base_fe_type.order);
657 #ifdef LIBMESH_ENABLE_AMR
660 if (add_p_level*elem->p_level() + base_fe_type.order >
661 FEInterface::max_order(base_fe_type, type))
665 << Utility::enum_to_string(base_fe_type.family)
666 <<
" on geometric element "
667 << Utility::enum_to_string(type) << std::endl
668 <<
"could not be p refined past FEInterface::max_order = "
669 << FEInterface::max_order(base_fe_type,type)
672 elem->set_p_level(FEInterface::max_order(base_fe_type,type)
673 - base_fe_type.order);
678 for (
auto n : elem->node_index_range())
680 Node & node = elem->node_ref(n);
682 if (elem->is_vertex(n))
684 const unsigned int old_node_dofs =
685 node.n_comp_group(sys_num, vg);
687 const unsigned int vertex_dofs =
688 std::max(FEInterface::n_dofs_at_node(fe_type, elem, n, add_p_level),
692 if (vertex_dofs > old_node_dofs)
694 node.set_n_comp_group(sys_num, vg,
699 node.set_vg_dof_base(sys_num, vg,
717 for (
auto & elem : mesh.active_element_ptr_range())
719 libmesh_assert(elem);
727 for (
auto n : elem->node_index_range())
729 Node & node = elem->node_ref(n);
731 const unsigned int old_node_dofs =
732 node.n_comp_group(sys_num, vg);
734 const unsigned int vertex_dofs = old_node_dofs?
735 cast_int<unsigned int>(node.vg_dof_base (sys_num,vg)):0;
737 const unsigned int new_node_dofs =
738 FEInterface::n_dofs_at_node(base_fe_type, elem, n, add_p_level);
741 if (elem->is_vertex(n))
743 libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
753 libmesh_assert_greater_equal (vertex_dofs, new_node_dofs);
762 node.set_n_comp_group(sys_num, vg,
767 node.set_vg_dof_base(sys_num, vg, 0);
773 else if (vertex_dofs == 0)
775 if (new_node_dofs > old_node_dofs)
777 node.set_n_comp_group(sys_num, vg,
780 node.set_vg_dof_base(sys_num, vg,
787 else if (extra_hanging_dofs)
789 if (new_node_dofs > old_node_dofs - vertex_dofs)
791 node.set_n_comp_group(sys_num, vg,
792 vertex_dofs + new_node_dofs);
794 node.set_vg_dof_base(sys_num, vg,
802 libmesh_assert_greater_equal (old_node_dofs, vertex_dofs);
803 if (new_node_dofs > old_node_dofs)
805 node.set_n_comp_group(sys_num, vg,
808 node.set_vg_dof_base (sys_num, vg,
815 const unsigned int dofs_per_elem =
816 FEInterface::n_dofs_per_elem(base_fe_type, elem, add_p_level);
818 elem->set_n_comp_group(sys_num, vg, dofs_per_elem);
837 const unsigned int sys_num = this->
sys_number();
840 for (
auto & node : mesh.node_ptr_range())
841 node->invalidate_dofs(sys_num);
844 for (
auto & elem : mesh.active_element_ptr_range())
845 elem->invalidate_dofs(sys_num);
866 _mesh.remove_ghosting_functor(*gf);
868 this->_coupling_functors.clear();
883 _mesh.remove_ghosting_functor(*gf);
885 this->_algebraic_ghosting_functors.clear();
907 #ifdef LIBMESH_ENABLE_AMR
930 parallel_object_only();
933 LOG_SCOPE(
"distribute_dofs()",
"DofMap");
935 libmesh_assert (mesh.is_prepared());
941 libmesh_assert_less (proc_id, n_proc);
965 std::vector<dof_id_type> dofs_on_proc(n_proc, 0);
966 this->comm().allgather(next_free_dof, dofs_on_proc);
969 #ifdef LIBMESH_ENABLE_AMR
995 libmesh_assert_equal_to (next_free_dof,
_end_df[proc_id]);
1003 if (this->n_processors() > 1)
1010 mesh.elements_end(),
1021 MeshTools::libmesh_assert_valid_dof_ids(mesh, sys_num);
1024 for (
auto & node : mesh.node_ptr_range())
1029 for (
auto v : make_range(dofobj->
n_vars(sys_num)))
1030 for (
auto c : make_range(dofobj->
n_comp(sys_num,v)))
1033 libmesh_assert_greater_equal (dofid, this->
first_dof(obj_proc_id));
1034 libmesh_assert_less (dofid, this->
end_dof(obj_proc_id));
1038 for (
auto & elem : mesh.element_ptr_range())
1043 for (
auto v : make_range(dofobj->
n_vars(sys_num)))
1044 for (
auto c : make_range(dofobj->
n_comp(sys_num,v)))
1047 libmesh_assert_greater_equal (dofid, this->
first_dof(obj_proc_id));
1048 libmesh_assert_less (dofid, this->
end_dof(obj_proc_id));
1056 #ifdef LIBMESH_ENABLE_AMR
1070 if (this->
variable(v).type().family == SCALAR)
1073 current_SCALAR_dof_index += this->
variable(v).
type().order.get_order();
1080 gf->dofmap_reinit();
1086 gf->dofmap_reinit();
1105 return std::accumulate(dofs_on_proc.begin(), dofs_on_proc.end(),
static_cast<std::size_t
>(0));
1110 const MeshBase & mesh,
1111 unsigned int var_num)
const
1117 const unsigned int sys_num = this->
sys_number();
1125 for (
auto & elem : mesh.active_local_element_ptr_range())
1132 const unsigned int n_nodes = elem->n_nodes();
1135 for (
unsigned int n=0; n<n_nodes; n++)
1137 const Node & node = elem->node_ref(n);
1139 if (node.processor_id() != this->processor_id())
1142 const unsigned int n_comp = node.n_comp(sys_num, var_num);
1143 for(
unsigned int i=0; i<n_comp; i++)
1145 const dof_id_type index = node.dof_number(sys_num,var_num,i);
1148 if (idx.empty() || index > idx.back())
1149 idx.push_back(index);
1154 const unsigned int n_comp = elem->n_comp(sys_num, var_num);
1155 for (
unsigned int i=0; i<n_comp; i++)
1157 const dof_id_type index = elem->dof_number(sys_num,var_num,i);
1158 if (idx.empty() || index > idx.back())
1159 idx.push_back(index);
1172 for (
const auto & node : mesh.local_node_ptr_range())
1174 libmesh_assert(node);
1176 const unsigned int n_comp = node->n_comp(sys_num, var_num);
1177 for (
unsigned int i=0; i<n_comp; i++)
1179 const dof_id_type index = node->dof_number(sys_num,var_num,i);
1180 if (idx.empty() || index > idx.back())
1181 idx.push_back(index);
1187 else if (this->processor_id() == (this->n_processors()-1))
1189 std::vector<dof_id_type> di_scalar;
1191 idx.insert( idx.end(), di_scalar.begin(), di_scalar.end());
1199 const unsigned int sys_num = this->
sys_number();
1207 for (
auto & elem : mesh.active_local_element_ptr_range())
1211 const unsigned int n_nodes = elem->n_nodes();
1214 for (
unsigned int n=0; n<n_nodes; n++)
1216 Node & node = elem->node_ref(n);
1218 for (
unsigned vg=0; vg<n_var_groups; vg++)
1222 if ((vg_description.
type().family != SCALAR) &&
1227 if ((node.n_comp_group(sys_num,vg) > 0) &&
1228 (node.processor_id() == this->processor_id()) &&
1229 (node.vg_dof_base(sys_num,vg) ==
1232 node.set_vg_dof_base(sys_num, vg,
1235 node.n_comp_group(sys_num,vg));
1243 for (
unsigned vg=0; vg<n_var_groups; vg++)
1247 if ((vg_description.
type().family != SCALAR) &&
1249 if (elem->n_comp_group(sys_num,vg) > 0)
1251 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1254 elem->set_vg_dof_base(sys_num,
1259 elem->n_comp(sys_num,vg));
1273 for (
auto & node : mesh.local_node_ptr_range())
1274 for (
unsigned vg=0; vg<n_var_groups; vg++)
1278 if (node->n_comp_group(sys_num,vg))
1281 node->set_vg_dof_base (sys_num,
1286 node->n_comp(sys_num,vg));
1302 const unsigned int sys_num = this->
sys_number();
1310 for (
unsigned vg=0; vg<n_var_groups; vg++)
1314 const unsigned int n_vars_in_group = vg_description.
n_variables();
1317 if (vg_description.
type().family == SCALAR)
1320 for (
auto & elem : mesh.active_local_element_ptr_range())
1328 const unsigned int n_nodes = elem->n_nodes();
1331 for (
unsigned int n=0; n<n_nodes; n++)
1333 Node & node = elem->node_ref(n);
1337 if ((node.n_comp_group(sys_num,vg) > 0) &&
1338 (node.processor_id() == this->processor_id()) &&
1339 (node.vg_dof_base(sys_num,vg) ==
1342 node.set_vg_dof_base(sys_num, vg, next_free_dof);
1344 next_free_dof += (n_vars_in_group*
1345 node.n_comp_group(sys_num,vg));
1350 if (elem->n_comp_group(sys_num,vg) > 0)
1352 libmesh_assert_equal_to (elem->vg_dof_base(sys_num,vg),
1355 elem->set_vg_dof_base(sys_num,
1359 next_free_dof += (n_vars_in_group*
1360 elem->n_comp_group(sys_num,vg));
1372 for (
auto & node : mesh.local_node_ptr_range())
1373 if (node->n_comp_group(sys_num,vg))
1376 node->set_vg_dof_base (sys_num,
1380 next_free_dof += (n_vars_in_group*
1381 node->n_comp_group(sys_num,vg));
1401 if (vg_description.
type().family == SCALAR)
1404 vg_description.
type().order.get_order());
1411 if (this->processor_id() == (this->n_processors()-1))
1420 MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1422 for (
auto & node : mesh.local_node_ptr_range())
1424 unsigned int n_var_g = node->n_var_groups(this->
sys_number());
1425 for (
unsigned int vg=0; vg != n_var_g; ++vg)
1427 unsigned int n_comp_g =
1430 node->vg_dof_base(this->
sys_number(), vg) : 0;
1442 const std::set<GhostingFunctor *>::iterator & gf_begin,
1443 const std::set<GhostingFunctor *>::iterator & gf_end,
1444 const MeshBase::const_element_iterator & elems_begin,
1445 const MeshBase::const_element_iterator & elems_end,
1448 for (
const auto & gf : as_range(gf_begin, gf_end))
1450 GhostingFunctor::map_type more_elements_to_ghost;
1453 (*gf)(elems_begin, elems_end, p, more_elements_to_ghost);
1458 #if defined(LIBMESH_ENABLE_DEPRECATED) && defined(LIBMESH_ENABLE_AMR)
1459 std::vector<std::pair<const Elem*, const CouplingMatrix*>> children_to_couple;
1460 for (
auto it = more_elements_to_ghost.begin();
1461 it != more_elements_to_ghost.end();)
1463 const Elem * elem = it->first;
1464 if (!elem->active())
1466 libmesh_deprecated();
1467 std::vector<const Elem*> children_to_ghost;
1468 elem->active_family_tree(children_to_ghost,
1470 for (
const Elem * child : children_to_ghost)
1471 if (child->processor_id() != p)
1472 children_to_couple.emplace_back(child, it->second);
1474 it = more_elements_to_ghost.erase(it);
1479 more_elements_to_ghost.insert(children_to_couple.begin(),
1480 children_to_couple.end());
1483 for (
const auto & [elem, elem_cm] : more_elements_to_ghost)
1487 libmesh_assert(elem->active());
1489 GhostingFunctor::map_type::iterator existing_it =
1490 elements_to_ghost.find (elem);
1492 if (existing_it == elements_to_ghost.end())
1493 elements_to_ghost.emplace(elem, elem_cm);
1496 if (existing_it->second)
1503 if (temporary_coupling_matrices.empty() ||
1504 !temporary_coupling_matrices.count(existing_it->second))
1510 auto result_pr = temporary_coupling_matrices.insert(std::make_unique<CouplingMatrix>(*existing_it->second));
1511 existing_it->second = result_pr.first->get();
1515 const_cast<CouplingMatrix &
>(*existing_it->second) &= *elem_cm;
1527 auto temp_it = temporary_coupling_matrices.find(existing_it->second);
1528 if (temp_it != temporary_coupling_matrices.end())
1529 temporary_coupling_matrices.erase(temp_it);
1531 existing_it->second =
nullptr;
1546 LOG_SCOPE(
"add_neighbors_to_send_list()",
"DofMap");
1549 if (this->n_processors() == 1)
1554 MeshBase::const_element_iterator local_elem_it
1555 = mesh.active_local_elements_begin();
1556 const MeshBase::const_element_iterator local_elem_end
1557 = mesh.active_local_elements_end();
1559 GhostingFunctor::map_type elements_to_send;
1566 temporary_coupling_matrices,
1569 local_elem_it, local_elem_end, mesh.processor_id());
1572 temporary_coupling_matrices,
1575 local_elem_it, local_elem_end, mesh.processor_id());
1580 std::map<const CouplingMatrix *, std::vector<unsigned int>>
1581 column_variable_lists;
1583 for (
const auto & [partner, ghost_coupling] : elements_to_send)
1586 libmesh_assert_not_equal_to
1587 (partner->processor_id(), this->processor_id());
1594 libmesh_assert_equal_to (ghost_coupling->size(), n_var);
1597 std::map<const CouplingMatrix *, std::vector<unsigned int>>::const_iterator
1598 column_variable_list = column_variable_lists.find(ghost_coupling);
1601 if (column_variable_list == column_variable_lists.end())
1603 auto inserted_variable_list_pair =
1604 column_variable_lists.emplace(ghost_coupling, std::vector<unsigned int>());
1605 column_variable_list = inserted_variable_list_pair.first;
1607 std::vector<unsigned int> & new_variable_list =
1608 inserted_variable_list_pair.first->second;
1610 std::vector<unsigned char> has_variable(n_var,
false);
1612 for (
unsigned int vi = 0; vi != n_var; ++vi)
1614 ConstCouplingRow ccr(vi, *ghost_coupling);
1616 for (
const auto & vj : ccr)
1617 has_variable[vj] =
true;
1619 for (
unsigned int vj = 0; vj != n_var; ++vj)
1621 if (has_variable[vj])
1622 new_variable_list.push_back(vj);
1626 const std::vector<unsigned int> & variable_list =
1627 column_variable_list->second;
1629 for (
const auto & vj : variable_list)
1631 std::vector<dof_id_type> di;
1639 libmesh_assert_less(d, this->
n_dofs());
1646 std::vector<dof_id_type> di;
1650 for (
const auto & dof : di)
1654 libmesh_assert_less(dof, this->
n_dofs());
1662 temporary_coupling_matrices.clear();
1672 for ( ; local_elem_it != local_elem_end; ++local_elem_it)
1674 const Elem * elem = *local_elem_it;
1676 std::vector<dof_id_type> di;
1680 for (
const auto & dof : di)
1684 libmesh_assert_less(dof, this->
n_dofs());
1694 LOG_SCOPE(
"prepare_send_list()",
"DofMap");
1697 if (this->n_processors() == 1)
1706 libMesh::out <<
"WARNING: You have specified both an extra send list function and object.\n"
1707 <<
" Are you sure this is what you meant to do??"
1723 std::vector<dof_id_type>::iterator new_end =
1739 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1764 bool implicit_neighbor_dofs =
1771 if (implicit_neighbor_dofs)
1793 if (!implicit_neighbor_dofs)
1801 bool all_discontinuous_dofs =
true;
1804 if (FEInterface::get_continuity(this->
variable_type(var)) != DISCONTINUOUS)
1805 all_discontinuous_dofs =
false;
1807 if (all_discontinuous_dofs)
1808 implicit_neighbor_dofs =
true;
1811 return implicit_neighbor_dofs;
1825 mat->attach_sparsity_pattern (*
_sp);
1827 mat->update_sparsity_pattern (
_sp->get_sparsity_pattern());
1832 _sp->clear_full_sparsity();
1865 coupling_functor.set_mesh(&
_mesh);
1867 _mesh.add_ghosting_functor(coupling_functor);
1876 _mesh.remove_ghosting_functor(coupling_functor);
1890 evaluable_functor.set_mesh(&
_mesh);
1892 _mesh.add_ghosting_functor(evaluable_functor);
1901 _mesh.remove_ghosting_functor(evaluable_functor);
1911 const std::vector<dof_id_type> & dof_indices_in,
1914 const unsigned int n_original_dofs = dof_indices_in.size();
1916 #ifdef LIBMESH_ENABLE_AMR
1919 libmesh_assert_equal_to (dof_indices_in.size(), Ue.
size());
1920 bool has_constrained_dofs =
false;
1922 for (
unsigned int il=0; il != n_original_dofs; ++il)
1928 libmesh_assert_less (ig, Ug.
size());
1936 if (has_constrained_dofs)
1939 std::vector<dof_id_type> constrained_dof_indices(dof_indices_in);
1946 libmesh_assert_equal_to (dof_indices_in.size(), C.
m());
1947 libmesh_assert_equal_to (constrained_dof_indices.size(), C.
n());
1953 for (
unsigned int i=0; i != n_original_dofs; i++)
1957 const unsigned int n_constrained =
1958 cast_int<unsigned int>(constrained_dof_indices.size());
1959 for (
unsigned int j=0; j<n_constrained; j++)
1961 const dof_id_type jg = constrained_dof_indices[j];
1969 Ue.
el(i) += C(i,j)*Ug(jg);
1978 libmesh_assert_equal_to (n_original_dofs, Ue.
size());
1980 for (
unsigned int il=0; il<n_original_dofs; il++)
1993 std::vector<dof_id_type> & di)
const
2001 libmesh_assert(!elem || elem->active());
2003 LOG_SCOPE(
"dof_indices()",
"DofMap");
2012 std::size_t tot_size = 0;
2015 if (elem && elem->type() == TRI3SUBDIVISION)
2018 const Tri3Subdivision * sd_elem =
static_cast<const Tri3Subdivision *
>(elem);
2021 if (!sd_elem->is_ghost())
2024 std::vector<const Node *> elem_nodes;
2025 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2028 for (
unsigned int vg=0; vg<n_var_groups; vg++)
2031 const unsigned int vars_in_group = var.
n_variables();
2033 if (var.
type().family == SCALAR &&
2036 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2039 tot_size += var.
type().order;
2041 std::vector<dof_id_type> di_new;
2043 di.insert( di.end(), di_new.begin(), di_new.end());
2047 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2051 cast_int<unsigned int>(elem_nodes.size())
2053 , var.
number(vig), tot_size
2064 const unsigned int n_nodes = elem ? elem->n_nodes() : 0;
2065 for (
unsigned int vg=0; vg<n_var_groups; vg++)
2068 const unsigned int vars_in_group = var.
n_variables();
2070 if (var.
type().family == SCALAR &&
2074 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2077 tot_size += var.
type().order;
2079 std::vector<dof_id_type> di_new;
2081 di.insert( di.end(), di_new.begin(), di_new.end());
2085 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2088 elem->get_nodes(), n_nodes
2090 , var.
number(vig), tot_size
2097 libmesh_assert_equal_to (tot_size, di.size());
2103 std::vector<dof_id_type> & di,
2104 const unsigned int vn,
2110 LOG_SCOPE(
"dof_indices()",
"DofMap");
2116 if (p_level == -12345)
2117 p_level = elem ? elem->p_level() : 0;
2121 const unsigned int vig = vn - var.
number();
2125 std::size_t tot_size = 0;
2128 if (elem && elem->type() == TRI3SUBDIVISION)
2131 const Tri3Subdivision * sd_elem =
static_cast<const Tri3Subdivision *
>(elem);
2134 if (!sd_elem->is_ghost())
2137 std::vector<const Node *> elem_nodes;
2138 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2140 _dof_indices(*elem, p_level, di, vg, vig, elem_nodes.data(),
2141 cast_int<unsigned int>(elem_nodes.size())
2152 if (var.
type().family == SCALAR &&
2157 tot_size += var.
type().order;
2159 std::vector<dof_id_type> di_new;
2161 di.insert( di.end(), di_new.begin(), di_new.end());
2164 _dof_indices(*elem, p_level, di, vg, vig, elem->get_nodes(),
2172 libmesh_assert_equal_to (tot_size, di.size());
2178 std::vector<dof_id_type> & di)
const
2183 LOG_SCOPE(
"dof_indices(Node)",
"DofMap");
2189 const unsigned int sys_num = this->
sys_number();
2192 for (
unsigned int vg=0; vg<n_var_groups; vg++)
2195 const unsigned int vars_in_group = var.
n_variables();
2197 if (var.
type().family == SCALAR)
2199 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2201 std::vector<dof_id_type> di_new;
2203 di.insert( di.end(), di_new.begin(), di_new.end());
2208 const int n_comp = node->n_comp_group(sys_num,vg);
2209 for (
unsigned int vig=0; vig != vars_in_group; ++vig)
2211 for (
int i=0; i != n_comp; ++i)
2214 node->dof_number(sys_num, vg, vig, i, n_comp);
2215 libmesh_assert_not_equal_to
2226 std::vector<dof_id_type> & di,
2227 const unsigned int vn)
const
2238 LOG_SCOPE(
"dof_indices(Node)",
"DofMap");
2243 const unsigned int sys_num = this->
sys_number();
2249 if (var.
type().family == SCALAR)
2251 std::vector<dof_id_type> di_new;
2253 di.insert( di.end(), di_new.begin(), di_new.end());
2257 const unsigned int vig = vn - var.
number();
2258 const int n_comp = node->n_comp_group(sys_num,vg);
2259 for (
int i=0; i != n_comp; ++i)
2262 node->dof_number(sys_num, vg, vig, i, n_comp);
2263 libmesh_assert_not_equal_to
2273 std::vector<dof_id_type> & di,
2274 const unsigned int vn)
const
2281 #ifdef LIBMESH_ENABLE_AMR
2285 std::vector<dof_id_type> & di,
2286 const unsigned int vn)
const
2292 #endif // LIBMESH_ENABLE_AMR
2299 std::vector<dof_id_type> & di,
2300 const unsigned int vn)
const
2307 LOG_SCOPE(
"_node_dof_indices()",
"DofMap");
2309 const unsigned int sys_num = this->
sys_number();
2310 const auto [vg, vig] =
2312 const unsigned int n_comp = obj.
n_comp_group(sys_num,vg);
2315 FEType fe_type = var.
type();
2316 const bool extra_hanging_dofs =
2317 FEInterface::extra_hanging_dofs(fe_type);
2319 const bool add_p_level =
2320 #ifdef LIBMESH_ENABLE_AMR
2330 const unsigned int nc =
2331 FEInterface::n_dofs_at_node(fe_type, &elem, n, add_p_level);
2337 if (extra_hanging_dofs && nc && !elem.is_vertex(n))
2339 const int dof_offset = n_comp - nc;
2346 libmesh_assert(!elem.active());
2350 for (
unsigned int i = dof_offset; i != n_comp; ++i)
2365 const unsigned int good_nc =
2366 std::min(static_cast<unsigned int>(n_comp), nc);
2367 for (
unsigned int i=0; i != good_nc; ++i)
2374 for (
unsigned int i=good_nc; i != nc; ++i)
2383 std::vector<dof_id_type> & di,
2384 const unsigned int vg,
2385 const unsigned int vig,
2386 const Node *
const * nodes,
2387 unsigned int n_nodes
2390 const unsigned int v,
2391 std::size_t & tot_size
2399 const ElemType type = elem.type();
2400 const unsigned int sys_num = this->
sys_number();
2401 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2402 const bool is_inf = elem.infinite();
2405 const bool extra_hanging_dofs =
2406 FEInterface::extra_hanging_dofs(var.
type());
2408 FEType fe_type = var.
type();
2410 const bool add_p_level =
2411 #ifdef LIBMESH_ENABLE_AMR
2419 if (var.
type().family == SUBDIVISION)
2420 tot_size += n_nodes;
2424 tot_size += FEInterface::n_dofs(fe_type, add_p_level*p_level, &elem);
2430 const FEInterface::n_dofs_at_node_ptr ndan =
2431 FEInterface::n_dofs_at_node_function(fe_type, &elem);
2434 for (
unsigned int n=0; n != n_nodes; n++)
2436 const Node & node = *nodes[n];
2441 const std::pair<unsigned int, unsigned int>
2442 vg_and_offset = node.var_to_vg_and_offset(sys_num,v);
2443 libmesh_assert_equal_to (vg, vg_and_offset.first);
2444 libmesh_assert_equal_to (vig, vg_and_offset.second);
2446 const unsigned int n_comp = node.n_comp_group(sys_num,vg);
2452 const unsigned int nc =
2453 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2455 FEInterface::n_dofs_at_node(fe_type, add_p_level*p_level, &elem, n) :
2457 ndan (type, static_cast<Order>(fe_type.order + add_p_level*p_level), n);
2463 if (extra_hanging_dofs && !elem.is_vertex(n))
2465 const int dof_offset = n_comp - nc;
2472 libmesh_assert(!elem.active());
2476 for (
int i=
int(n_comp)-1; i>=dof_offset; i--)
2479 node.dof_number(sys_num, vg, vig, i, n_comp);
2492 const unsigned int good_nc = std::min(n_comp, nc);
2493 for (
unsigned int i=0; i!=good_nc; ++i)
2496 node.dof_number(sys_num, vg, vig, i, n_comp);
2498 libmesh_assert_less (d, this->
n_dofs());
2506 for (
unsigned int i=n_comp; i!=nc; ++i)
2512 const unsigned int nc = FEInterface::n_dofs_per_elem(fe_type, add_p_level*p_level, &elem);
2521 const unsigned int n_comp = elem.n_comp_group(sys_num,vg);
2522 if (elem.n_systems() > sys_num && nc <= n_comp)
2524 for (
unsigned int i=0; i<nc; i++)
2527 elem.dof_number(sys_num, vg, vig, i, n_comp);
2535 libmesh_assert(!elem.active() || fe_type.family == LAGRANGE || fe_type.family == SUBDIVISION);
2545 const unsigned int vn,
2546 #ifdef LIBMESH_ENABLE_AMR
2553 LOG_SCOPE(
"SCALAR_dof_indices()",
"DofMap");
2555 libmesh_assert(this->
variable(vn).type().family == SCALAR);
2557 #ifdef LIBMESH_ENABLE_AMR
2571 const int n_dofs_vn = this->
variable(vn).
type().order.get_order();
2573 di.resize(n_dofs_vn);
2574 for (
int i = 0; i != n_dofs_vn; ++i)
2599 for (
const auto & di : dof_indices_in)
2608 template <
typename DofObjectSub
class>
2610 unsigned int var_num)
const
2613 if (obj.processor_id() == this->processor_id())
2616 std::vector<dof_id_type> di;
2628 #ifdef LIBMESH_ENABLE_AMR
2631 std::vector<dof_id_type> & di,
2632 const unsigned int vn)
const
2634 LOG_SCOPE(
"old_dof_indices()",
"DofMap");
2636 libmesh_assert(elem);
2638 const ElemType type = elem->type();
2639 const unsigned int sys_num = this->
sys_number();
2641 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2642 const bool is_inf = elem->infinite();
2648 libmesh_assert(!elem->has_dofs(sys_num) ||
2649 elem->p_refinement_flag() == Elem::JUST_REFINED ||
2650 elem->get_old_dof_object());
2656 std::vector<const Node *> elem_nodes;
2657 const Node *
const * nodes_ptr;
2658 unsigned int n_nodes;
2659 if (elem->type() == TRI3SUBDIVISION)
2662 const Tri3Subdivision * sd_elem =
static_cast<const Tri3Subdivision *
>(elem);
2663 MeshTools::Subdivision::find_one_ring(sd_elem, elem_nodes);
2664 nodes_ptr = elem_nodes.data();
2665 n_nodes = cast_int<unsigned int>(elem_nodes.size());
2670 nodes_ptr = elem->get_nodes();
2671 n_nodes = elem->n_nodes();
2675 for (
unsigned int vg=0; vg<n_var_groups; vg++)
2678 const unsigned int vars_in_group = var.
n_variables();
2680 for (
unsigned int vig=0; vig<vars_in_group; vig++)
2682 const unsigned int v = var.
number(vig);
2685 if (var.
type().family == SCALAR &&
2690 std::vector<dof_id_type> di_new;
2692 di.insert( di.end(), di_new.begin(), di_new.end());
2699 FEType fe_type = var.
type();
2700 const bool add_p_level =
2701 #ifdef LIBMESH_ENABLE_AMR
2709 int p_adjustment = 0;
2710 if (elem->p_refinement_flag() == Elem::JUST_REFINED)
2712 libmesh_assert_greater (elem->p_level(), 0);
2715 else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
2719 p_adjustment *= add_p_level;
2722 int extra_order = int(add_p_level*elem->p_level()) + p_adjustment;
2724 const bool extra_hanging_dofs =
2725 FEInterface::extra_hanging_dofs(fe_type);
2727 const FEInterface::n_dofs_at_node_ptr ndan =
2728 FEInterface::n_dofs_at_node_function(fe_type, elem);
2731 for (
unsigned int n=0; n<n_nodes; n++)
2733 const Node * node = nodes_ptr[n];
2740 const unsigned int nc =
2741 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2743 FEInterface::n_dofs_at_node(var.
type(), extra_order, elem, n) :
2745 ndan (type, static_cast<Order>(var.
type().order + extra_order), n);
2747 const int n_comp = old_dof_obj.
n_comp_group(sys_num,vg);
2753 if (extra_hanging_dofs && !elem->is_vertex(n))
2755 const int dof_offset = n_comp - nc;
2762 libmesh_assert(!elem->active() || elem->refinement_flag() ==
2763 Elem::JUST_COARSENED);
2767 for (
int i=n_comp-1; i>=dof_offset; i--)
2770 old_dof_obj.
dof_number(sys_num, vg, vig, i, n_comp);
2789 const unsigned int old_nc =
2790 std::min(static_cast<unsigned int>(n_comp), nc);
2791 for (
unsigned int i=0; i != old_nc; ++i)
2794 old_dof_obj.
dof_number(sys_num, vg, vig, i, n_comp);
2800 for (
unsigned int i=old_nc; i != nc; ++i)
2806 const unsigned int nc =
2807 FEInterface::n_dofs_per_elem(fe_type, extra_order, elem);
2813 const unsigned int n_comp =
2816 if (old_dof_obj.
n_systems() > sys_num &&
2820 for (
unsigned int i=0; i<nc; i++)
2823 old_dof_obj.
dof_number(sys_num, vg, vig, i, n_comp);
2847 #endif // LIBMESH_ENABLE_AMR
2850 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2854 typedef std::set<dof_id_type> RCSet;
2857 RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
2866 for (
const auto & dof : elem_dofs)
2870 DofConstraints::const_iterator
2884 for (
const auto & pr : constraint_row)
2885 if (!dof_set.count (pr.first))
2887 dof_set.insert (pr.first);
2899 elem_dofs.insert (elem_dofs.end(),
2900 dof_set.begin(), dof_set.end());
2911 #endif // LIBMESH_ENABLE_CONSTRAINTS
2924 std::ostringstream os;
2929 const char * may_equal =
" <= ";
2934 if (mat->need_full_sparsity_pattern())
2938 long double avg_n_nz = 0, avg_n_oz = 0;
2942 for (
const auto & val :
_sp->get_n_nz())
2944 max_n_nz = std::max(max_n_nz, val);
2948 std::size_t n_nz_size =
_sp->get_n_nz().size();
2950 this->comm().max(max_n_nz);
2951 this->comm().sum(avg_n_nz);
2952 this->comm().sum(n_nz_size);
2954 avg_n_nz /= std::max(n_nz_size,std::size_t(1));
2956 for (
const auto & val :
_sp->get_n_oz())
2958 max_n_oz = std::max(max_n_oz, val);
2962 std::size_t n_oz_size =
_sp->get_n_oz().size();
2964 this->comm().max(max_n_oz);
2965 this->comm().sum(avg_n_oz);
2966 this->comm().sum(n_oz_size);
2968 avg_n_oz /= std::max(n_oz_size,std::size_t(1));
2971 os <<
" DofMap Sparsity\n Average On-Processor Bandwidth"
2972 << may_equal << avg_n_nz <<
'\n';
2974 os <<
" Average Off-Processor Bandwidth"
2975 << may_equal << avg_n_oz <<
'\n';
2977 os <<
" Maximum On-Processor Bandwidth"
2978 << may_equal << max_n_nz <<
'\n';
2980 os <<
" Maximum Off-Processor Bandwidth"
2981 << may_equal << max_n_oz << std::endl;
2983 #ifdef LIBMESH_ENABLE_CONSTRAINTS
2985 std::size_t n_constraints = 0, max_constraint_length = 0,
2987 long double avg_constraint_length = 0.;
2995 std::size_t rowsize = row.size();
2997 max_constraint_length = std::max(max_constraint_length,
2999 avg_constraint_length += rowsize;
3006 this->comm().sum(n_constraints);
3007 this->comm().sum(n_rhss);
3008 this->comm().sum(avg_constraint_length);
3009 this->comm().max(max_constraint_length);
3011 os <<
" DofMap Constraints\n Number of DoF Constraints = "
3015 <<
" Number of Heterogenous Constraints= " << n_rhss;
3018 avg_constraint_length /= n_constraints;
3021 <<
" Average DoF Constraint Length= " << avg_constraint_length;
3024 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
3025 std::size_t n_node_constraints = 0, max_node_constraint_length = 0,
3027 long double avg_node_constraint_length = 0.;
3032 if (node->processor_id() != this->processor_id())
3036 std::size_t rowsize = row.size();
3038 max_node_constraint_length = std::max(max_node_constraint_length,
3040 avg_node_constraint_length += rowsize;
3041 n_node_constraints++;
3043 if (pr.second != Point(0))
3047 this->comm().sum(n_node_constraints);
3048 this->comm().sum(n_node_rhss);
3049 this->comm().sum(avg_node_constraint_length);
3050 this->comm().max(max_node_constraint_length);
3052 os <<
"\n Number of Node Constraints = " << n_node_constraints;
3055 <<
" Number of Heterogenous Node Constraints= " << n_node_rhss;
3056 if (n_node_constraints)
3058 avg_node_constraint_length /= n_node_constraints;
3059 os <<
"\n Maximum Node Constraint Length= " << max_node_constraint_length
3061 <<
" Average Node Constraint Length= " << avg_node_constraint_length;
3063 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
3067 #endif // LIBMESH_ENABLE_CONSTRAINTS
3073 template LIBMESH_EXPORT
bool DofMap::is_evaluable<Elem>(
const Elem &,
unsigned int)
const;
3074 template LIBMESH_EXPORT
bool DofMap::is_evaluable<Node>(
const Node &,
unsigned int)
const;
std::vector< VariableGroup > _variable_groups
The finite element type for each variable group.
unsigned int n_comp_group(const unsigned int s, const unsigned int vg) const
std::unique_ptr< SparsityPattern::Build > _sp
The sparsity pattern of the global matrix.
DofObject * elem_ptr(MeshBase &mesh, dof_id_type i) const
T command_line_next(std::string name, T value)
Use GetPot's search()/next() functions to get following arguments from the command line...
bool _implicit_neighbor_dofs_initialized
Bools to indicate if we override the –implicit_neighbor_dofs commandline options. ...
void distribute_local_dofs_node_major(dof_id_type &next_free_dof, MeshBase &mesh)
Distributes the global degrees of freedom for dofs on this processor.
const FEType & type() const
bool _implicit_neighbor_dofs
std::string get_info() const
Gets summary info about the sparsity bandwidth and constraints.
void _node_dof_indices(const Elem &elem, unsigned int n, const DofObject &obj, std::vector< dof_id_type > &di, const unsigned int vn) const
Helper function that implements the element-nodal versions of dof_indices and old_dof_indices.
void print_info(std::ostream &os=libMesh::out) const
Prints summary info about the sparsity bandwidth and constraints.
DefaultCoupling & default_coupling()
Default coupling functor.
void old_dof_indices(const Elem &elem, unsigned int n, std::vector< dof_id_type > &di, const unsigned int vn) const
Appends to the vector di the old global degree of freedom indices for elem.node_ref(n), for one variable vn.
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_begin() const
Beginning of range of algebraic ghosting functors.
unsigned int n() const
返回矩阵的列维度。
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
bool _error_on_constraint_loop
This flag indicates whether or not we do an opt-mode check for the presence of constraint loops...
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
void * _extra_sparsity_context
A pointer associated with the extra sparsity that can optionally be passed in.
const FEType & variable_type(const unsigned int c) const
std::size_t distribute_dofs(MeshBase &)
Distribute dofs on the current mesh.
void set_implicit_neighbor_dofs(bool implicit_neighbor_dofs)
Allow the implicit_neighbor_dofs flag to be set programmatically.
void build_constraint_matrix_and_vector(DenseMatrix< Number > &C, DenseVector< Number > &H, std::vector< dof_id_type > &elem_dofs, int qoi_index=-1, const bool called_recursively=false) const
Build the constraint matrix C and the forcing vector H associated with the element degree of freedom ...
void add_default_ghosting()
Add the default functor(s) for coupling and algebraic ghosting.
We're using a class instead of a typedef to allow forward declarations and future flexibility...
virtual numeric_index_type size() const =0
获取向量的大小。
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
Beginning of range of coupling functors.
void _dof_indices(const Elem &elem, int p_level, std::vector< dof_id_type > &di, const unsigned int vg, const unsigned int vig, const Node *const *nodes, unsigned int n_nodes#ifdef DEBUG, const unsigned int v, std::size_t &tot_size#endif) const
Helper function that gets the dof indices on the current element for a non-SCALAR type variable...
std::vector< dof_id_type > _send_list
A list containing all the global DOF indices that affect the solution on my processor.
void set_verify_dirichlet_bc_consistency(bool val)
Set the _verify_dirichlet_bc_consistency flag.
bool is_attached(SparseMatrix< Number > &matrix)
Matrices should not be attached more than once.
void attach_matrix(SparseMatrix< Number > &matrix)
Additional matrices may be attached to this DofMap.
DofObject * node_ptr(MeshBase &mesh, dof_id_type i) const
void clear_send_list()
Clears the _send_list vector.
DefaultCoupling & default_algebraic_ghosting()
Default algebraic ghosting functor.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
void attach_sparsity_pattern(const SparsityPattern::Build &sp)
设置要使用的稀疏性模式的指针。在矩阵需要比系统中的大(或更小以提高效率)的模式, 或者在 DofMap 未计算系统稀疏性模式的情况下使用。
std::set< GhostingFunctor * > _algebraic_ghosting_functors
The list of all GhostingFunctor objects to be used when distributing ghosted vectors.
std::vector< dof_id_type > _end_old_df
Last old DOF index (plus 1) on processor p.
std::pair< unsigned int, unsigned int > var_to_vg_and_offset(const unsigned int s, const unsigned int var) const
void local_variable_indices(std::vector< dof_id_type > &idx, const MeshBase &mesh, unsigned int var_num) const
Fills an array of those dof indices which belong to the given variable number and live on the current...
void set_vg_dof_base(const unsigned int s, const unsigned int vg, const dof_id_type db)
VariableGroup DoF indices are indexed as id = base + var_in_vg*ncomp + comp This method allows for di...
void invalidate_dofs(MeshBase &mesh) const
Invalidates all active DofObject dofs for this system.
virtual void augment_send_list(std::vector< dof_id_type > &send_list)=0
User-defined function to augment the send list.
bool local_index(dof_id_type dof_index) const
const Variable & variable(const unsigned int c) const
dof_id_type n_dofs() const
virtual void zero()=0
将向量中的每个元素设置为0。由于派生类中的存储方法可能不同,需要将其声明为纯虚函数。
void set_error_on_constraint_loop(bool error_on_constraint_loop)
const VariableGroup & variable_group(const unsigned int c) const
void add_coupling_functor(GhostingFunctor &coupling_functor, bool to_mesh=true)
Adds a functor which can specify coupling requirements for creation of sparse matrices.
std::vector< dof_id_type > _first_old_df
First old DOF index on processor p.
uint8_t processor_id_type
std::vector< dof_id_type > _first_scalar_df
First DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
AdjointDofConstraintValues _adjoint_constraint_values
bool _constrained_sparsity_construction
This flag indicates whether or not we explicitly take constraint equations into account when computin...
AugmentSendList * _augment_send_list
Function object to call to add extra entries to the send list.
bool need_full_sparsity_pattern
Default false; set to true if any attached matrix requires a full sparsity pattern.
这是一个通用的稀疏矩阵类。该类包含了必须在派生类中覆盖的纯虚拟成员。 使用一个公共的基类允许从不同的求解器包中以不同的格式统一访问稀疏矩阵。
dof_id_type vg_dof_base(const unsigned int s, const unsigned int vg) const
VariableGroup DoF indices are indexed as id = base + var_in_vg*ncomp + comp This method allows for di...
void reinit_send_list(MeshBase &mesh)
Clears the _send_list vector and then rebuilds it.
bool is_constrained_dof(const dof_id_type dof) const
std::unordered_map< unsigned int, unsigned int > _var_to_vg
A map from variable number to variable group number.
This class defines the notion of a variable in the system.
void add_neighbors_to_send_list(MeshBase &mesh)
Adds entries to the _send_list vector corresponding to DoFs on elements neighboring the current proce...
std::vector< dof_id_type > _first_old_scalar_df
First old DOF index for SCALAR variable v, or garbage for non-SCALAR variable v.
dof_id_type _n_SCALAR_dofs
The total number of SCALAR dofs associated to all SCALAR variables.
void assert_no_nodes_missed(MeshBase &mesh)
void set_nonlocal_dof_objects(iterator_type objects_begin, iterator_type objects_end, MeshBase &mesh, dofobject_accessor objects)
Helper function for distributing dofs in parallel.
unsigned int m() const
返回矩阵的行维度。
std::set< std::unique_ptr< CouplingMatrix >, Utility::CompareUnderlying > CouplingMatricesSet
unsigned int number(unsigned int v) const
virtual unsigned int size() const =0
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
bool is_periodic_boundary(const boundary_id_type boundaryid) const
unsigned int n_var_groups(const unsigned int s) const
unsigned int n_variables() const
void add_variable_group(VariableGroup var_group)
Add an unknown of order order and finite element type type to the system of equations.
We're using a class instead of a typedef to allow forward declarations and future flexibility...
bool active_on_subdomain(subdomain_id_type sid) const
virtual bool need_full_sparsity_pattern() const
void clear()
Free all new memory associated with the object, but restore its original state, with the mesh pointer...
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
DofConstraints _dof_constraints
Data structure containing DOF constraints.
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling...
void reinit(MeshBase &mesh)
Reinitialize the underlying data structures conformal to the current mesh.
DofMap(const unsigned int sys_number, MeshBase &mesh)
Constructor.
CouplingMatrix * _dof_coupling
Degree of freedom coupling.
unsigned int n_variable_groups() const
unsigned int sys_number() const
void * _extra_send_list_context
A pointer associated with the extra send list that can optionally be passed in.
This class defines a logically grouped set of variables in the system.
void set_n_comp_group(const unsigned int s, const unsigned int vg, const unsigned int ncomp)
Sets the number of components for VariableGroup vg of system s associated with this DofObject...
bool semilocal_index(dof_id_type dof_index) const
void update_sparsity_pattern(SparseMatrix< Number > &matrix) const
Additional matrices may be be temporarily initialized by this DofMap.
DofObject & get_old_dof_object_ref()
As above, but do not use in situations where the old_dof_object may be nullptr, since this function a...
std::set< GhostingFunctor * >::const_iterator algebraic_ghosting_functors_end() const
End of range of algebraic ghosting functors.
std::vector< SparseMatrix< Number > * > _matrices
Additional matrices handled by this object.
dof_id_type end_dof() const
void attach_dof_map(const DofMap &dof_map)
设置要使用的 DofMap 的指针。如果不使用单独的稀疏性模式, 则使用来自 DofMap 的模式。
void distribute_scalar_dofs(dof_id_type &next_free_dof)
unsigned int n_variables() const
virtual numeric_index_type first_local_index() const =0
获取实际存储在该处理器上的第一个向量元素的索引。
std::unique_ptr< PeriodicBoundaries > _periodic_boundaries
Data structure containing periodic boundaries.
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn...
void remove_coupling_functor(GhostingFunctor &coupling_functor)
Removes a functor which was previously added to the set of coupling functors, from both this DofMap a...
virtual void update_sparsity_pattern(const SparsityPattern::Graph &)
更新矩阵的稀疏性模式。当您的 SparseMatrix<T> 实现不需要此数据时, 只需不覆盖此方法。
void process_constraints(MeshBase &)
Postprocesses any constrained degrees of freedom to be constrained only in terms of unconstrained dof...
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, CouplingMatricesSet &temporary_coupling_matrices, const std::set< GhostingFunctor * >::iterator &gf_begin, const std::set< GhostingFunctor * >::iterator &gf_end, const MeshBase::const_element_iterator &elems_begin, const MeshBase::const_element_iterator &elems_end, processor_id_type p)
dof_id_type n_old_dofs() const
bool _verify_dirichlet_bc_consistency
Flag which determines whether we should do some additional checking of the consistency of the Dirichl...
std::unique_ptr< DefaultCoupling > _default_coupling
The default coupling GhostingFunctor, used to implement standard libMesh sparsity pattern constructio...
DofConstraintValueMap _primal_constraint_values
std::vector< Variable > _variables
The finite element type for each variable.
DofConstraints _stashed_dof_constraints
void remove_default_ghosting()
Remove any default ghosting functor(s).
SparsityPattern::AugmentSparsityPattern * _augment_sparsity_pattern
Function object to call to add extra entries to the sparsity pattern.
std::map< dof_id_type, Real, std::less< dof_id_type >, Threads::scalable_allocator< std::pair< const dof_id_type, Real > > > DofConstraintRow
A row of the Dof constraint matrix.
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
dof_id_type _n_old_dfs
Total number of degrees of freedom on old dof objects.
void clear_sparsity()
Clears the sparsity pattern.
bool all_semilocal_indices(const std::vector< dof_id_type > &dof_indices) const
std::set< GhostingFunctor * > _coupling_functors
The list of all GhostingFunctor objects to be used when coupling degrees of freedom in matrix sparsit...
std::unordered_set< unsigned int > _dont_p_refine
A container of variable groups that we should not p-refine.
std::vector< dof_id_type > _end_df
Last DOF index (plus 1) on processor p.
dof_id_type n_SCALAR_dofs() const
std::vector< dof_id_type > _first_df
First DOF index on processor p.
定义用于有限元计算的抽象稠密向量基类。 可以从这个类派生出特定的稠密向量,例如 DenseSubVectors。
std::map< const Node *, Real, std::less< const Node * >, Threads::scalable_allocator< std::pair< const Node *const, Real > > > NodeConstraintRow
A row of the Node constraint mapping.
MeshBase & _mesh
The mesh that system uses.
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
Finds all the DOFS associated with the element DOFs elem_dofs.
void prepare_send_list()
Takes the _send_list vector (which may have duplicate entries) and sorts it.
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
bool on_command_line(std::string arg)
void(* _extra_sparsity_function)(SparsityPattern::Graph &, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz, void *)
A function pointer to a function to call to add extra entries to the sparsity pattern.
std::unique_ptr< DefaultCoupling > _default_evaluating
The default algebraic GhostingFunctor, used to implement standard libMesh send_list construction...
void(* _extra_send_list_function)(std::vector< dof_id_type > &, void *)
A function pointer to a function to call to add extra entries to the send list.
std::vector< unsigned int > _variable_group_numbers
The variable group number for each variable.
std::map< GhostingFunctor *, std::shared_ptr< GhostingFunctor > > _shared_functors
Hang on to references to any GhostingFunctor objects we were passed in shared_ptr form...
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
End of range of coupling functors.
void remove_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor)
Removes a functor which was previously added to the set of algebraic ghosting functors, from both this DofMap and from the underlying mesh.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
void compute_sparsity(const MeshBase &)
Computes the sparsity pattern for the matrices corresponding to proc_id and sends that data to Linear...
unsigned int n_systems() const
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors...
virtual T el(const unsigned int i) const =0
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
bool use_coupled_neighbor_dofs(const MeshBase &mesh) const
Tells other library functions whether or not this problem includes coupling between dofs in neighbori...
void set_error_on_cyclic_constraint(bool error_on_cyclic_constraint)
Specify whether or not we perform an extra (opt-mode enabled) check for constraint loops...
void extract_local_vector(const NumericVector< Number > &Ug, const std::vector< dof_id_type > &dof_indices, DenseVectorBase< Number > &Ue) const
Builds the local element vector Ue from the global vector Ug, accounting for any constrained degrees ...
bool is_evaluable(const DofObjectSubclass &obj, unsigned int var_num=libMesh::invalid_uint) const
virtual numeric_index_type last_local_index() const =0
获取实际存储在该处理器上的最后一个向量元素的索引+1。
void distribute_local_dofs_var_major(dof_id_type &next_free_dof, MeshBase &mesh)
Distributes the global degrees of freedom, for dofs on this processor.
dof_id_type first_dof() const
dof_id_type _n_dfs
Total number of degrees of freedom.
processor_id_type processor_id() const
NodeConstraints _node_constraints
Data structure containing DofObject constraints.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.