104 const MPI_Comm &mpi_communicator,
105 const unsigned int n_locally_internal,
108 using namespace dealii;
110 const IndexSet &locally_owned = dof_handler.locally_owned_dofs();
111 const auto n_locally_owned = locally_owned.n_elements();
114 Assert(locally_owned.is_contiguous() ==
true,
116 "Need a contiguous set of locally owned indices."));
119 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
121 const auto locally_relevant =
122 DoFTools::extract_locally_relevant_dofs(dof_handler);
126 Utilities::MPI::Partitioner partitioner(
127 locally_owned, locally_relevant, mpi_communicator);
129 IndexSet export_indices(n_locally_owned);
130 for (
const auto &it : partitioner.import_indices()) {
131 export_indices.add_range(it.first, it.second);
134 std::vector<dealii::types::global_dof_index> new_order(n_locally_owned);
141 unsigned int n_export_indices = 0;
143 Assert(n_locally_internal <= n_locally_owned, dealii::ExcInternalError());
145 for (
unsigned int i = 0; i < n_locally_internal; i +=
warp_size) {
146 bool export_index_present =
false;
147 for (
unsigned int j = 0; j <
warp_size; ++j) {
148 if (export_indices.is_element(i + j)) {
149 export_index_present =
true;
154 if (export_index_present) {
155 Assert(n_export_indices %
warp_size == 0, dealii::ExcInternalError());
156 for (
unsigned int j = 0; j <
warp_size; ++j) {
157 new_order[i + j] = offset + n_export_indices++;
160 for (
unsigned int j = 0; j <
warp_size; ++j)
161 new_order[i + j] = dealii::numbers::invalid_dof_index;
166 unsigned int n_other = 0;
167 for (
unsigned int i = n_locally_internal; i < n_locally_owned; ++i)
168 if (export_indices.is_element(i))
171 Assert(n_other + n_export_indices >= export_indices.n_elements(),
172 dealii::ExcInternalError());
175 unsigned int running_index = n_export_indices;
181 for (
unsigned int i = 0; i < n_locally_internal; i +=
warp_size) {
182 if (new_order[i] == dealii::numbers::invalid_dof_index) {
183 for (
unsigned int j = 0; j <
warp_size; ++j) {
184 Assert(new_order[i + j] == dealii::numbers::invalid_dof_index,
185 dealii::ExcInternalError());
186 new_order[i + j] = offset + running_index++;
191 Assert(running_index == n_locally_internal, dealii::ExcInternalError());
193 for (
unsigned int i = n_locally_internal; i < n_locally_owned; i++) {
194 new_order[i] = offset + running_index++;
197 Assert(running_index == n_locally_owned, dealii::ExcInternalError());
199 dof_handler.renumber_dofs(new_order);
201 Assert(n_export_indices %
warp_size == 0, dealii::ExcInternalError());
202 Assert(n_export_indices <= n_locally_internal,
203 dealii::ExcInternalError());
204 return n_export_indices;
217 const dealii::DynamicSparsityPattern &sparsity,
218 const unsigned int n_locally_internal,
221 using namespace dealii;
223 const IndexSet &locally_owned = dof_handler.locally_owned_dofs();
224 const auto n_locally_owned = locally_owned.n_elements();
227 Assert(locally_owned.is_contiguous() ==
true,
229 "Need a contiguous set of locally owned indices."));
232 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
234 std::vector<dealii::types::global_dof_index> new_order(n_locally_owned);
242 unsigned int n_consistent_range = 0;
244 Assert(n_locally_internal <= n_locally_owned, dealii::ExcInternalError());
246 for (
unsigned int i = 0; i < n_locally_internal; i +=
warp_size) {
248 bool stride_is_consistent =
true;
249 const auto warp_row_length = sparsity.row_length(offset + i);
250 for (
unsigned int j = 0; j <
warp_size; ++j) {
251 if (warp_row_length != sparsity.row_length(offset + i + j)) {
252 stride_is_consistent =
false;
257 if (stride_is_consistent) {
258 for (
unsigned int j = 0; j <
warp_size; ++j) {
259 new_order[i + j] = offset + n_consistent_range++;
262 for (
unsigned int j = 0; j <
warp_size; ++j)
263 new_order[i + j] = dealii::numbers::invalid_dof_index;
271 unsigned int running_index = n_consistent_range;
273 for (
unsigned int i = 0; i < n_locally_internal; i +=
warp_size) {
274 if (new_order[i] == dealii::numbers::invalid_dof_index) {
275 for (
unsigned int j = 0; j <
warp_size; ++j) {
276 Assert(new_order[i + j] == dealii::numbers::invalid_dof_index,
277 dealii::ExcInternalError());
278 new_order[i + j] = offset + running_index++;
283 Assert(running_index == n_locally_internal, dealii::ExcInternalError());
285 for (
unsigned int i = n_locally_internal; i < n_locally_owned; i++) {
286 new_order[i] = offset + running_index++;
289 Assert(running_index == n_locally_owned, dealii::ExcInternalError());
291 dof_handler.renumber_dofs(new_order);
293 Assert(n_consistent_range %
warp_size == 0, dealii::ExcInternalError());
294 Assert(n_consistent_range <= n_locally_internal,
295 dealii::ExcInternalError());
296 return n_consistent_range;
317 const dealii::DynamicSparsityPattern &sparsity,
320 using namespace dealii;
322 const auto &locally_owned = dof_handler.locally_owned_dofs();
323 const auto n_locally_owned = locally_owned.n_elements();
327 Assert(locally_owned.is_contiguous() ==
true,
329 "Need a contiguous set of locally owned indices."));
332 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
334 using dof_type = dealii::types::global_dof_index;
335 std::vector<dof_type> new_order(n_locally_owned);
336 dof_type current_index = offset;
344 std::map<unsigned int, std::set<dof_type>> bins;
346 for (
unsigned int i = 0; i < n_locally_owned; ++i) {
347 const dof_type index = i;
348 const unsigned int row_length = sparsity.row_length(offset + index);
349 bins[row_length].insert(index);
351 if (bins[row_length].size() ==
warp_size) {
352 for (
const auto &index : bins[row_length])
353 new_order[index] = current_index++;
354 bins.erase(row_length);
358 unsigned int n_locally_internal = current_index - offset;
362 for (
const auto &entries : bins) {
363 Assert(entries.second.size() > 0, ExcInternalError());
364 for (
const auto &index : entries.second)
365 new_order[index] = current_index++;
367 Assert(current_index == offset + n_locally_owned, ExcInternalError());
369 dof_handler.renumber_dofs(new_order);
371 Assert(n_locally_internal %
warp_size == 0, ExcInternalError());
372 return n_locally_internal;