17 #include <deal.II/base/utilities.h> 18 #include <deal.II/base/memory_consumption.h> 19 #include <deal.II/base/parallel.h> 20 #include <deal.II/base/multithread_info.h> 21 #include <deal.II/base/mpi.h> 22 #include <deal.II/base/conditional_ostream.h> 24 #include <deal.II/matrix_free/task_info.h> 27 #ifdef DEAL_II_WITH_THREADS 29 #include <tbb/task_scheduler_init.h> 30 #include <tbb/parallel_for.h> 31 #include <tbb/blocked_range.h> 37 DEAL_II_NAMESPACE_OPEN
44 namespace MatrixFreeFunctions
46 #ifdef DEAL_II_WITH_THREADS 56 ActualCellWork (MFWorkerInterface **worker_pointer,
57 const unsigned int partition,
58 const TaskInfo &task_info)
61 worker_pointer(worker_pointer),
66 ActualCellWork (MFWorkerInterface &worker,
67 const unsigned int partition,
68 const TaskInfo &task_info)
71 worker_pointer (nullptr),
76 void operator() ()
const 78 MFWorkerInterface *used_worker = worker !=
nullptr ? worker : *worker_pointer;
80 used_worker->cell(std::make_pair(task_info.cell_partition_data[partition],
81 task_info.cell_partition_data[partition+1]));
83 if (task_info.face_partition_data.empty() ==
false)
85 used_worker->face(std::make_pair(task_info.face_partition_data[partition],
86 task_info.face_partition_data[partition+1]));
88 used_worker->boundary(std::make_pair(task_info.boundary_partition_data[partition],
89 task_info.boundary_partition_data[partition+1]));
94 MFWorkerInterface *worker;
95 MFWorkerInterface **worker_pointer;
97 const TaskInfo &task_info;
100 class CellWork :
public tbb::task
103 CellWork (MFWorkerInterface &worker,
104 const unsigned int partition,
105 const TaskInfo &task_info,
106 const bool is_blocked)
110 is_blocked (is_blocked)
113 tbb::task *execute ()
117 if (is_blocked==
true)
118 dummy->spawn (*dummy);
122 tbb::empty_task *dummy;
126 const bool is_blocked;
131 class PartitionWork :
public tbb::task
134 PartitionWork (MFWorkerInterface &function_in,
135 const unsigned int partition_in,
136 const TaskInfo &task_info_in,
137 const bool is_blocked_in =
false)
140 function (function_in),
142 task_info (task_info_in),
143 is_blocked (is_blocked_in)
146 tbb::task *execute ()
148 tbb::empty_task *root =
new( tbb::task::allocate_root() )tbb::empty_task;
149 const unsigned int evens = task_info.partition_evens[
partition];
150 const unsigned int odds = task_info.partition_odds[
partition];
151 const unsigned int n_blocked_workers =
152 task_info.partition_n_blocked_workers[
partition];
153 const unsigned int n_workers = task_info.partition_n_workers[
partition];
154 std::vector<CellWork *> worker(n_workers);
155 std::vector<CellWork *> blocked_worker(n_blocked_workers);
157 root->set_ref_count(evens+1);
158 for (
unsigned int j=0; j<evens; j++)
160 worker[j] =
new(root->allocate_child())
161 CellWork(
function, task_info.
162 partition_row_index[partition]+2*j,
166 worker[j]->set_ref_count(2);
167 blocked_worker[j-1]->dummy =
new(worker[j]->allocate_child())
169 worker[j-1]->spawn(*blocked_worker[j-1]);
172 worker[j]->set_ref_count(1);
175 blocked_worker[j] =
new(worker[j]->allocate_child())
176 CellWork(
function, task_info.
178 [partition] + 2*j+1, task_info,
true);
184 worker[evens] =
new(worker[j]->allocate_child())
185 CellWork(
function, task_info.
186 partition_row_index[partition]+2*j+1,
188 worker[j]->spawn(*worker[evens]);
192 tbb::empty_task *child =
new(worker[j]->allocate_child())
194 worker[j]->spawn(*child);
199 root->wait_for_all();
200 root->destroy(*root);
201 if (is_blocked==
true)
202 dummy->spawn (*dummy);
206 tbb::empty_task *dummy;
209 MFWorkerInterface &
function;
211 const TaskInfo &task_info;
212 const bool is_blocked;
224 CellWork (MFWorkerInterface &worker_in,
225 const TaskInfo &task_info_in,
226 const unsigned int partition_in)
229 task_info (task_info_in),
233 void operator()(
const tbb::blocked_range<unsigned int> &r)
const 235 const unsigned int start_index = task_info.cell_partition_data[
partition]
236 + task_info.block_size * r.begin();
237 const unsigned int end_index = std::min(start_index +
238 task_info.block_size*(r.end()-r.begin()),
239 task_info.cell_partition_data[partition+1]);
240 worker.cell(std::make_pair(start_index, end_index));
242 if (task_info.face_partition_data.empty() ==
false)
248 MFWorkerInterface &worker;
249 const TaskInfo &task_info;
255 class PartitionWork :
public tbb::task
258 PartitionWork (MFWorkerInterface &worker_in,
259 const unsigned int partition_in,
260 const TaskInfo &task_info_in,
261 const bool is_blocked_in)
266 task_info (task_info_in),
267 is_blocked (is_blocked_in)
270 tbb::task *execute ()
272 const unsigned int n_chunks = (task_info.cell_partition_data[
partition+1]-
273 task_info.cell_partition_data[
partition]+
274 task_info.block_size-1)/task_info.block_size;
275 parallel_for(tbb::blocked_range<unsigned int>(0,n_chunks,1),
276 CellWork (worker,task_info,partition));
277 if (is_blocked==
true)
278 dummy->spawn (*dummy);
282 tbb::empty_task *dummy;
285 MFWorkerInterface &worker;
287 const TaskInfo &task_info;
288 const bool is_blocked;
295 class MPICommunication :
public tbb::task
298 MPICommunication (MFWorkerInterface &worker_in,
299 const bool do_compress)
302 do_compress(do_compress)
305 tbb::task *execute ()
307 if (do_compress ==
false)
308 worker.vector_update_ghosts_finish();
310 worker.vector_compress_start();
315 MFWorkerInterface &worker;
316 const bool do_compress;
319 #endif // DEAL_II_WITH_THREADS 328 #ifdef DEAL_II_WITH_THREADS 333 if (
scheme == partition_partition)
335 tbb::empty_task *root =
new( tbb::task::allocate_root() )
337 root->set_ref_count(
evens+1);
338 std::vector<partition::PartitionWork *> worker(
n_workers);
339 std::vector<partition::PartitionWork *>
341 MPICommunication *worker_compr =
342 new(root->allocate_child())MPICommunication(funct,
true);
343 worker_compr->set_ref_count(1);
344 for (
unsigned int j=0; j<
evens; j++)
348 worker[j] =
new(root->allocate_child())
349 partition::PartitionWork (funct,2*j,*
this,
false);
350 worker[j]->set_ref_count(2);
351 blocked_worker[j-1]->dummy =
new(worker[j]->allocate_child())
354 worker[j-1]->spawn(*blocked_worker[j-1]);
356 worker_compr->spawn(*blocked_worker[j-1]);
360 worker[j] =
new(worker_compr->allocate_child())
361 partition::PartitionWork (funct,2*j,*
this,
false);
362 worker[j]->set_ref_count(2);
363 MPICommunication *worker_dist =
364 new (worker[j]->allocate_child())MPICommunication(funct,
false);
365 worker_dist->spawn(*worker_dist);
369 blocked_worker[j] =
new(worker[j]->allocate_child())
370 partition::PartitionWork(funct,2*j+1,*
this,
true);
376 worker[
evens] =
new(worker[j]->allocate_child())
377 partition::PartitionWork(funct,2*j+1,*
this,
false);
378 worker[j]->spawn(*worker[
evens]);
382 tbb::empty_task *child =
new(worker[j]->allocate_child())
384 worker[j]->spawn(*child);
389 root->wait_for_all();
390 root->destroy(*root);
398 tbb::empty_task *root =
new( tbb::task::allocate_root() ) tbb::empty_task;
399 root->set_ref_count(
evens+1);
403 std::vector<color::PartitionWork *> worker(
n_workers);
405 unsigned int worker_index = 0, slice_index = 0;
406 unsigned int spawn_index = 0;
407 int spawn_index_child = -2;
408 MPICommunication *worker_compr =
409 new (root->allocate_child())MPICommunication(funct,
true);
410 worker_compr->set_ref_count(1);
413 const unsigned int spawn_index_new = worker_index;
415 worker[worker_index] =
new(worker_compr->allocate_child())
416 color::PartitionWork(funct,slice_index,*
this,
false);
418 worker[worker_index] =
new(root->allocate_child())
419 color::PartitionWork(funct,slice_index,*
this,
false);
423 worker[worker_index]->set_ref_count(1);
425 worker[worker_index] =
new (worker[worker_index-1]->allocate_child())
426 color::PartitionWork(funct,slice_index,*
this,
false);
428 worker[worker_index]->set_ref_count(2);
431 blocked_worker[(part-1)/2]->dummy =
432 new (worker[worker_index]->allocate_child()) tbb::empty_task;
434 if (spawn_index_child == -1)
435 worker[spawn_index]->spawn(*blocked_worker[(part-1)/2]);
439 worker[spawn_index]->spawn(*worker[spawn_index_child]);
441 spawn_index = spawn_index_new;
442 spawn_index_child = -2;
446 MPICommunication *worker_dist =
447 new (worker[worker_index]->allocate_child())MPICommunication(funct,
false);
448 worker_dist->spawn(*worker_dist);
456 blocked_worker[part/2] =
new(worker[worker_index-1]->allocate_child())
457 color::PartitionWork(funct,slice_index,*
this,
true);
461 blocked_worker[part/2]->set_ref_count(1);
462 worker[worker_index] =
new(blocked_worker[part/2]->allocate_child())
463 color::PartitionWork(funct,slice_index,*
this,
false);
468 spawn_index_child = -1;
477 worker[worker_index]->set_ref_count(1);
480 worker[worker_index] =
new (worker[worker_index-1]->allocate_child())
481 color::PartitionWork(funct,slice_index,*
this,
false);
483 spawn_index_child = worker_index;
488 tbb::empty_task *
final =
new (worker[worker_index-1]->allocate_child())
490 worker[spawn_index]->spawn(*
final);
491 spawn_index_child = worker_index-1;
497 worker[spawn_index]->spawn(*worker[spawn_index_child]);
499 root->wait_for_all();
500 root->destroy(*root);
511 tbb::empty_task *root =
new( tbb::task::allocate_root() ) tbb::empty_task;
512 root->set_ref_count(2);
513 color::PartitionWork *worker =
514 new (root->allocate_child())color::PartitionWork(funct,color,*
this,
false);
515 root->spawn(*worker);
516 root->wait_for_all();
517 root->destroy(*root);
598 template <
typename StreamType>
600 const std::size_t data_length)
const 607 out << memory_c.
min <<
"/" << memory_c.
avg <<
"/" << memory_c.
max;
608 out <<
" MB" << std::endl;
616 return (
sizeof(*
this)+
631 const unsigned int n_active_and_ghost_cells,
632 const unsigned int vectorization_length_in,
633 std::vector<unsigned int> &boundary_cells)
641 unsigned int fillup_needed =
648 std::vector<unsigned int> new_boundary_cells;
649 new_boundary_cells.reserve (boundary_cells.size());
651 unsigned int next_free_slot = 0, bound_index = 0;
652 while (fillup_needed > 0 && bound_index < boundary_cells.size())
654 if (next_free_slot < boundary_cells[bound_index])
658 if (next_free_slot + fillup_needed <= boundary_cells[bound_index])
660 for (
unsigned int j=boundary_cells[bound_index]-fillup_needed;
661 j < boundary_cells[bound_index]; ++j)
662 new_boundary_cells.push_back(j);
669 for (
unsigned int j=next_free_slot;
670 j<boundary_cells[bound_index]; ++j)
671 new_boundary_cells.push_back(j);
672 fillup_needed -= boundary_cells[bound_index]-next_free_slot;
675 new_boundary_cells.push_back(boundary_cells[bound_index]);
676 next_free_slot = boundary_cells[bound_index]+1;
679 while (fillup_needed > 0 && (new_boundary_cells.size()==0 ||
681 new_boundary_cells.push_back(new_boundary_cells.back()+1);
682 while (bound_index<boundary_cells.size())
683 new_boundary_cells.push_back(boundary_cells[bound_index++]);
685 boundary_cells.swap(new_boundary_cells);
689 std::sort (boundary_cells.begin(), boundary_cells.end());
702 const std::vector<unsigned int> &cells_close_to_boundary,
703 const unsigned int dofs_per_cell,
704 const std::vector<unsigned int> &cell_vectorization_categories,
705 const bool cell_vectorization_categories_strict,
706 std::vector<unsigned int> &renumbering,
707 std::vector<unsigned char> &incompletely_filled_vectorization)
709 const unsigned int n_macro_cells =
710 (n_active_cells + vectorization_length - 1) / vectorization_length;
711 const unsigned int n_ghost_slots =
712 (n_ghost_cells + vectorization_length - 1) / vectorization_length;
713 const unsigned int n_boundary_cells = boundary_cells.size();
715 incompletely_filled_vectorization.resize (n_macro_cells+n_ghost_slots);
716 renumbering.resize(n_active_cells + n_ghost_cells,
722 partition_row_index.resize(3);
724 partition_row_index.resize(5);
727 std::vector<unsigned char> cell_marked(n_active_cells+n_ghost_cells, 0);
730 for (
unsigned int i=0; i<n_boundary_cells; ++i)
731 cell_marked[boundary_cells[i]] = 2;
733 Assert(boundary_cells.size()%vectorization_length == 0 ||
734 boundary_cells.size() == n_active_cells,
737 const unsigned int n_second_slot =
738 ((n_active_cells - n_boundary_cells)/2/vectorization_length)*vectorization_length;
739 unsigned int count = 0;
740 for (
unsigned int i=0; i<cells_close_to_boundary.size(); ++i)
741 if (cell_marked[cells_close_to_boundary[i]] == 0)
743 cell_marked[cells_close_to_boundary[i]] = count<n_second_slot ? 1 : 3;
748 for ( ; c<n_active_cells && count < n_second_slot; ++c)
749 if (cell_marked[c] == 0)
754 for ( ; c < n_active_cells; ++c)
755 if (cell_marked[c] == 0)
757 for ( ; c < n_active_cells+n_ghost_cells; ++c)
758 if (cell_marked[c] == 0)
762 std::fill(cell_marked.begin(), cell_marked.end(), 1);
764 for (
unsigned int i=0; i<cell_marked.size(); ++i)
767 unsigned int n_categories = 1;
768 std::vector<unsigned int> tight_category_map;
769 if (cell_vectorization_categories.empty() ==
false)
772 n_active_cells+n_ghost_cells);
777 tight_category_map.reserve(n_active_cells+n_ghost_cells);
778 std::set<unsigned int> used_categories;
779 for (
unsigned int i=0; i<n_active_cells+n_ghost_cells; ++i)
780 used_categories.insert(cell_vectorization_categories[i]);
781 std::vector<unsigned int> used_categories_vector(used_categories.size());
783 for (
auto &it : used_categories)
784 used_categories_vector[n_categories++] = it;
785 for (
unsigned int i=0; i<n_active_cells+n_ghost_cells; ++i)
787 const unsigned int index = std::lower_bound(used_categories_vector.begin(),
788 used_categories_vector.end(),
789 cell_vectorization_categories[i])
790 - used_categories_vector.begin();
792 tight_category_map[i] = index;
796 incompletely_filled_vectorization.resize(incompletely_filled_vectorization.size()
799 else if (cells_close_to_boundary.empty())
800 tight_category_map.resize(n_active_cells+n_ghost_cells, 0);
804 tight_category_map.resize(n_active_cells+n_ghost_cells, 1);
805 for (
unsigned int i=0; i<cells_close_to_boundary.size(); ++i)
806 tight_category_map[cells_close_to_boundary[i]] = 0;
809 cell_partition_data.clear();
810 cell_partition_data.resize(1, 0);
811 unsigned int counter = 0;
812 unsigned int n_cells = 0;
813 std::vector<std::vector<unsigned int> > renumbering_category(n_categories);
814 for (
unsigned int block=1; block<(n_procs>1u ? 5u : 3u); ++block)
817 for (
unsigned int i=0; i<n_active_cells+n_ghost_cells; ++i)
818 if (cell_marked[i] == block)
819 renumbering_category[tight_category_map[i]].push_back(i);
823 if (cell_vectorization_categories_strict ==
false && n_categories > 1)
824 for (
unsigned int j=n_categories-1; j>0; --j)
826 unsigned int lower_index = j-1;
827 while (renumbering_category[j].size()%vectorization_length)
829 while (renumbering_category[j].size()%vectorization_length &&
830 !renumbering_category[lower_index].empty())
832 renumbering_category[j].push_back(renumbering_category[lower_index].back());
833 renumbering_category[lower_index].pop_back();
835 if (lower_index == 0)
843 for (
unsigned int j=0; j<n_categories; ++j)
845 for (
unsigned int jj=0; jj<renumbering_category[j].size(); jj++)
846 renumbering[counter++] = renumbering_category[j][jj];
847 unsigned int remainder = renumbering_category[j].size()%vectorization_length;
849 incompletely_filled_vectorization
850 [renumbering_category[j].size()/vectorization_length+n_cells]
852 const unsigned int n_my_macro_cells =
853 (renumbering_category[j].size()+vectorization_length-1)/vectorization_length;
854 renumbering_category[j].clear();
858 const unsigned int block_size = std::max((2048U/dofs_per_cell)/8*4, 2U);
860 for (
unsigned int k=0; k<n_my_macro_cells; k+=block_size)
861 cell_partition_data.push_back(n_cells +
862 std::min(k+block_size,
865 cell_partition_data.back() += n_my_macro_cells;
866 n_cells += n_my_macro_cells;
868 partition_row_index[block] = cell_partition_data.size()-1;
869 if (block == 3 || (block==1 && n_procs == 1))
870 cell_partition_data.push_back(n_cells);
872 if (cell_vectorization_categories_strict ==
true)
879 incompletely_filled_vectorization.resize(cell_partition_data.back());
887 std::vector<unsigned int> &renumbering,
888 std::vector<unsigned char> &incompletely_filled_vectorization)
890 const unsigned int n_macro_cells =
891 (n_active_cells + vectorization_length - 1) / vectorization_length;
892 const unsigned int n_ghost_slots =
893 (n_ghost_cells + vectorization_length - 1) / vectorization_length;
894 incompletely_filled_vectorization.resize (n_macro_cells+n_ghost_slots);
895 if (n_macro_cells*vectorization_length > n_active_cells)
896 incompletely_filled_vectorization[n_macro_cells-1] =
897 vectorization_length - (n_macro_cells*vectorization_length - n_active_cells);
898 if (n_ghost_slots*vectorization_length > n_ghost_cells)
899 incompletely_filled_vectorization[n_macro_cells+n_ghost_slots-1] =
900 vectorization_length - (n_ghost_slots*vectorization_length - n_ghost_cells);
902 std::vector<unsigned int> reverse_numbering (n_active_cells,
904 for (
unsigned int j=0; j<boundary_cells.size(); ++j)
905 reverse_numbering[boundary_cells[j]] = j;
906 unsigned int counter = boundary_cells.size();
907 for (
unsigned int j=0; j<n_active_cells; ++j)
909 reverse_numbering[j] = counter++;
914 for (
unsigned int j=n_active_cells; j<n_active_cells+n_ghost_cells; ++j)
915 renumbering.push_back(j);
919 cell_partition_data.clear();
920 cell_partition_data.push_back(0);
923 const unsigned int n_macro_boundary_cells =
924 (boundary_cells.size()+vectorization_length-1)/vectorization_length;
925 cell_partition_data.push_back((n_macro_cells-n_macro_boundary_cells)/2);
926 cell_partition_data.push_back(cell_partition_data[1] + n_macro_boundary_cells);
930 cell_partition_data.push_back(n_macro_cells);
931 cell_partition_data.push_back(cell_partition_data.back() + n_ghost_slots);
932 partition_row_index.resize(n_procs > 1 ? 4 : 2);
933 partition_row_index[0] = 0;
934 partition_row_index[1] = 1;
937 partition_row_index[2] = 2;
938 partition_row_index[3] = 3;
957 const unsigned int minimum_parallel_grain_size = 200;
959 minimum_parallel_grain_size)
976 std::vector<unsigned int> &renumbering,
977 std::vector<unsigned char> &irregular_cells,
980 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
981 if (n_macro_cells == 0)
986 unsigned int partition = 0, counter = 0;
991 make_connectivity_cells_to_blocks(irregular_cells, connectivity_large, connectivity);
998 std::vector<unsigned int> cell_partition(n_blocks,
1003 std::vector<unsigned int> partition_list (n_blocks,0);
1004 std::vector<unsigned int> partition_color_list(n_blocks,0);
1007 std::vector<unsigned int> partition_size (2,0);
1013 unsigned int cluster_size = 1;
1016 make_partitioning( connectivity, cluster_size, cell_partition,
1017 partition_list, partition_size, partition );
1020 make_coloring_within_partitions_pre_blocked
1021 (connectivity, partition, cell_partition,
1022 partition_list, partition_size, partition_color_list);
1024 partition_list = renumbering;
1029 std::vector<unsigned int> sorted_pc_list (partition_color_list);
1030 std::sort(sorted_pc_list.begin(), sorted_pc_list.end());
1031 for (
unsigned int i=0; i<sorted_pc_list.size(); ++i)
1038 std::vector<unsigned int> block_start(n_macro_cells+1);
1039 std::vector<unsigned char> irregular(n_macro_cells);
1041 unsigned int mcell_start=0;
1043 for (
unsigned int block=0; block<n_blocks; block++)
1045 block_start[block+1] = block_start[block];
1046 for (
unsigned int mcell=mcell_start; mcell<
1047 std::min(mcell_start+block_size, n_macro_cells);
1050 unsigned int n_comp = (irregular_cells[mcell]>0)
1051 ?irregular_cells[mcell]:vectorization_length;
1052 block_start[block+1] += n_comp;
1055 mcell_start += block_size;
1058 unsigned int counter_macro = 0;
1059 unsigned int block_size_last =
1060 n_macro_cells - block_size * (n_blocks-1);
1061 if (block_size_last == 0)
1062 block_size_last = block_size;
1064 unsigned int tick = 0;
1065 for (
unsigned int block=0; block<n_blocks; block++)
1067 unsigned int present_block = partition_color_list[block];
1068 for (
unsigned int cell = block_start[present_block];
1069 cell<block_start[present_block+1]; ++cell)
1070 renumbering[counter++] = partition_list[cell];
1071 unsigned int this_block_size = (present_block == n_blocks-1)?
1072 block_size_last:block_size;
1076 if (cell_partition_data[tick] == block)
1077 cell_partition_data[tick++] = counter_macro;
1079 for (
unsigned int j=0; j<this_block_size; j++)
1080 irregular[counter_macro++] =
1081 irregular_cells[present_block*block_size+j];
1084 cell_partition_data.back() = counter_macro;
1086 irregular_cells.swap(irregular);
1093 std::vector<unsigned int> sorted_renumbering (renumbering);
1094 std::sort(sorted_renumbering.begin(), sorted_renumbering.end());
1095 for (
unsigned int i=0; i<sorted_renumbering.size(); ++i)
1101 update_task_info(partition);
1110 (
const std::vector<unsigned int> &cell_active_fe_index,
1112 std::vector<unsigned int> &renumbering,
1113 std::vector<unsigned char> &irregular_cells,
1116 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
1117 if (n_macro_cells == 0)
1126 make_connectivity_cells_to_blocks(irregular_cells, connectivity, connectivity_blocks);
1128 unsigned int n_blocks = 0;
1129 if ( scheme == partition_color || scheme == color )
1130 n_blocks = this->n_blocks;
1132 n_blocks = n_active_cells;
1137 std::vector<unsigned int> cell_partition(n_blocks,
1143 std::vector<unsigned int> partition_list (n_blocks,0);
1144 std::vector<unsigned int> partition_2layers_list(n_blocks,0);
1147 std::vector<unsigned int> partition_size (2,0);
1149 unsigned int partition = 0;
1155 unsigned int cluster_size = 1;
1156 if (scheme == partition_partition)
1157 cluster_size = block_size*vectorization_length;
1160 if ( scheme == partition_color || scheme == color )
1161 make_partitioning( connectivity_blocks, cluster_size, cell_partition,
1162 partition_list, partition_size, partition);
1164 make_partitioning( connectivity, cluster_size, cell_partition,
1165 partition_list, partition_size, partition);
1168 if ( scheme == partition_partition )
1172 make_partitioning_within_partitions_post_blocked
1173 (connectivity, cell_active_fe_index, partition, cluster_size, hp_bool,
1174 cell_partition, partition_list, partition_size,
1175 partition_2layers_list, irregular_cells);
1177 else if ( scheme == partition_color || scheme == color )
1179 make_coloring_within_partitions_pre_blocked
1180 (connectivity_blocks, partition, cell_partition,
1181 partition_list, partition_size, partition_2layers_list);
1187 std::vector<unsigned int> sorted_pc_list (partition_2layers_list);
1188 std::sort(sorted_pc_list.begin(), sorted_pc_list.end());
1189 for (
unsigned int i=0; i<sorted_pc_list.size(); ++i)
1195 std::vector<unsigned int> renumbering_in (n_active_cells,0);
1196 renumbering_in.swap(renumbering);
1197 if (scheme == partition_partition)
1202 for (
unsigned int j=0; j<renumbering.size(); j++)
1203 renumbering[j] = renumbering_in[partition_2layers_list[j]];
1205 for (
unsigned int i=0; i<n_ghost_cells; ++i)
1206 renumbering.push_back(i+n_active_cells);
1212 std::vector<unsigned int> block_start(n_macro_cells+1);
1213 std::vector<unsigned char> irregular(n_macro_cells);
1215 unsigned int counter = 0;
1216 unsigned int mcell_start=0;
1218 for (
unsigned int block=0; block<n_blocks; block++)
1220 block_start[block+1] = block_start[block];
1221 for (
unsigned int mcell=mcell_start; mcell<
1222 std::min(mcell_start+block_size, n_macro_cells);
1225 unsigned int n_comp = (irregular_cells[mcell]>0)
1226 ?irregular_cells[mcell]:vectorization_length;
1227 block_start[block+1] += n_comp;
1230 mcell_start += block_size;
1233 unsigned int counter_macro = 0;
1234 unsigned int block_size_last =
1235 n_macro_cells - block_size * (n_blocks-1);
1236 if (block_size_last == 0)
1237 block_size_last = block_size;
1239 unsigned int tick = 0;
1240 for (
unsigned int block=0; block<n_blocks; block++)
1242 unsigned int present_block = partition_2layers_list[block];
1243 for (
unsigned int cell = block_start[present_block];
1244 cell<block_start[present_block+1]; ++cell)
1245 renumbering[counter++] = renumbering_in[cell];
1246 unsigned int this_block_size = (present_block == n_blocks-1)?
1247 block_size_last:block_size;
1251 if (cell_partition_data[tick] == block)
1252 cell_partition_data[tick++] = counter_macro;
1254 for (
unsigned int j=0; j<this_block_size; j++)
1255 irregular[counter_macro++] =
1256 irregular_cells[present_block*block_size+j];
1259 cell_partition_data.back() = counter_macro;
1261 irregular_cells.swap(irregular);
1267 std::vector<unsigned int> sorted_renumbering (renumbering);
1268 std::sort(sorted_renumbering.begin(), sorted_renumbering.end());
1269 for (
unsigned int i=0; i<sorted_renumbering.size(); ++i)
1276 update_task_info(partition);
1284 (
const std::vector<unsigned int> &cell_active_fe_index,
1286 std::vector<unsigned int> &renumbering,
1287 std::vector<unsigned char> &irregular_cells,
1290 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
1291 if (n_macro_cells == 0)
1294 const unsigned int cluster_size = block_size*vectorization_length;
1301 std::vector<unsigned int> cell_partition (n_active_cells,
1307 std::vector<unsigned int> partition_list(n_active_cells,0);
1308 std::vector<unsigned int> partition_partition_list(n_active_cells,0);
1311 std::vector<unsigned int> partition_size(2,0);
1313 unsigned int partition = 0;
1318 make_partitioning( connectivity, cluster_size, cell_partition,
1319 partition_list, partition_size, partition);
1322 make_partitioning_within_partitions_post_blocked
1323 (connectivity, cell_active_fe_index, partition, cluster_size, hp_bool,
1325 partition_list, partition_size,
1326 partition_partition_list,
1329 partition_list.swap(renumbering);
1331 for (
unsigned int j=0; j<renumbering.size(); j++)
1332 renumbering[j] = partition_list[partition_partition_list[j]];
1334 for (
unsigned int i=0; i<n_ghost_cells; ++i)
1335 renumbering.push_back(i+n_active_cells);
1337 update_task_info(partition);
1345 (
const std::vector<unsigned char> &irregular_cells,
1349 std::vector<std::vector<unsigned int> > cell_blocks(n_blocks);
1350 std::vector<unsigned int> touched_cells(n_active_cells);
1351 unsigned int cell = 0;
1352 for (
unsigned int i=0, mcell=0; i<n_blocks; ++i)
1354 for (
unsigned int c=0; c<block_size &&
1355 mcell < *(cell_partition_data.end()-2); ++c, ++mcell)
1357 unsigned int ncomp = (irregular_cells[mcell]>0)
1358 ?irregular_cells[mcell]:vectorization_length;
1359 for (
unsigned int c=0; c<ncomp; ++c, ++cell)
1361 cell_blocks[i].push_back(cell);
1362 touched_cells[cell] = i;
1367 for (
unsigned int i=0; i<cell_blocks.size(); ++i)
1368 for (
unsigned int col=0; col<cell_blocks[i].size(); ++col)
1371 = connectivity_cells.
begin(cell_blocks[i][col]);
1372 it != connectivity_cells.
end(cell_blocks[i][col]); ++it)
1374 if (touched_cells[it->column()] != i)
1375 connectivity_blocks.
add(i,touched_cells[it->column()]);
1388 const std::vector<unsigned int> &cell_active_fe_index,
1389 const unsigned int partition,
1390 const unsigned int cluster_size,
1392 const std::vector<unsigned int> &cell_partition,
1393 const std::vector<unsigned int> &partition_list,
1394 const std::vector<unsigned int> &partition_size,
1395 std::vector<unsigned int> &partition_partition_list,
1396 std::vector<unsigned char> &irregular_cells)
1399 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
1400 const unsigned int n_ghost_slots =
1401 *(cell_partition_data.end()-1)-n_macro_cells;
1404 std::vector<unsigned int> neighbor_list;
1406 std::vector<unsigned int> neighbor_neighbor_list;
1408 std::vector<unsigned int> renumbering(n_active_cells);
1410 irregular_cells.back() = 0;
1411 irregular_cells.resize(n_active_cells+n_ghost_slots);
1413 unsigned int max_fe_index = 0;
1414 for (
unsigned int i=0; i<cell_active_fe_index.size(); ++i)
1415 max_fe_index = std::max(cell_active_fe_index[i], max_fe_index);
1416 Assert(!hp_bool || cell_active_fe_index.size() == n_active_cells,
1420 unsigned int n_macro_cells_before = 0;
1426 std::vector<unsigned int> cell_partition_l2(n_active_cells,
1428 partition_row_index.clear();
1429 partition_row_index.resize(partition+1,0);
1430 cell_partition_data.resize(1,0);
1432 unsigned int counter = 0;
1433 unsigned int missing_macros;
1434 for (
unsigned int part=0; part<partition; ++part)
1436 neighbor_neighbor_list.resize(0);
1437 neighbor_list.resize(0);
1439 unsigned int partition_l2 = 0;
1440 unsigned int start_up = partition_size[part];
1441 unsigned int partition_counter = 0;
1444 if (neighbor_list.size()==0)
1447 partition_counter = 0;
1448 for (
unsigned int j=start_up; j<partition_size[part+1]; ++j)
1449 if (cell_partition[partition_list[j]] == part &&
1454 partition_counter = 1;
1458 cell_partition_l2[partition_list[start_up]] =
1460 neighbor_neighbor_list.push_back
1461 (partition_list[start_up]);
1462 partition_partition_list[counter++] =
1463 partition_list[start_up];
1470 partition_counter = 0;
1471 for (
unsigned int j=0; j<neighbor_list.size(); ++j)
1473 Assert(cell_partition[neighbor_list[j]]==part,
1475 Assert(cell_partition_l2[neighbor_list[j]]==partition_l2-1,
1478 connectivity.
begin(neighbor_list[j]),
1479 end = connectivity.
end(neighbor_list[j]);
1480 for (; neighbor!=end ; ++neighbor)
1482 if (cell_partition[neighbor->
column()] == part &&
1483 cell_partition_l2[neighbor->
column()]==
1486 cell_partition_l2[neighbor->
column()] = partition_l2;
1487 neighbor_neighbor_list.push_back(neighbor->
column());
1488 partition_partition_list[counter++] = neighbor->
column();
1489 partition_counter++;
1494 if (partition_counter>0)
1496 int index_before = neighbor_neighbor_list.size(),
1497 index = index_before;
1502 std::vector<unsigned int> remaining_per_macro_cell
1504 std::vector<std::vector<unsigned int> >
1505 renumbering_fe_index;
1508 if (hp_bool ==
true)
1510 renumbering_fe_index.resize(max_fe_index+1);
1511 for (cell=counter-partition_counter; cell<counter; ++cell)
1513 renumbering_fe_index
1514 [cell_active_fe_index.empty() ? 0 :
1515 cell_active_fe_index[partition_partition_list
1517 push_back(partition_partition_list[cell]);
1520 for (
unsigned int j=0; j<max_fe_index+1; j++)
1522 remaining_per_macro_cell[j] =
1523 renumbering_fe_index[j].size()%vectorization_length;
1524 if (remaining_per_macro_cell[j] != 0)
1526 missing_macros += ((renumbering_fe_index[j].size()+
1527 vectorization_length-1)/vectorization_length);
1532 remaining_per_macro_cell.resize(1);
1533 remaining_per_macro_cell[0] = partition_counter%
1534 vectorization_length;
1535 missing_macros = partition_counter/vectorization_length;
1536 if (remaining_per_macro_cell[0] != 0)
1542 missing_macros = cluster_size - (missing_macros%cluster_size);
1545 while (missing_macros>0 || filled ==
false)
1549 index = neighbor_neighbor_list.size();
1550 if (index == index_before)
1552 if (missing_macros != 0)
1554 neighbor_neighbor_list.resize(0);
1559 index_before = index;
1562 unsigned int additional = neighbor_neighbor_list
1569 neighbor = connectivity.
begin(additional),
1570 end = connectivity.
end(additional);
1571 for (; neighbor!=end ; ++neighbor)
1573 if (cell_partition[neighbor->
column()] == part &&
1574 cell_partition_l2[neighbor->
column()] ==
1577 unsigned int this_index = 0;
1578 if (hp_bool ==
true)
1579 this_index = cell_active_fe_index.empty() ? 0 :
1580 cell_active_fe_index[neighbor->
column()];
1586 if (missing_macros > 0 ||
1587 remaining_per_macro_cell[this_index] > 0)
1589 cell_partition_l2[neighbor->
column()] = partition_l2;
1590 neighbor_neighbor_list.push_back(neighbor->
column());
1591 if (hp_bool ==
true)
1592 renumbering_fe_index[this_index].
1593 push_back(neighbor->
column());
1594 partition_partition_list[counter] =
1597 partition_counter++;
1598 if (remaining_per_macro_cell[this_index]
1599 == 0 && missing_macros > 0)
1601 remaining_per_macro_cell[this_index]++;
1602 if (remaining_per_macro_cell[this_index]
1603 == vectorization_length)
1605 remaining_per_macro_cell[this_index] = 0;
1607 if (missing_macros == 0)
1610 for (
unsigned int fe_ind=0;
1611 fe_ind<max_fe_index+1; ++fe_ind)
1612 if (remaining_per_macro_cell[fe_ind]!=0)
1621 if (hp_bool ==
true)
1626 cell = counter - partition_counter;
1627 for (
unsigned int j=0; j<max_fe_index+1; j++)
1629 for (
unsigned int jj=0; jj<renumbering_fe_index[j].
1631 renumbering[cell++] =
1632 renumbering_fe_index[j][jj];
1633 if (renumbering_fe_index[j].size()%vectorization_length != 0)
1634 irregular_cells[renumbering_fe_index[j].size()/
1635 vectorization_length+
1636 n_macro_cells_before] =
1637 renumbering_fe_index[j].size()%vectorization_length;
1638 n_macro_cells_before += (renumbering_fe_index[j].
1639 size()+vectorization_length-1)/
1640 vectorization_length;
1641 renumbering_fe_index[j].resize(0);
1646 n_macro_cells_before += partition_counter/vectorization_length;
1647 if (partition_counter%vectorization_length != 0)
1649 irregular_cells[n_macro_cells_before] =
1650 partition_counter%vectorization_length;
1651 n_macro_cells_before++;
1655 cell_partition_data.
1656 push_back(n_macro_cells_before);
1659 neighbor_list = neighbor_neighbor_list;
1660 neighbor_neighbor_list.resize(0);
1662 partition_row_index[part+1] =
1663 partition_row_index[part] + partition_l2;
1666 if (hp_bool ==
true)
1668 partition_partition_list.swap(renumbering);
1679 const unsigned int partition,
1680 const std::vector<unsigned int> &cell_partition,
1681 const std::vector<unsigned int> &partition_list,
1682 const std::vector<unsigned int> &partition_size,
1683 std::vector<unsigned int> &partition_color_list)
1685 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
1686 std::vector<unsigned int> cell_color(n_blocks, n_macro_cells);
1687 std::vector<bool> color_finder;
1689 partition_row_index.resize(partition+1);
1690 cell_partition_data.clear();
1691 unsigned int color_counter = 0, index_counter = 0;
1692 for (
unsigned int part=0; part<partition; part++)
1694 partition_row_index[part] = index_counter;
1695 unsigned int max_color = 0;
1696 for (
unsigned int k=partition_size[part]; k<partition_size[part+1];
1699 unsigned int cell = partition_list[k];
1700 unsigned int n_neighbors = connectivity.
row_length(cell);
1704 color_finder.resize(n_neighbors+1);
1705 for (
unsigned int j=0; j<=n_neighbors; ++j)
1706 color_finder[j]=
true;
1708 neighbor = connectivity.
begin(cell),
1709 end = connectivity.
end(cell);
1710 for (; neighbor!=end ; ++neighbor)
1714 if (cell_partition[neighbor->
column()] == part &&
1715 cell_color[neighbor->
column()] <= n_neighbors)
1716 color_finder[cell_color[neighbor->
column()]] =
false;
1720 while (color_finder[cell_color[cell]] ==
false)
1722 if (cell_color[cell] > max_color)
1723 max_color = cell_color[cell];
1728 for (
unsigned int color=0; color<=max_color; color++)
1730 cell_partition_data.push_back(color_counter);
1732 for (
unsigned int k=partition_size[part];
1733 k<partition_size[part+1]; k++)
1735 unsigned int cell=partition_list[k];
1736 if (cell_color[cell] == color)
1738 partition_color_list[color_counter++] = cell;
1743 cell_partition_data.push_back(n_blocks);
1744 partition_row_index[partition] = index_counter;
1753 const unsigned int cluster_size,
1754 std::vector<unsigned int> &cell_partition,
1755 std::vector<unsigned int> &partition_list,
1756 std::vector<unsigned int> &partition_size,
1757 unsigned int &partition)
const 1766 std::vector<unsigned int> neighbor_list;
1768 std::vector<unsigned int> neighbor_neighbor_list;
1778 unsigned int counter=0;
1779 unsigned int start_nonboundary = cell_partition_data.size() == 5 ?
1780 vectorization_length * (cell_partition_data[2] -
1781 cell_partition_data[1]) : 0;
1783 const unsigned int n_macro_cells = *(cell_partition_data.end()-2);
1784 if (n_macro_cells == 0)
1786 if (scheme == color)
1787 start_nonboundary = n_macro_cells;
1788 if ( scheme == partition_color || scheme == color )
1789 start_nonboundary = ((start_nonboundary+block_size-1)
1791 unsigned int n_blocks;
1792 if ( scheme == partition_color || scheme == color )
1793 n_blocks = this->n_blocks;
1795 n_blocks = n_active_cells;
1797 if (start_nonboundary > n_blocks)
1798 start_nonboundary = n_blocks;
1801 unsigned int start_up = 0;
1803 unsigned int remainder = cluster_size;
1811 if (start_nonboundary>0)
1813 for (
unsigned int cell=0; cell<start_nonboundary; ++cell)
1815 const unsigned int cell_nn = cell;
1816 cell_partition[cell_nn] = partition;
1817 neighbor_list.push_back(cell_nn);
1818 partition_list[counter++] = cell_nn;
1819 partition_size.back()++;
1821 start_nonboundary = 0;
1822 remainder -= (start_nonboundary%cluster_size);
1823 if (remainder == cluster_size)
1830 cell_partition[start_up] = partition;
1831 neighbor_list.push_back(start_up);
1832 partition_list[counter++] = start_up;
1833 partition_size.back()++;
1836 if (remainder == cluster_size)
1839 int index_before = neighbor_list.size(), index = index_before,
1843 if (index==index_stop)
1845 index = neighbor_list.size();
1846 if (index == index_before)
1848 neighbor_list.resize(0);
1851 index_stop = index_before;
1852 index_before = index;
1855 unsigned int additional = neighbor_list[index];
1857 connectivity.
begin(additional),
1858 end = connectivity.
end(additional);
1859 for (; neighbor!=end ; ++neighbor)
1863 partition_size.back()++;
1864 cell_partition[neighbor->
column()] = partition;
1865 neighbor_list.push_back(neighbor->
column());
1866 partition_list[counter++] = neighbor->
column();
1874 while (neighbor_list.size()>0)
1879 unsigned int partition_counter = 0;
1882 partition_size.push_back(partition_size.back());
1886 for (
unsigned int j=0; j<neighbor_list.size(); ++j)
1888 Assert(cell_partition[neighbor_list[j]]==partition-1,
1891 connectivity.
begin(neighbor_list[j]),
1892 end = connectivity.
end(neighbor_list[j]);
1893 for (; neighbor!=end ; ++neighbor)
1897 partition_size.back()++;
1898 cell_partition[neighbor->
column()] = partition;
1902 neighbor_neighbor_list.push_back(neighbor->
column());
1903 partition_list[counter++] = neighbor->
column();
1904 partition_counter++;
1908 remainder = cluster_size-(partition_counter%cluster_size);
1909 if (remainder == cluster_size)
1912 int index_before = neighbor_neighbor_list.size(), index = index_before;
1915 if (index==index_stop)
1917 index = neighbor_neighbor_list.size();
1918 if (index == index_before)
1920 neighbor_neighbor_list.resize(0);
1923 index_stop = index_before;
1924 index_before = index;
1927 unsigned int additional = neighbor_neighbor_list[index];
1929 connectivity.
begin(additional),
1930 end = connectivity.
end(additional);
1931 for (; neighbor!=end ; ++neighbor)
1935 partition_size.back()++;
1936 cell_partition[neighbor->
column()] = partition;
1937 neighbor_neighbor_list.push_back(neighbor->
column());
1938 partition_list[counter++] = neighbor->
column();
1946 neighbor_list = neighbor_neighbor_list;
1947 neighbor_neighbor_list.resize(0);
1953 for (
unsigned int j=start_up; j<n_blocks; ++j)
1959 remainder = cluster_size;
1973 (
const unsigned int partition)
1975 evens = (partition+1)/2;
1978 odds-(odds+evens+1)%2;
1979 n_workers = evens+odds-
1982 partition_evens.resize(partition);
1983 partition_odds.resize(partition);
1984 partition_n_blocked_workers.resize(partition);
1985 partition_n_workers.resize(partition);
1986 for (
unsigned int part=0; part<partition; part++)
1988 partition_evens[part] =
1989 (partition_row_index[part+1]-
1990 partition_row_index[part]+1)/2;
1991 partition_odds[part] =
1992 (partition_row_index[part+1]-
1993 partition_row_index[part])/2;
1994 partition_n_blocked_workers[part] =
1995 partition_odds[part]-(partition_odds[part]+
1996 partition_evens[part]+1)%2;
1997 partition_n_workers[part] =
1998 partition_evens[part]+partition_odds[part]-
1999 partition_n_blocked_workers[part];
2008 template void internal::MatrixFreeFunctions::TaskInfo::
2009 print_memory_statistics<std::ostream> (std::ostream &,
const std::size_t)
const;
2010 template void internal::MatrixFreeFunctions::TaskInfo::
2011 print_memory_statistics<ConditionalOStream> (
ConditionalOStream &,
const std::size_t)
const;
2014 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
virtual void cell(const std::pair< unsigned int, unsigned int > &cell_range)=0
TasksParallelScheme scheme
void loop(MFWorkerInterface &worker) const
void add(const size_type i, const size_type j)
void guess_block_size(const unsigned int dofs_per_cell)
std::vector< unsigned int > partition_row_index
#define AssertIndexRange(index, range)
std::vector< unsigned int > partition_n_workers
virtual void vector_update_ghosts_finish()=0
Finishes the communication for the update ghost values operation.
std::vector< unsigned int > cell_partition_data
#define AssertThrow(cond, exc)
void make_connectivity_cells_to_blocks(const std::vector< unsigned char > &irregular_cells, const DynamicSparsityPattern &connectivity_cells, DynamicSparsityPattern &connectivity_blocks) const
std::vector< unsigned int > partition_n_blocked_workers
void make_partitioning_within_partitions_post_blocked(const DynamicSparsityPattern &connectivity, const std::vector< unsigned int > &cell_active_fe_index, const unsigned int partition, const unsigned int cluster_size, const bool hp_bool, const std::vector< unsigned int > &cell_partition, const std::vector< unsigned int > &partition_list, const std::vector< unsigned int > &partition_size, std::vector< unsigned int > &partition_partition_list, std::vector< unsigned char > &irregular_cells)
void make_coloring_within_partitions_pre_blocked(const DynamicSparsityPattern &connectivity, const unsigned int partition, const std::vector< unsigned int > &cell_partition, const std::vector< unsigned int > &partition_list, const std::vector< unsigned int > &partition_size, std::vector< unsigned int > &partition_color_list)
unsigned int vectorization_length
#define Assert(cond, exc)
unsigned int n_blocked_workers
void make_thread_graph_partition_color(DynamicSparsityPattern &connectivity, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &irregular_cells, const bool hp_bool)
void update_task_info(const unsigned int partition)
std::vector< unsigned int > boundary_partition_data
void initial_setup_blocks_tasks(const std::vector< unsigned int > &boundary_cells, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &incompletely_filled_vectorization)
unsigned int n_ghost_cells
virtual void zero_dst_vector_range(const unsigned int range_index)=0
virtual void boundary(const std::pair< unsigned int, unsigned int > &face_range)=0
void create_blocks_serial(const std::vector< unsigned int > &boundary_cells, const std::vector< unsigned int > &cells_close_to_boundary, const unsigned int dofs_per_cell, const std::vector< unsigned int > &cell_vectorization_categories, const bool cell_vectorization_categories_strict, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &incompletely_filled_vectorization)
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
unsigned int n_active_cells
virtual void vector_update_ghosts_start()=0
Starts the communication for the update ghost values operation.
virtual void face(const std::pair< unsigned int, unsigned int > &face_range)=0
std::vector< unsigned int > face_partition_data
void collect_boundary_cells(const unsigned int n_active_cells, const unsigned int n_active_and_ghost_cells, const unsigned int vectorization_length, std::vector< unsigned int > &boundary_cells)
size_type row_length(const size_type row) const
void make_thread_graph_partition_partition(const std::vector< unsigned int > &cell_active_fe_index, DynamicSparsityPattern &connectivity, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &irregular_cells, const bool hp_bool)
void make_partitioning(const DynamicSparsityPattern &connectivity, const unsigned int cluster_size, std::vector< unsigned int > &cell_partition, std::vector< unsigned int > &partition_list, std::vector< unsigned int > &partition_size, unsigned int &partition) const
virtual void vector_compress_start()=0
Starts the communication for the vector compress operation.
std::vector< unsigned int > partition_odds
std::size_t memory_consumption() const
static ::ExceptionBase & ExcNotImplemented()
static unsigned int n_threads()
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
std::vector< unsigned int > partition_evens
void print_memory_statistics(StreamType &out, std::size_t data_length) const
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static ::ExceptionBase & ExcInternalError()
void make_thread_graph(const std::vector< unsigned int > &cell_active_fe_index, DynamicSparsityPattern &connectivity, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &irregular_cells, const bool hp_bool)
virtual void vector_compress_finish()=0
Finishes the communication for the vector compress operation.