21 #include "libmesh/sparsity_pattern.h"
24 #include "libmesh/coupling_matrix.h"
25 #include "libmesh/dof_map.h"
26 #include "libmesh/elem.h"
27 #include "libmesh/ghosting_functor.h"
28 #include "libmesh/hashword.h"
29 #include "libmesh/parallel_algebra.h"
30 #include "libmesh/parallel.h"
38 namespace SparsityPattern
47 const std::set<GhostingFunctor *> & coupling_functors_in,
48 const bool implicit_neighbor_dofs_in,
49 const bool need_full_sparsity_pattern_in) :
53 dof_coupling(dof_coupling_in),
54 coupling_functors(coupling_functors_in),
55 implicit_neighbor_dofs(implicit_neighbor_dofs_in),
56 need_full_sparsity_pattern(need_full_sparsity_pattern_in),
68 dof_map(other.dof_map),
69 dof_coupling(other.dof_coupling),
70 coupling_functors(other.coupling_functors),
71 implicit_neighbor_dofs(other.implicit_neighbor_dofs),
72 need_full_sparsity_pattern(other.need_full_sparsity_pattern),
73 hashed_dof_sets(other.hashed_dof_sets),
82 #if defined(__GNUC__) && (__GNUC__ < 4) && !defined(__INTEL_COMPILER)
91 std::vector<dof_id_type> & dofs_vi,
95 #ifdef LIBMESH_ENABLE_CONSTRAINTS
100 std::sort(dofs_vi.begin(), dofs_vi.end());
106 const std::vector<dof_id_type> & element_dofs_j)
108 const unsigned int n_dofs_on_element_i =
109 cast_int<unsigned int>(element_dofs_i.size());
115 std::vector<dof_id_type>
118 const unsigned int n_dofs_on_element_j =
119 cast_int<unsigned int>(element_dofs_j.size());
128 bool dofs_seen =
false;
129 if (n_dofs_on_element_j > 0 && n_dofs_on_element_i > 256)
136 dofs_seen = !result.second;
142 if (n_dofs_on_element_j > 0 && !dofs_seen)
144 for (
unsigned int i=0; i<n_dofs_on_element_i; i++)
153 if ((ig >= first_dof_on_proc) &&
154 (ig < end_dof_on_proc))
160 libmesh_assert_greater_equal (ig, first_dof_on_proc);
175 row->insert(row->end(),
176 element_dofs_j.begin(),
177 element_dofs_j.end());
187 SparsityPattern::Row::iterator
188 low = std::lower_bound
189 (row->begin(), row->end(), element_dofs_j.front()),
190 high = std::upper_bound
191 (low, row->end(), element_dofs_j.back());
193 for (
unsigned int j=0; j<n_dofs_on_element_j; j++)
198 std::pair<SparsityPattern::Row::iterator,
199 SparsityPattern::Row::iterator>
200 pos = std::equal_range (low, high, jg);
203 if (pos.first == pos.second)
204 dofs_to_add.push_back(jg);
213 if (!dofs_to_add.empty())
215 const std::size_t old_size = row->size();
217 row->insert (row->end(),
222 (row->begin(), row->begin()+old_size,
249 std::vector<std::vector<dof_id_type> > element_dofs_i(n_var);
251 std::vector<const Elem *> coupled_neighbors;
252 for (
const auto & elem : range)
256 Elem *
const * elempp = const_cast<Elem * const *>(&elem);
257 Elem *
const * elemend = elempp+1;
272 std::set<CouplingMatrix *> temporary_coupling_matrices;
275 temporary_coupling_matrices,
281 for (
unsigned int vi=0; vi<n_var; vi++)
284 for (
unsigned int vi=0; vi<n_var; vi++)
285 for (
const auto & pr : elements_to_couple)
287 const Elem *
const partner = pr.first;
294 libmesh_assert_equal_to (ghost_coupling->
size(), n_var);
297 for (
const auto &
idx : ccr)
303 std::vector<dof_id_type> partner_dofs;
311 for (
unsigned int vj = 0; vj != n_var; ++vj)
314 this->
handle_vi_vj(element_dofs_i[vi], element_dofs_i[vj]);
317 std::vector<dof_id_type> partner_dofs;
325 for (
auto & mat : temporary_coupling_matrices)
343 n_nz.resize (n_dofs_on_proc, 0);
344 n_oz.resize (n_dofs_on_proc, 0);
351 for (
const auto & df : row)
352 if ((df < first_dof_on_proc) || (df >= end_dof_on_proc))
392 else if (!their_row.empty())
394 my_row.insert (my_row.end(),
401 std::sort (my_row.begin(), my_row.end());
403 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
409 for (
const auto & df : my_row)
410 if ((df < first_dof_on_proc) || (df >= end_dof_on_proc))
418 n_nz[r] = std::min(
n_nz[r], n_dofs_on_proc);
420 n_oz[r] =std::min(
n_oz[r], static_cast<dof_id_type>(n_global_dofs-
n_nz[r]));
452 my_row.insert (my_row.end(),
459 std::sort (my_row.begin(), my_row.end());
461 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
474 parallel_object_only();
478 auto pid =
comm.rank();
479 auto num_procs =
comm.size();
481 auto dof_tag =
comm.get_unique_tag();
482 auto row_tag =
comm.get_unique_tag();
490 std::map<processor_id_type, std::pair<std::vector<dof_id_type>, std::vector<Row>>> data_to_send;
493 std::vector<char> will_send_to(num_procs);
501 const auto dof_id = it->first;
502 auto & row = it->second;
509 if (!will_send_to[proc_id])
512 will_send_to[proc_id] =
true;
515 auto & proc_data = data_to_send[proc_id];
517 proc_data.first.push_back(dof_id);
520 proc_data.second.emplace_back(std::move(row));
527 comm.alltoall(will_send_to);
531 auto & will_receive_from = will_send_to;
533 std::vector<Parallel::Request> dof_sends(num_sends);
534 std::vector<Parallel::Request> row_sends(num_sends);
538 for (
auto & proc_data : data_to_send)
540 auto proc_id = proc_data.first;
542 auto & dofs = proc_data.second.first;
543 auto & rows = proc_data.second.second;
545 comm.send(proc_id, dofs, dof_sends[current_send], dof_tag);
546 comm.send(proc_id, rows, row_sends[current_send], row_tag);
554 std::vector<processor_id_type> receiving_from;
557 auto will = will_receive_from[proc_id];
562 receiving_from.push_back(proc_id);
567 for (
auto proc_id : receiving_from)
569 std::vector<dof_id_type> in_dofs;
570 std::vector<Row> in_rows;
573 comm.receive(proc_id, in_dofs, dof_tag);
574 comm.receive(proc_id, in_rows, row_tag);
576 const std::size_t n_rows = in_dofs.size();
577 for (std::size_t i = 0; i != n_rows; ++i)
579 const auto r = in_dofs[i];
580 const auto my_r = r - local_first_dof;
582 auto & their_row = in_rows[i];
595 my_row.assign (their_row.begin(), their_row.end());
599 my_row.insert (my_row.end(),
606 std::sort (my_row.begin(), my_row.end());
608 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
614 for (
const auto & df : my_row)
615 if ((df < local_first_dof) || (df >= local_end_dof))
622 for (
const auto & df : their_row)
623 if ((df < local_first_dof) || (df >= local_end_dof))
628 n_nz[my_r] = std::min(
n_nz[my_r], n_dofs_on_proc);
630 static_cast<dof_id_type>(n_global_dofs-
n_nz[my_r]));
639 Parallel::wait(dof_sends);
640 Parallel::wait(row_sends);