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);