32 namespace SparsityPattern
41 std::set<GhostingFunctor *> coupling_functors_in,
42 const bool implicit_neighbor_dofs_in,
43 const bool need_full_sparsity_pattern_in) :
47 dof_coupling(dof_coupling_in),
48 coupling_functors(coupling_functors_in),
49 implicit_neighbor_dofs(implicit_neighbor_dofs_in),
50 need_full_sparsity_pattern(need_full_sparsity_pattern_in),
62 dof_map(other.dof_map),
63 dof_coupling(other.dof_coupling),
64 coupling_functors(other.coupling_functors),
65 implicit_neighbor_dofs(other.implicit_neighbor_dofs),
66 need_full_sparsity_pattern(other.need_full_sparsity_pattern),
75 #if defined(__GNUC__) && (__GNUC__ < 4) && !defined(__INTEL_COMPILER) 84 std::vector<dof_id_type> & dofs_vi,
88 #ifdef LIBMESH_ENABLE_CONSTRAINTS 93 std::sort(dofs_vi.begin(), dofs_vi.end());
99 const std::vector<dof_id_type> & element_dofs_j)
101 const unsigned int n_dofs_on_element_i =
102 cast_int<unsigned int>(element_dofs_i.size());
108 std::vector<dof_id_type>
111 const unsigned int n_dofs_on_element_j =
112 cast_int<unsigned int>(element_dofs_j.size());
117 if (n_dofs_on_element_j > 0)
119 for (
unsigned int i=0; i<n_dofs_on_element_i; i++)
128 if ((ig >= first_dof_on_proc) &&
129 (ig < end_dof_on_proc))
135 libmesh_assert_greater_equal (ig, first_dof_on_proc);
150 row->insert(row->end(),
151 element_dofs_j.begin(),
152 element_dofs_j.end());
162 SparsityPattern::Row::iterator
163 low = std::lower_bound
164 (row->begin(), row->end(), element_dofs_j.front()),
165 high = std::upper_bound
166 (low, row->end(), element_dofs_j.back());
168 for (
unsigned int j=0; j<n_dofs_on_element_j; j++)
173 std::pair<SparsityPattern::Row::iterator,
174 SparsityPattern::Row::iterator>
175 pos = std::equal_range (low, high, jg);
178 if (pos.first == pos.second)
179 dofs_to_add.push_back(jg);
188 if (!dofs_to_add.empty())
190 const std::size_t old_size = row->size();
192 row->insert (row->end(),
197 (row->begin(), row->begin()+old_size,
224 std::vector<std::vector<dof_id_type> > element_dofs_i(n_var);
226 std::vector<const Elem *> coupled_neighbors;
227 for (
const auto & elem : range)
231 Elem *
const * elempp =
const_cast<Elem *
const *
>(&elem);
232 Elem *
const * elemend = elempp+1;
247 std::set<CouplingMatrix *> temporary_coupling_matrices;
250 temporary_coupling_matrices,
256 for (
unsigned int vi=0; vi<n_var; vi++)
259 for (
unsigned int vi=0; vi<n_var; vi++)
260 for (
const auto & pr : elements_to_couple)
262 const Elem *
const partner = pr.first;
269 libmesh_assert_equal_to (ghost_coupling->
size(), n_var);
272 for (
const auto &
idx : ccr)
278 std::vector<dof_id_type> partner_dofs;
286 for (
unsigned int vj = 0; vj != n_var; ++vj)
289 this->
handle_vi_vj(element_dofs_i[vi], element_dofs_i[vj]);
292 std::vector<dof_id_type> partner_dofs;
300 for (
auto & mat : temporary_coupling_matrices)
318 n_nz.resize (n_dofs_on_proc, 0);
319 n_oz.resize (n_dofs_on_proc, 0);
326 for (
const auto & df : row)
327 if ((df < first_dof_on_proc) || (df >= end_dof_on_proc))
367 else if (!their_row.empty())
369 my_row.insert (my_row.end(),
376 std::sort (my_row.begin(), my_row.end());
378 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
384 for (
const auto & df : my_row)
385 if ((df < first_dof_on_proc) || (df >= end_dof_on_proc))
415 libmesh_assert (!their_row.empty());
427 my_row.insert (my_row.end(),
434 std::sort (my_row.begin(), my_row.end());
436 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
445 parallel_object_only();
461 std::map<processor_id_type, std::pair<std::vector<dof_id_type>, std::vector<Row>>> data_to_send;
464 std::vector<char> will_send_to(num_procs);
472 const auto dof_id = it->first;
473 auto & row = it->second;
480 if (!will_send_to[proc_id])
483 will_send_to[proc_id] =
true;
486 auto & proc_data = data_to_send[proc_id];
488 proc_data.first.push_back(
dof_id);
491 proc_data.second.emplace_back(std::move(row));
502 auto & will_receive_from = will_send_to;
504 std::vector<Parallel::Request> dof_sends(num_sends);
505 std::vector<Parallel::Request> row_sends(num_sends);
509 for (
auto & proc_data : data_to_send)
511 auto proc_id = proc_data.first;
513 auto & dofs = proc_data.second.first;
514 auto & rows = proc_data.second.second;
516 comm.
send(proc_id, dofs, dof_sends[current_send], dof_tag);
517 comm.
send(proc_id, rows, row_sends[current_send], row_tag);
525 std::vector<processor_id_type> receiving_from;
528 auto will = will_receive_from[proc_id];
533 receiving_from.push_back(proc_id);
538 for (
auto proc_id : receiving_from)
540 std::vector<dof_id_type> in_dofs;
541 std::vector<Row> in_rows;
547 const std::size_t n_rows = in_dofs.
size();
548 for (std::size_t i = 0; i != n_rows; ++i)
550 const auto r = in_dofs[i];
551 const auto my_r = r - local_first_dof;
553 auto & their_row = in_rows[i];
560 libmesh_assert(!their_row.empty());
566 my_row.assign (their_row.begin(), their_row.end());
570 my_row.insert (my_row.end(),
577 std::sort (my_row.begin(), my_row.end());
579 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
585 for (
const auto & df : my_row)
586 if ((df < local_first_dof) || (df >= local_end_dof))
593 for (
const auto & df : their_row)
594 if ((df < local_first_dof) || (df >= local_end_dof))
601 static_cast<dof_id_type>(n_global_dofs-
n_nz[my_r]));
void find_connected_dofs(std::vector< dof_id_type > &elem_dofs) const
SparsityPattern::Graph sparsity_pattern
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
void wait(std::vector< Request > &r)
std::set< GhostingFunctor * >::const_iterator coupling_functors_begin() const
dof_id_type n_dofs_on_processor(const processor_id_type proc) const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
processor_id_type size() const
The base class for all geometric element types.
uint8_t processor_id_type
unsigned int n_variables() const
void alltoall(std::vector< T, A > &r) const
const Parallel::Communicator & comm() const
const bool need_full_sparsity_pattern
MessageTag get_unique_tag(int tagvalue) const
Utility class for defining generic ranges for threading.
Manages the degrees of freedom (DOFs) in a simulation.
std::vector< dof_id_type, Threads::scalable_allocator< dof_id_type > > Row
void join(const Build &other)
dof_id_type n_dofs() const
processor_id_type rank() const
static const processor_id_type invalid_processor_id
void sorted_connected_dofs(const Elem *elem, std::vector< dof_id_type > &dofs_vi, unsigned int vi)
std::unordered_map< const Elem *, const CouplingMatrix * > map_type
void _dummy_function(void)
std::vector< dof_id_type > n_nz
An object whose state is distributed along a set of processors.
unsigned int size(const data_type &type) const
SparsityPattern::NonlocalGraph nonlocal_pattern
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Build(const MeshBase &mesh_in, const DofMap &dof_map_in, const CouplingMatrix *dof_coupling_in, std::set< GhostingFunctor *> coupling_functors_in, const bool implicit_neighbor_dofs_in, const bool need_full_sparsity_pattern_in)
std::set< GhostingFunctor * >::const_iterator coupling_functors_end() const
void handle_vi_vj(const std::vector< dof_id_type > &element_dofs_i, const std::vector< dof_id_type > &element_dofs_j)
void operator()(const ConstElemRange &range)
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
processor_id_type processor_id() const
unsigned int size() const
long double min(long double a, double b)
static void merge_ghost_functor_outputs(GhostingFunctor::map_type &elements_to_ghost, std::set< CouplingMatrix *> &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)
Defines the coupling between variables of a System.
static void sort_row(const BidirectionalIterator begin, BidirectionalIterator middle, const BidirectionalIterator end)
std::vector< dof_id_type > n_oz