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/base/mpi.h> 29 #include <deal.II/lac/dynamic_sparsity_pattern.h> 30 #include <deal.II/lac/block_sparsity_pattern.h> 33 #ifdef DEAL_II_WITH_METIS 34 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
39 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
43 DEAL_II_NAMESPACE_OPEN
49 const unsigned int n_partitions,
50 std::vector<unsigned int> &partition_indices)
58 Assert (partition_indices.size() == sparsity_pattern.
n_rows(),
60 sparsity_pattern.
n_rows()));
63 if (n_partitions == 1 || (sparsity_pattern.
n_rows()==1))
65 std::fill_n (partition_indices.begin(), partition_indices.size(), 0U);
71 #ifndef DEAL_II_WITH_METIS 72 (void)sparsity_pattern;
82 n =
static_cast<signed int>(sparsity_pattern.
n_rows()),
84 nparts = static_cast<int>(n_partitions),
93 nparts = std::min(n, nparts);
96 idx_t options[METIS_NOPTIONS];
97 METIS_SetDefaultOptions (options);
101 std::vector<idx_t> int_rowstart(1);
102 int_rowstart.reserve(sparsity_pattern.
n_rows()+1);
103 std::vector<idx_t> int_colnums;
108 col < sparsity_pattern.
end(row); ++col)
109 int_colnums.push_back(col->column());
110 int_rowstart.push_back(int_colnums.size());
113 std::vector<idx_t> int_partition_indices (sparsity_pattern.
n_rows());
122 ierr = METIS_PartGraphRecursive(&n, &ncon, &int_rowstart[0], &int_colnums[0],
124 &nparts,NULL,NULL,&options[0],
125 &dummy,&int_partition_indices[0]);
129 ierr = METIS_PartGraphKway(&n, &ncon, &int_rowstart[0], &int_colnums[0],
131 &nparts,NULL,NULL,&options[0],
132 &dummy,&int_partition_indices[0]);
139 std::copy (int_partition_indices.begin(),
140 int_partition_indices.end(),
141 partition_indices.begin());
155 const std::vector<DynamicSparsityPattern::size_type> &new_indices)
163 if (sparsity.
row_length(row) < min_coordination)
166 starting_point = row;
190 return starting_point;
198 std::vector<DynamicSparsityPattern::size_type> &new_indices,
199 const std::vector<DynamicSparsityPattern::size_type> &starting_indices)
206 ExcMessage (
"You can't specify more starting indices than there are rows"));
209 ExcMessage(
"Only valid for sparsity patterns which store all rows."));
212 ExcMessage (
"Invalid starting index: All starting indices need " 213 "to be between zero and the number of rows in the " 214 "sparsity pattern."));
218 std::vector<DynamicSparsityPattern::size_type> last_round_dofs (starting_indices);
221 std::fill (new_indices.begin(), new_indices.end(),
225 if (last_round_dofs.empty())
227 .push_back (internal::find_unnumbered_starting_index (sparsity,
235 new_indices[last_round_dofs[i]] = next_free_number++;
241 std::vector<DynamicSparsityPattern::size_type> next_round_dofs;
246 j<sparsity.
end(last_round_dofs[i]); ++j)
247 next_round_dofs.push_back (j->column());
250 std::sort (next_round_dofs.begin(), next_round_dofs.end());
253 std::vector<DynamicSparsityPattern::size_type>::iterator end_sorted;
254 end_sorted = std::unique (next_round_dofs.begin(), next_round_dofs.end());
255 next_round_dofs.erase (end_sorted, next_round_dofs.end());
258 for (
int s=next_round_dofs.size()-1; s>=0; --s)
260 next_round_dofs.erase (next_round_dofs.begin() + s);
266 if (next_round_dofs.empty())
268 if (std::find (new_indices.begin(), new_indices.end(),
280 Assert (starting_indices.empty(),
281 ExcMessage (
"The input graph appears to have more than one " 282 "component, but as stated in the documentation " 283 "we only want to reorder such graphs if no " 284 "starting indices are given. The function was " 285 "called with starting indices, however."))
288 .push_back (internal::find_unnumbered_starting_index (sparsity,
296 std::multimap<DynamicSparsityPattern::size_type, int> dofs_by_coordination;
299 for (std::vector<DynamicSparsityPattern::size_type>::iterator s=next_round_dofs.begin();
300 s!=next_round_dofs.end(); ++s)
305 const std::pair<const DynamicSparsityPattern::size_type, int> new_entry (coordination, *s);
306 dofs_by_coordination.insert (new_entry);
310 std::multimap<DynamicSparsityPattern::size_type, int>::iterator i;
311 for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i)
312 new_indices[i->second] = next_free_number++;
315 last_round_dofs = next_round_dofs;
325 (next_free_number == sparsity.
n_rows()),
333 std::vector<SparsityPattern::size_type> &new_indices,
334 const std::vector<SparsityPattern::size_type> &starting_indices)
337 for (
unsigned int row=0; row<sparsity.
n_rows(); ++row)
341 dsp.
add(row, it->column());
352 std::vector<DynamicSparsityPattern::size_type> &renumbering)
358 ExcMessage(
"Only valid for sparsity patterns which store all rows."));
360 std::vector<types::global_dof_index> touched_nodes(connectivity.
n_rows(),
362 std::vector<unsigned int> row_lengths(connectivity.
n_rows());
363 std::set<types::global_dof_index> current_neighbors;
364 std::vector<std::vector<types::global_dof_index> > groups;
374 row_lengths[row] = connectivity.
row_length(row);
377 std::vector<unsigned int> n_remaining_neighbors(row_lengths);
390 std::pair<types::global_dof_index,types::global_dof_index> min_neighbors
394 if (row_lengths[i] < min_neighbors.second)
396 min_neighbors = std::make_pair(i, n_remaining_neighbors[i]);
397 if (n_remaining_neighbors[i] <= 1)
405 current_neighbors.clear();
406 current_neighbors.insert(min_neighbors.first);
407 while (!current_neighbors.empty())
413 for (std::set<types::global_dof_index>::iterator it=current_neighbors.begin();
414 it != current_neighbors.end(); ++it)
418 if (n_remaining_neighbors[*it] < min_neighbors.second)
419 min_neighbors = std::make_pair(*it, n_remaining_neighbors[*it]);
426 for (std::set<types::global_dof_index>::iterator it=current_neighbors.begin();
427 it != current_neighbors.end(); ++it)
428 if (n_remaining_neighbors[*it] == best_row_length)
429 if (row_lengths[*it] > min_neighbors.second)
430 min_neighbors = std::make_pair(*it, row_lengths[*it]);
434 groups.push_back(std::vector<types::global_dof_index>());
435 std::vector<types::global_dof_index> &next_group = groups.back();
437 next_group.push_back(min_neighbors.first);
438 touched_nodes[min_neighbors.first] = groups.size()-1;
440 = connectivity.
begin(min_neighbors.first);
441 it != connectivity.
end(min_neighbors.first); ++it)
444 next_group.push_back(it->column());
445 touched_nodes[it->column()] = groups.size()-1;
453 for (
unsigned int i=0; i<next_group.size(); ++i)
456 = connectivity.
begin(next_group[i]);
457 it != connectivity.
end(next_group[i]); ++it)
460 current_neighbors.insert(it->column());
461 n_remaining_neighbors[it->column()]--;
463 current_neighbors.erase(next_group[i]);
474 if (groups.size() < connectivity.
n_rows())
482 = connectivity.
begin(groups[i][col]);
483 it != connectivity.
end(groups[i][col]); ++it)
484 connectivity_next.
add(i, touched_nodes[it->column()]);
487 std::vector<types::global_dof_index> renumbering_next(groups.size());
494 renumbering[count] = groups[renumbering_next[i]][col];
502 renumbering[count] = groups[i][col];
509 std::vector<DynamicSparsityPattern::size_type> &renumbering)
514 internal::reorder_hierarchical(connectivity, renumbering);
520 #ifdef DEAL_II_WITH_MPI 523 const std::vector<DynamicSparsityPattern::size_type> &rows_per_cpu,
524 const MPI_Comm &mpi_comm,
528 std::vector<DynamicSparsityPattern::size_type> start_index(rows_per_cpu.size()+1);
531 start_index[i+1]=start_index[i]+rows_per_cpu[i];
534 std::vector<DynamicSparsityPattern::size_type> >
540 unsigned int dest_cpu=0;
548 while (row>=start_index[dest_cpu+1])
554 row_idx+=rows_per_cpu[myid]-1;
565 std::vector<DynamicSparsityPattern::size_type> &dst = send_data[dest_cpu];
573 dst.push_back(column);
579 unsigned int num_receive=0;
581 std::vector<unsigned int> send_to;
582 send_to.reserve(send_data.size());
583 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
584 send_to.push_back(it->first);
591 std::vector<MPI_Request> requests(send_data.size());
597 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
599 const int ierr = MPI_Isend(&(it->second[0]),
601 DEAL_II_DOF_INDEX_MPI_TYPE,
612 std::vector<DynamicSparsityPattern::size_type> recv_buf;
613 for (
unsigned int index=0; index<num_receive; ++index)
617 int ierr = MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, mpi_comm, &status);
621 ierr = MPI_Get_count(&status, DEAL_II_DOF_INDEX_MPI_TYPE, &len);
623 recv_buf.resize(len);
624 ierr = MPI_Recv(&recv_buf[0], len, DEAL_II_DOF_INDEX_MPI_TYPE, status.MPI_SOURCE,
625 status.MPI_TAG, mpi_comm, &status);
628 std::vector<DynamicSparsityPattern::size_type>::const_iterator ptr = recv_buf.begin();
629 std::vector<DynamicSparsityPattern::size_type>::const_iterator end = recv_buf.end();
635 for (
unsigned int c=0; c<num; ++c)
649 const int ierr = MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
656 const std::vector<IndexSet> &owned_set_per_cpu,
657 const MPI_Comm &mpi_comm,
663 std::vector<BlockDynamicSparsityPattern::size_type> >
668 unsigned int dest_cpu=0;
678 while (!owned_set_per_cpu[dest_cpu].is_element(row))
681 if (dest_cpu==owned_set_per_cpu.size())
696 std::vector<BlockDynamicSparsityPattern::size_type> &dst = send_data[dest_cpu];
704 dst.push_back(column);
710 unsigned int num_receive=0;
712 std::vector<unsigned int> send_to;
713 send_to.reserve(send_data.size());
714 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
715 send_to.push_back(it->first);
722 std::vector<MPI_Request> requests(send_data.size());
728 for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
730 const int ierr = MPI_Isend(&(it->second[0]),
732 DEAL_II_DOF_INDEX_MPI_TYPE,
743 std::vector<BlockDynamicSparsityPattern::size_type> recv_buf;
744 for (
unsigned int index=0; index<num_receive; ++index)
748 int ierr = MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, mpi_comm, &status);
752 ierr = MPI_Get_count(&status, DEAL_II_DOF_INDEX_MPI_TYPE, &len);
754 recv_buf.resize(len);
755 ierr = MPI_Recv(&recv_buf[0], len, DEAL_II_DOF_INDEX_MPI_TYPE, status.MPI_SOURCE,
756 status.MPI_TAG, mpi_comm, &status);
759 std::vector<BlockDynamicSparsityPattern::size_type>::const_iterator ptr = recv_buf.begin();
760 std::vector<BlockDynamicSparsityPattern::size_type>::const_iterator end = recv_buf.end();
766 for (
unsigned int c=0; c<num; ++c)
780 const int ierr = MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
787 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)
std::size_t n_nonzero_elements() const
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)
static ::ExceptionBase & ExcMETISNotInstalled()
#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
static ::ExceptionBase & ExcNotCompressed()
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
void add(const size_type i, const size_type j)
unsigned int global_dof_index
#define Assert(cond, exc)
static ::ExceptionBase & ExcInvalidArraySize(int arg1, int arg2)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
const IndexSet & row_index_set() const
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
static ::ExceptionBase & ExcNotQuadratic()
types::global_dof_index size_type
#define AssertThrowMPI(error_code)
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
static ::ExceptionBase & ExcMETISError(int arg1)
static ::ExceptionBase & ExcInternalError()