42 template <
int dim,
typename Number>
45 , element_is_continuous(false)
47 , n_child_cell_dofs(0)
52 template <
int dim,
typename Number>
56 , element_is_continuous(false)
58 , n_child_cell_dofs(0)
65 template <
int dim,
typename Number>
70 this->mg_constrained_dofs = &mg_c;
75 template <
int dim,
typename Number>
82 element_is_continuous =
false;
84 n_child_cell_dofs = 0;
85 level_dof_indices.clear();
86 parent_child_connect.clear();
87 dirichlet_indices.clear();
88 n_owned_level_cells.clear();
89 prolongation_matrix_1d.clear();
90 evaluation_data.clear();
91 weights_on_refined.clear();
95 template <
int dim,
typename Number>
99 const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
100 &external_partitioners)
102 this->fill_and_communicate_copy_indices(dof_handler);
104 vector_partitioners.resize(0,
107 for (
unsigned int level = 0;
level <= this->ghosted_level_vector.max_level();
109 vector_partitioners[
level] =
110 this->ghosted_level_vector[
level].get_partitioner();
112 std::vector<std::vector<Number>> weights_unvectorized;
116 internal::MGTransfer::setup_transfer<dim, Number>(
118 this->mg_constrained_dofs,
119 external_partitioners,
122 parent_child_connect,
125 weights_unvectorized,
126 this->copy_indices_global_mine,
127 vector_partitioners);
131 this->ghosted_level_vector.resize(0, vector_partitioners.max_level());
132 for (
unsigned int level = 0;
level <= vector_partitioners.max_level();
134 if (external_partitioners.size() == vector_partitioners.max_level() + 1 &&
135 external_partitioners[
level].get() == vector_partitioners[
level].get())
136 this->ghosted_level_vector[
level].reinit(0);
138 this->ghosted_level_vector[
level].reinit(vector_partitioners[
level]);
153 const unsigned int n_levels =
156 const unsigned int n_weights_per_cell = Utilities::fixed_power<dim>(3);
157 weights_on_refined.resize(n_levels - 1);
160 weights_on_refined[
level - 1].resize(
161 ((n_owned_level_cells[
level - 1] + vec_size - 1) / vec_size) *
164 for (
unsigned int c = 0; c < n_owned_level_cells[
level - 1]; ++c)
166 const unsigned int comp = c / vec_size;
167 const unsigned int v = c % vec_size;
168 for (
unsigned int i = 0; i < n_weights_per_cell; ++i)
170 weights_on_refined[
level - 1][comp * n_weights_per_cell + i][v] =
171 weights_unvectorized[
level - 1][c * n_weights_per_cell + i];
176 evaluation_data.resize(n_child_cell_dofs);
181 template <
int dim,
typename Number>
184 const unsigned int to_level,
188 Assert((to_level >= 1) && (to_level <= level_dof_indices.size()),
192 this->vector_partitioners[to_level - 1].get();
193 if (src_inplace ==
false)
195 if (this->ghosted_level_vector[to_level - 1].get_partitioner().get() !=
196 this->vector_partitioners[to_level - 1].get())
197 this->ghosted_level_vector[to_level - 1].reinit(
198 this->vector_partitioners[to_level - 1]);
199 this->ghosted_level_vector[to_level - 1].copy_locally_owned_data_from(
203 const bool dst_inplace =
204 dst.
get_partitioner().get() == this->vector_partitioners[to_level].get();
205 if (dst_inplace ==
false)
207 if (this->ghosted_level_vector[to_level].get_partitioner().get() !=
208 this->vector_partitioners[to_level].get())
209 this->ghosted_level_vector[to_level].reinit(
210 this->vector_partitioners[to_level]);
213 this->ghosted_level_vector[to_level] = 0.;
219 src_inplace ? src : this->ghosted_level_vector[to_level - 1];
221 dst_inplace ? dst : this->ghosted_level_vector[to_level];
228 do_prolongate_add<0>(to_level, dst_vec, src_vec);
229 else if (fe_degree == 1)
230 do_prolongate_add<1>(to_level, dst_vec, src_vec);
231 else if (fe_degree == 2)
232 do_prolongate_add<2>(to_level, dst_vec, src_vec);
233 else if (fe_degree == 3)
234 do_prolongate_add<3>(to_level, dst_vec, src_vec);
235 else if (fe_degree == 4)
236 do_prolongate_add<4>(to_level, dst_vec, src_vec);
237 else if (fe_degree == 5)
238 do_prolongate_add<5>(to_level, dst_vec, src_vec);
239 else if (fe_degree == 6)
240 do_prolongate_add<6>(to_level, dst_vec, src_vec);
241 else if (fe_degree == 7)
242 do_prolongate_add<7>(to_level, dst_vec, src_vec);
243 else if (fe_degree == 8)
244 do_prolongate_add<8>(to_level, dst_vec, src_vec);
245 else if (fe_degree == 9)
246 do_prolongate_add<9>(to_level, dst_vec, src_vec);
247 else if (fe_degree == 10)
248 do_prolongate_add<10>(to_level, dst_vec, src_vec);
250 do_prolongate_add<-1>(to_level, dst_vec, src_vec);
253 if (dst_inplace ==
false)
256 if (src_inplace ==
true)
262 template <
int dim,
typename Number>
265 const unsigned int from_level,
269 Assert((from_level >= 1) && (from_level <= level_dof_indices.size()),
272 const bool src_inplace =
273 src.
get_partitioner().get() == this->vector_partitioners[from_level].get();
274 if (src_inplace ==
false)
276 if (this->ghosted_level_vector[from_level].get_partitioner().get() !=
277 this->vector_partitioners[from_level].get())
278 this->ghosted_level_vector[from_level].reinit(
279 this->vector_partitioners[from_level]);
280 this->ghosted_level_vector[from_level].copy_locally_owned_data_from(src);
284 this->vector_partitioners[from_level - 1].get();
285 if (dst_inplace ==
false)
287 if (this->ghosted_level_vector[from_level - 1].get_partitioner().get() !=
288 this->vector_partitioners[from_level - 1].get())
289 this->ghosted_level_vector[from_level - 1].reinit(
290 this->vector_partitioners[from_level - 1]);
291 AssertDimension(this->ghosted_level_vector[from_level - 1].local_size(),
293 this->ghosted_level_vector[from_level - 1] = 0.;
297 src_inplace ? src : this->ghosted_level_vector[from_level];
299 dst_inplace ? dst : this->ghosted_level_vector[from_level - 1];
304 do_restrict_add<0>(from_level, dst_vec, src_vec);
305 else if (fe_degree == 1)
306 do_restrict_add<1>(from_level, dst_vec, src_vec);
307 else if (fe_degree == 2)
308 do_restrict_add<2>(from_level, dst_vec, src_vec);
309 else if (fe_degree == 3)
310 do_restrict_add<3>(from_level, dst_vec, src_vec);
311 else if (fe_degree == 4)
312 do_restrict_add<4>(from_level, dst_vec, src_vec);
313 else if (fe_degree == 5)
314 do_restrict_add<5>(from_level, dst_vec, src_vec);
315 else if (fe_degree == 6)
316 do_restrict_add<6>(from_level, dst_vec, src_vec);
317 else if (fe_degree == 7)
318 do_restrict_add<7>(from_level, dst_vec, src_vec);
319 else if (fe_degree == 8)
320 do_restrict_add<8>(from_level, dst_vec, src_vec);
321 else if (fe_degree == 9)
322 do_restrict_add<9>(from_level, dst_vec, src_vec);
323 else if (fe_degree == 10)
324 do_restrict_add<10>(from_level, dst_vec, src_vec);
327 do_restrict_add<-1>(from_level, dst_vec, src_vec);
330 if (dst_inplace ==
false)
333 if (src_inplace ==
true)
341 template <
int dim,
int degree,
typename Number>
345 const unsigned int fe_degree,
350 const int loop_length = degree != -1 ? 2 * degree + 1 : 2 * fe_degree + 1;
351 unsigned int degree_to_3[100];
353 for (
int i = 1; i < loop_length - 1; ++i)
355 degree_to_3[loop_length - 1] = 2;
357 for (
int k = 0; k < (dim > 2 ? loop_length : 1); ++k)
358 for (
int j = 0; j < (dim > 1 ? loop_length : 1); ++j)
360 const unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
361 data[0] *= weights[
shift];
364 for (
int i = 1; i < loop_length - 1; ++i)
365 data[i] *= weights[
shift + 1];
366 data[loop_length - 1] *= weights[
shift + 2];
374 template <
int dim,
typename Number>
375 template <
int degree>
378 const unsigned int to_level,
383 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
384 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
385 const unsigned int n_scalar_cell_dofs =
386 Utilities::fixed_power<dim>(n_child_dofs_1d);
394 if (this->mg_constrained_dofs !=
nullptr &&
395 this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
402 this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
403 .distribute(copy_src);
413 for (
unsigned int cell = 0; cell < n_owned_level_cells[to_level - 1];
416 const unsigned int n_lanes =
417 cell + vec_size > n_owned_level_cells[to_level - 1] ?
418 n_owned_level_cells[to_level - 1] - cell :
422 for (
unsigned int v = 0; v < n_lanes; ++v)
424 const unsigned int shift =
425 internal::MGTransfer::compute_shift_within_children<dim>(
426 parent_child_connect[to_level - 1][cell + v].
second,
427 fe_degree + 1 - element_is_continuous,
429 const unsigned int *indices =
430 &level_dof_indices[to_level - 1]
431 [parent_child_connect[to_level - 1][cell + v]
437 for (
unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
438 for (
unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
439 for (
unsigned int i = 0; i < degree_size; ++i, ++m)
441 indices[c * n_scalar_cell_dofs +
442 k * n_child_dofs_1d * n_child_dofs_1d +
443 j * n_child_dofs_1d + i]);
446 for (std::vector<unsigned short>::const_iterator i =
447 dirichlet_indices[to_level - 1][cell + v].
begin();
448 i != dirichlet_indices[to_level - 1][cell + v].end();
450 evaluation_data[*i][v] = 0.;
455 degree_size * n_child_dofs_1d);
457 if (element_is_continuous)
469 do_forward(prolongation_matrix_1d,
470 evaluation_data.begin() +
471 c * Utilities::fixed_power<dim>(degree_size),
472 evaluation_data.begin() + c * n_scalar_cell_dofs,
475 weight_dofs_on_child<dim, degree, Number>(
476 &weights_on_refined[to_level - 1][(cell / vec_size) * three_to_dim],
479 evaluation_data.begin());
491 do_forward(prolongation_matrix_1d,
492 evaluation_data.begin() +
493 c * Utilities::fixed_power<dim>(degree_size),
494 evaluation_data.begin() + c * n_scalar_cell_dofs,
500 const unsigned int *indices =
501 &level_dof_indices[to_level][cell * n_child_cell_dofs];
502 for (
unsigned int v = 0; v < n_lanes; ++v)
504 for (
unsigned int i = 0; i < n_child_cell_dofs; ++i)
506 indices += n_child_cell_dofs;
513 template <
int dim,
typename Number>
514 template <
int degree>
517 const unsigned int from_level,
522 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
523 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
524 const unsigned int n_scalar_cell_dofs =
525 Utilities::fixed_power<dim>(n_child_dofs_1d);
528 for (
unsigned int cell = 0; cell < n_owned_level_cells[from_level - 1];
531 const unsigned int n_lanes =
532 cell + vec_size > n_owned_level_cells[from_level - 1] ?
533 n_owned_level_cells[from_level - 1] - cell :
538 const unsigned int *indices =
539 &level_dof_indices[from_level][cell * n_child_cell_dofs];
540 for (
unsigned int v = 0; v < n_lanes; ++v)
542 for (
unsigned int i = 0; i < n_child_cell_dofs; ++i)
544 indices += n_child_cell_dofs;
549 degree_size * n_child_dofs_1d);
551 if (element_is_continuous)
553 weight_dofs_on_child<dim, degree, Number>(
554 &weights_on_refined[from_level - 1]
555 [(cell / vec_size) * three_to_dim],
558 evaluation_data.data());
567 do_backward(prolongation_matrix_1d,
569 evaluation_data.begin() + c * n_scalar_cell_dofs,
570 evaluation_data.begin() +
571 c * Utilities::fixed_power<dim>(degree_size),
585 do_backward(prolongation_matrix_1d,
587 evaluation_data.begin() + c * n_scalar_cell_dofs,
588 evaluation_data.begin() +
589 c * Utilities::fixed_power<dim>(degree_size),
595 for (
unsigned int v = 0; v < n_lanes; ++v)
597 const unsigned int shift =
598 internal::MGTransfer::compute_shift_within_children<dim>(
599 parent_child_connect[from_level - 1][cell + v].
second,
600 fe_degree + 1 - element_is_continuous,
603 parent_child_connect[from_level - 1][cell + v].
first *
605 n_child_cell_dofs - 1,
606 level_dof_indices[from_level - 1].size());
607 const unsigned int *indices =
608 &level_dof_indices[from_level - 1]
609 [parent_child_connect[from_level - 1][cell + v]
616 for (std::vector<unsigned short>::const_iterator i =
617 dirichlet_indices[from_level - 1][cell + v].
begin();
618 i != dirichlet_indices[from_level - 1][cell + v].end();
620 evaluation_data[*i][v] = 0.;
622 for (
unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
623 for (
unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
624 for (
unsigned int i = 0; i < degree_size; ++i, ++m)
626 indices[c * n_scalar_cell_dofs +
627 k * n_child_dofs_1d * n_child_dofs_1d +
628 j * n_child_dofs_1d + i]) +=
629 evaluation_data[m][v];
637 template <
int dim,
typename Number>
655 template <
int dim,
typename Number>
665 template <
int dim,
typename Number>
667 const std::vector<MGConstrainedDoFs> &mg_c)
668 : same_for_all(false)
670 for (
const auto &constrained_block_dofs : mg_c)
676 template <
int dim,
typename Number>
682 ExcMessage(
"This object was initialized with support for usage with "
683 "one DoFHandler for each block, but this method assumes "
684 "that the same DoFHandler is used for all the blocks!"));
687 matrix_free_transfer_vector[0].initialize_constraints(mg_c);
692 template <
int dim,
typename Number>
695 const std::vector<MGConstrainedDoFs> &mg_c)
698 ExcMessage(
"This object was initialized with support for using "
699 "the same DoFHandler for all the blocks, but this "
700 "method assumes that there is a separate DoFHandler "
704 for (
unsigned int i = 0; i < mg_c.size(); ++i)
705 matrix_free_transfer_vector[i].initialize_constraints(mg_c[i]);
710 template <
int dim,
typename Number>
714 matrix_free_transfer_vector.clear();
719 template <
int dim,
typename Number>
725 matrix_free_transfer_vector[0].build(dof_handler);
730 template <
int dim,
typename Number>
735 AssertDimension(matrix_free_transfer_vector.size(), dof_handler.size());
736 for (
unsigned int i = 0; i < dof_handler.size(); ++i)
737 matrix_free_transfer_vector[i].build(*dof_handler[i]);
742 template <
int dim,
typename Number>
745 const unsigned int to_level,
757 const unsigned int data_block = same_for_all ? 0 :
b;
758 matrix_free_transfer_vector[data_block].prolongate(to_level,
766 template <
int dim,
typename Number>
769 const unsigned int from_level,
781 const unsigned int data_block = same_for_all ? 0 :
b;
782 matrix_free_transfer_vector[data_block].restrict_and_add(from_level,
790 template <
int dim,
typename Number>
794 std::size_t total_memory_consumption = 0;
795 for (
const auto &el : matrix_free_transfer_vector)
796 total_memory_consumption += el.memory_consumption();
797 return total_memory_consumption;
803 #include "mg_transfer_matrix_free.inst"