17 #include <deal.II/base/exceptions.h> 18 #include <deal.II/lac/exceptions.h> 19 #include <deal.II/lac/sparsity_pattern.h> 20 #include <deal.II/lac/sparsity_tools.h> 26 #ifdef DEAL_II_WITH_MPI 27 #include <deal.II/base/utilities.h> 28 #include <deal.II/lac/dynamic_sparsity_pattern.h> 29 #include <deal.II/lac/block_sparsity_pattern.h> 32 #ifdef DEAL_II_WITH_METIS 33 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
42 DEAL_II_NAMESPACE_OPEN
48 const unsigned int n_partitions,
49 std::vector<unsigned int> &partition_indices)
54 SparsityPattern::ExcNotCompressed());
56 Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
57 Assert (partition_indices.size() == sparsity_pattern.
n_rows(),
58 ExcInvalidArraySize (partition_indices.size(),
59 sparsity_pattern.
n_rows()));
62 if (n_partitions == 1 || (sparsity_pattern.
n_rows()==1))
64 std::fill_n (partition_indices.begin(), partition_indices.size(), 0U);
70 #ifndef DEAL_II_WITH_METIS 71 (void)sparsity_pattern;
81 n =
static_cast<signed int>(sparsity_pattern.
n_rows()),
83 nparts = static_cast<int>(n_partitions),
92 nparts = std::min(n, nparts);
95 idx_t options[METIS_NOPTIONS];
96 METIS_SetDefaultOptions (options);
100 std::vector<idx_t> int_rowstart(1);
101 int_rowstart.reserve(sparsity_pattern.
n_rows()+1);
102 std::vector<idx_t> int_colnums;
107 col < sparsity_pattern.
end(row); ++col)
108 int_colnums.push_back(col->column());
109 int_rowstart.push_back(int_colnums.size());
112 std::vector<idx_t> int_partition_indices (sparsity_pattern.
n_rows());
121 ierr = METIS_PartGraphRecursive(&n, &ncon, &int_rowstart[0], &int_colnums[0],
123 &nparts,NULL,NULL,&options[0],
124 &dummy,&int_partition_indices[0]);
128 ierr = METIS_PartGraphKway(&n, &ncon, &int_rowstart[0], &int_colnums[0],
130 &nparts,NULL,NULL,&options[0],
131 &dummy,&int_partition_indices[0]);
138 std::copy (int_partition_indices.begin(),
139 int_partition_indices.end(),
140 partition_indices.begin());
154 const std::vector<DynamicSparsityPattern::size_type> &new_indices)
162 if (sparsity.
row_length(row) < min_coordination)
165 starting_point = row;
189 return starting_point;
197 std::vector<DynamicSparsityPattern::size_type> &new_indices,
198 const std::vector<DynamicSparsityPattern::size_type> &starting_indices)
201 ExcDimensionMismatch (sparsity.
n_rows(), sparsity.
n_cols()));
203 ExcDimensionMismatch (sparsity.
n_rows(), new_indices.size()));
205 ExcMessage (
"You can't specify more starting indices than there are rows"));
208 ExcMessage(
"Only valid for sparsity patterns which store all rows."));
215 std::vector<DynamicSparsityPattern::size_type> last_round_dofs (starting_indices);
218 std::fill (new_indices.begin(), new_indices.end(),
224 (last_round_dofs[i]>=sparsity.
n_rows()))
227 std::remove_if (last_round_dofs.begin(), last_round_dofs.end(),
228 std::bind2nd(std::equal_to<DynamicSparsityPattern::size_type>(),
232 if (last_round_dofs.empty())
234 .push_back (internal::find_unnumbered_starting_index (sparsity,
242 new_indices[last_round_dofs[i]] = next_free_number++;
248 std::vector<DynamicSparsityPattern::size_type> next_round_dofs;
253 j<sparsity.
end(last_round_dofs[i]); ++j)
254 next_round_dofs.push_back (j->column());
257 std::sort (next_round_dofs.begin(), next_round_dofs.end());
260 std::vector<DynamicSparsityPattern::size_type>::iterator end_sorted;
261 end_sorted = std::unique (next_round_dofs.begin(), next_round_dofs.end());
262 next_round_dofs.erase (end_sorted, next_round_dofs.end());
265 for (
int s=next_round_dofs.size()-1; s>=0; --s)
267 next_round_dofs.erase (next_round_dofs.begin() + s);
273 if (next_round_dofs.empty())
275 if (std::find (new_indices.begin(), new_indices.end(),
287 Assert (starting_indices.empty(),
288 ExcMessage (
"The input graph appears to have more than one " 289 "component, but as stated in the documentation " 290 "we only want to reorder such graphs if no " 291 "starting indices are given. The function was " 292 "called with starting indices, however."))
295 .push_back (internal::find_unnumbered_starting_index (sparsity,
303 std::multimap<DynamicSparsityPattern::size_type, int> dofs_by_coordination;
306 for (std::vector<DynamicSparsityPattern::size_type>::iterator s=next_round_dofs.begin();
307 s!=next_round_dofs.end(); ++s)
312 const std::pair<const DynamicSparsityPattern::size_type, int> new_entry (coordination, *s);
313 dofs_by_coordination.insert (new_entry);
317 std::multimap<DynamicSparsityPattern::size_type, int>::iterator i;
318 for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i)
319 new_indices[i->second] = next_free_number++;
322 last_round_dofs = next_round_dofs;
332 (next_free_number == sparsity.
n_rows()),
340 std::vector<SparsityPattern::size_type> &new_indices,
341 const std::vector<SparsityPattern::size_type> &starting_indices)
344 for (
unsigned int row=0; row<sparsity.
n_rows(); ++row)
348 dsp.
add(row, it->column());
359 std::vector<DynamicSparsityPattern::size_type> &renumbering)
365 ExcMessage(
"Only valid for sparsity patterns which store all rows."));
367 std::vector<types::global_dof_index> touched_nodes(connectivity.
n_rows(),
369 std::vector<unsigned int> row_lengths(connectivity.
n_rows());
370 std::set<types::global_dof_index> current_neighbors;
371 std::vector<std::vector<types::global_dof_index> > groups;
381 row_lengths[row] = connectivity.
row_length(row);
382 Assert(row_lengths[row] > 0, ExcInternalError());
384 std::vector<unsigned int> n_remaining_neighbors(row_lengths);
397 std::pair<types::global_dof_index,types::global_dof_index> min_neighbors
401 if (row_lengths[i] < min_neighbors.second)
403 min_neighbors = std::make_pair(i, n_remaining_neighbors[i]);
404 if (n_remaining_neighbors[i] <= 1)
410 Assert(min_neighbors.second > 0, ExcInternalError());
412 current_neighbors.clear();
413 current_neighbors.insert(min_neighbors.first);
414 while (!current_neighbors.empty())
420 for (std::set<types::global_dof_index>::iterator it=current_neighbors.begin();
421 it != current_neighbors.end(); ++it)
425 if (n_remaining_neighbors[*it] < min_neighbors.second)
426 min_neighbors = std::make_pair(*it, n_remaining_neighbors[*it]);
433 for (std::set<types::global_dof_index>::iterator it=current_neighbors.begin();
434 it != current_neighbors.end(); ++it)
435 if (n_remaining_neighbors[*it] == best_row_length)
436 if (row_lengths[*it] > min_neighbors.second)
437 min_neighbors = std::make_pair(*it, row_lengths[*it]);
441 groups.push_back(std::vector<types::global_dof_index>());
442 std::vector<types::global_dof_index> &next_group = groups.back();
444 next_group.push_back(min_neighbors.first);
445 touched_nodes[min_neighbors.first] = groups.size()-1;
447 = connectivity.
begin(min_neighbors.first);
448 it != connectivity.
end(min_neighbors.first); ++it)
451 next_group.push_back(it->column());
452 touched_nodes[it->column()] = groups.size()-1;
460 for (
unsigned int i=0; i<next_group.size(); ++i)
463 = connectivity.
begin(next_group[i]);
464 it != connectivity.
end(next_group[i]); ++it)
467 current_neighbors.insert(it->column());
468 n_remaining_neighbors[it->column()]--;
470 current_neighbors.erase(next_group[i]);
477 Assert(n_remaining_neighbors[row] == 0, ExcInternalError());
481 if (groups.size() < connectivity.
n_rows())
489 = connectivity.
begin(groups[i][col]);
490 it != connectivity.
end(groups[i][col]); ++it)
491 connectivity_next.
add(i, touched_nodes[it->column()]);
494 std::vector<types::global_dof_index> renumbering_next(groups.size());
501 renumbering[count] = groups[renumbering_next[i]][col];
509 renumbering[count] = groups[i][col];
516 std::vector<DynamicSparsityPattern::size_type> &renumbering)
521 internal::reorder_hierarchical(connectivity, renumbering);
527 #ifdef DEAL_II_WITH_MPI 530 const std::vector<DynamicSparsityPattern::size_type> &rows_per_cpu,
531 const MPI_Comm &mpi_comm,
535 std::vector<DynamicSparsityPattern::size_type> start_index(rows_per_cpu.size()+1);
538 start_index[i+1]=start_index[i]+rows_per_cpu[i];
541 std::vector<DynamicSparsityPattern::size_type> >
547 unsigned int dest_cpu=0;
549 DynamicSparsityPattern::size_type n_local_rel_rows = myrange.
n_elements();
550 for (DynamicSparsityPattern::size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
555 while (row>=start_index[dest_cpu+1])
561 row_idx+=rows_per_cpu[myid]-1;
565 DynamicSparsityPattern::size_type rlen = dsp.
row_length(row);
572 std::vector<DynamicSparsityPattern::size_type> &dst = send_data[dest_cpu];
576 for (DynamicSparsityPattern::size_type c=0; c<rlen; ++c)
579 DynamicSparsityPattern::size_type column = dsp.
column_number(row, c);
580 dst.push_back(column);
586 unsigned int num_receive=0;
588 std::vector<unsigned int> send_to;
589 send_to.reserve(send_data.size());
590 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
591 send_to.push_back(it->first);
598 std::vector<MPI_Request> requests(send_data.size());
604 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
605 MPI_Isend(&(it->second[0]),
607 DEAL_II_DOF_INDEX_MPI_TYPE,
616 std::vector<DynamicSparsityPattern::size_type> recv_buf;
617 for (
unsigned int index=0; index<num_receive; ++index)
621 MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, mpi_comm, &status);
622 Assert (status.MPI_TAG==124, ExcInternalError());
624 MPI_Get_count(&status, DEAL_II_DOF_INDEX_MPI_TYPE, &len);
625 recv_buf.resize(len);
626 MPI_Recv(&recv_buf[0], len, DEAL_II_DOF_INDEX_MPI_TYPE, status.MPI_SOURCE,
627 status.MPI_TAG, mpi_comm, &status);
629 std::vector<DynamicSparsityPattern::size_type>::const_iterator ptr = recv_buf.begin();
630 std::vector<DynamicSparsityPattern::size_type>::const_iterator end = recv_buf.end();
633 DynamicSparsityPattern::size_type num=*(ptr++);
634 Assert(ptr!=end, ExcInternalError());
635 DynamicSparsityPattern::size_type row=*(ptr++);
636 for (
unsigned int c=0; c<num; ++c)
638 Assert(ptr!=end, ExcInternalError());
643 Assert(ptr==end, ExcInternalError());
649 MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
654 const std::vector<IndexSet> &owned_set_per_cpu,
655 const MPI_Comm &mpi_comm,
661 std::vector<BlockDynamicSparsityPattern::size_type> >
666 unsigned int dest_cpu=0;
668 BlockDynamicSparsityPattern::size_type n_local_rel_rows = myrange.
n_elements();
669 for (BlockDynamicSparsityPattern::size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
671 BlockDynamicSparsityPattern::size_type row=myrange.
nth_index_in_set(row_idx);
676 while (!owned_set_per_cpu[dest_cpu].is_element(row))
679 if (dest_cpu==owned_set_per_cpu.size())
687 BlockDynamicSparsityPattern::size_type rlen = dsp.
row_length(row);
694 std::vector<BlockDynamicSparsityPattern::size_type> &dst = send_data[dest_cpu];
698 for (BlockDynamicSparsityPattern::size_type c=0; c<rlen; ++c)
701 BlockDynamicSparsityPattern::size_type column = dsp.
column_number(row, c);
702 dst.push_back(column);
708 unsigned int num_receive=0;
710 std::vector<unsigned int> send_to;
711 send_to.reserve(send_data.size());
712 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
713 send_to.push_back(it->first);
720 std::vector<MPI_Request> requests(send_data.size());
726 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
727 MPI_Isend(&(it->second[0]),
729 DEAL_II_DOF_INDEX_MPI_TYPE,
738 std::vector<BlockDynamicSparsityPattern::size_type> recv_buf;
739 for (
unsigned int index=0; index<num_receive; ++index)
743 MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, mpi_comm, &status);
744 Assert (status.MPI_TAG==124, ExcInternalError());
746 MPI_Get_count(&status, DEAL_II_DOF_INDEX_MPI_TYPE, &len);
747 recv_buf.resize(len);
748 MPI_Recv(&recv_buf[0], len, DEAL_II_DOF_INDEX_MPI_TYPE, status.MPI_SOURCE,
749 status.MPI_TAG, mpi_comm, &status);
751 std::vector<BlockDynamicSparsityPattern::size_type>::const_iterator ptr = recv_buf.begin();
752 std::vector<BlockDynamicSparsityPattern::size_type>::const_iterator end = recv_buf.end();
755 BlockDynamicSparsityPattern::size_type num=*(ptr++);
756 Assert(ptr!=end, ExcInternalError());
757 BlockDynamicSparsityPattern::size_type row=*(ptr++);
758 for (
unsigned int c=0; c<num; ++c)
760 Assert(ptr!=end, ExcInternalError());
765 Assert(ptr==end, ExcInternalError());
771 MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
776 DEAL_II_NAMESPACE_CLOSE
const types::global_dof_index invalid_size_type
size_type column_number(const size_type row, const unsigned int index) const
#define AssertDimension(dim1, dim2)
size_type nth_index_in_set(const unsigned int local_index) const
size_type column_number(const size_type row, const size_type index) const
void add(const size_type i, const size_type j)
::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
bool is_compressed() const
types::global_dof_index size_type
bool is_valid_entry() const
types::global_dof_index size_type
void add(const size_type i, const size_type j)
unsigned int global_dof_index
#define Assert(cond, exc)
const IndexSet & row_index_set() const
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
size_type n_nonzero_elements() const
types::global_dof_index size_type
size_type row_length(const size_type row) const
unsigned int row_length(const size_type row) const
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
const types::global_dof_index invalid_dof_index
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
size_type n_elements() const