17 #include <deal.II/base/function.h> 18 #include <deal.II/base/logstream.h> 19 #include <deal.II/base/vectorization.h> 21 #include <deal.II/dofs/dof_accessor.h> 22 #include <deal.II/dofs/dof_tools.h> 24 #include <deal.II/fe/fe.h> 26 #include <deal.II/grid/tria.h> 27 #include <deal.II/grid/tria_iterator.h> 29 #include <deal.II/lac/la_parallel_vector.h> 31 #include <deal.II/matrix_free/evaluation_kernels.h> 33 #include <deal.II/multigrid/mg_tools.h> 34 #include <deal.II/multigrid/mg_transfer_internal.h> 35 #include <deal.II/multigrid/mg_transfer_matrix_free.h> 39 DEAL_II_NAMESPACE_OPEN
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 this->fill_and_communicate_copy_indices(mg_dof);
101 std::vector<std::vector<Number>> weights_unvectorized;
105 internal::MGTransfer::setup_transfer<dim, Number>(
107 this->mg_constrained_dofs,
110 parent_child_connect,
113 weights_unvectorized,
114 this->copy_indices_global_mine,
115 this->ghosted_level_vector);
118 element_is_continuous = elem_info.element_is_continuous;
120 n_child_cell_dofs = elem_info.n_child_cell_dofs;
123 prolongation_matrix_1d.resize(elem_info.prolongation_matrix_1d.size());
124 for (
unsigned int i = 0; i < elem_info.prolongation_matrix_1d.size(); i++)
125 prolongation_matrix_1d[i] = elem_info.prolongation_matrix_1d[i];
129 const unsigned int n_levels = mg_dof.get_triangulation().n_global_levels();
131 const unsigned int n_weights_per_cell = Utilities::fixed_power<dim>(3);
132 weights_on_refined.resize(n_levels - 1);
133 for (
unsigned int level = 1; level < n_levels; ++level)
135 weights_on_refined[level - 1].resize(
136 ((n_owned_level_cells[level - 1] + vec_size - 1) / vec_size) *
139 for (
unsigned int c = 0; c < n_owned_level_cells[level - 1]; ++c)
141 const unsigned int comp = c / vec_size;
142 const unsigned int v = c % vec_size;
143 for (
unsigned int i = 0; i < n_weights_per_cell; ++i)
145 weights_on_refined[level - 1][comp * n_weights_per_cell + i][v] =
146 weights_unvectorized[level - 1][c * n_weights_per_cell + i];
151 evaluation_data.resize(n_child_cell_dofs);
156 template <
int dim,
typename Number>
159 const unsigned int to_level,
163 Assert((to_level >= 1) && (to_level <= level_dof_indices.size()),
171 this->ghosted_level_vector[to_level - 1].copy_locally_owned_data_from(src);
172 this->ghosted_level_vector[to_level - 1].update_ghost_values();
173 this->ghosted_level_vector[to_level] = 0.;
179 do_prolongate_add<0>(to_level,
180 this->ghosted_level_vector[to_level],
181 this->ghosted_level_vector[to_level - 1]);
182 else if (fe_degree == 1)
183 do_prolongate_add<1>(to_level,
184 this->ghosted_level_vector[to_level],
185 this->ghosted_level_vector[to_level - 1]);
186 else if (fe_degree == 2)
187 do_prolongate_add<2>(to_level,
188 this->ghosted_level_vector[to_level],
189 this->ghosted_level_vector[to_level - 1]);
190 else if (fe_degree == 3)
191 do_prolongate_add<3>(to_level,
192 this->ghosted_level_vector[to_level],
193 this->ghosted_level_vector[to_level - 1]);
194 else if (fe_degree == 4)
195 do_prolongate_add<4>(to_level,
196 this->ghosted_level_vector[to_level],
197 this->ghosted_level_vector[to_level - 1]);
198 else if (fe_degree == 5)
199 do_prolongate_add<5>(to_level,
200 this->ghosted_level_vector[to_level],
201 this->ghosted_level_vector[to_level - 1]);
202 else if (fe_degree == 6)
203 do_prolongate_add<6>(to_level,
204 this->ghosted_level_vector[to_level],
205 this->ghosted_level_vector[to_level - 1]);
206 else if (fe_degree == 7)
207 do_prolongate_add<7>(to_level,
208 this->ghosted_level_vector[to_level],
209 this->ghosted_level_vector[to_level - 1]);
210 else if (fe_degree == 8)
211 do_prolongate_add<8>(to_level,
212 this->ghosted_level_vector[to_level],
213 this->ghosted_level_vector[to_level - 1]);
214 else if (fe_degree == 9)
215 do_prolongate_add<9>(to_level,
216 this->ghosted_level_vector[to_level],
217 this->ghosted_level_vector[to_level - 1]);
218 else if (fe_degree == 10)
219 do_prolongate_add<10>(to_level,
220 this->ghosted_level_vector[to_level],
221 this->ghosted_level_vector[to_level - 1]);
223 do_prolongate_add<-1>(to_level,
224 this->ghosted_level_vector[to_level],
225 this->ghosted_level_vector[to_level - 1]);
233 template <
int dim,
typename Number>
236 const unsigned int from_level,
240 Assert((from_level >= 1) && (from_level <= level_dof_indices.size()),
245 AssertDimension(this->ghosted_level_vector[from_level - 1].local_size(),
248 this->ghosted_level_vector[from_level].copy_locally_owned_data_from(src);
249 this->ghosted_level_vector[from_level].update_ghost_values();
250 this->ghosted_level_vector[from_level - 1] = 0.;
253 do_restrict_add<0>(from_level,
254 this->ghosted_level_vector[from_level - 1],
255 this->ghosted_level_vector[from_level]);
256 else if (fe_degree == 1)
257 do_restrict_add<1>(from_level,
258 this->ghosted_level_vector[from_level - 1],
259 this->ghosted_level_vector[from_level]);
260 else if (fe_degree == 2)
261 do_restrict_add<2>(from_level,
262 this->ghosted_level_vector[from_level - 1],
263 this->ghosted_level_vector[from_level]);
264 else if (fe_degree == 3)
265 do_restrict_add<3>(from_level,
266 this->ghosted_level_vector[from_level - 1],
267 this->ghosted_level_vector[from_level]);
268 else if (fe_degree == 4)
269 do_restrict_add<4>(from_level,
270 this->ghosted_level_vector[from_level - 1],
271 this->ghosted_level_vector[from_level]);
272 else if (fe_degree == 5)
273 do_restrict_add<5>(from_level,
274 this->ghosted_level_vector[from_level - 1],
275 this->ghosted_level_vector[from_level]);
276 else if (fe_degree == 6)
277 do_restrict_add<6>(from_level,
278 this->ghosted_level_vector[from_level - 1],
279 this->ghosted_level_vector[from_level]);
280 else if (fe_degree == 7)
281 do_restrict_add<7>(from_level,
282 this->ghosted_level_vector[from_level - 1],
283 this->ghosted_level_vector[from_level]);
284 else if (fe_degree == 8)
285 do_restrict_add<8>(from_level,
286 this->ghosted_level_vector[from_level - 1],
287 this->ghosted_level_vector[from_level]);
288 else if (fe_degree == 9)
289 do_restrict_add<9>(from_level,
290 this->ghosted_level_vector[from_level - 1],
291 this->ghosted_level_vector[from_level]);
292 else if (fe_degree == 10)
293 do_restrict_add<10>(from_level,
294 this->ghosted_level_vector[from_level - 1],
295 this->ghosted_level_vector[from_level]);
298 do_restrict_add<-1>(from_level,
299 this->ghosted_level_vector[from_level - 1],
300 this->ghosted_level_vector[from_level]);
303 dst += this->ghosted_level_vector[from_level - 1];
310 template <
int dim,
int degree,
typename Number>
314 const unsigned int fe_degree,
319 const int loop_length = degree != -1 ? 2 * degree + 1 : 2 * fe_degree + 1;
320 unsigned int degree_to_3[100];
322 for (
int i = 1; i < loop_length - 1; ++i)
324 degree_to_3[loop_length - 1] = 2;
326 for (
int k = 0; k < (dim > 2 ? loop_length : 1); ++k)
327 for (
int j = 0; j < (dim > 1 ? loop_length : 1); ++j)
329 const unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
330 data[0] *= weights[shift];
333 for (
int i = 1; i < loop_length - 1; ++i)
334 data[i] *= weights[shift + 1];
335 data[loop_length - 1] *= weights[shift + 2];
343 template <
int dim,
typename Number>
344 template <
int degree>
347 const unsigned int to_level,
352 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
353 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
354 const unsigned int n_scalar_cell_dofs =
355 Utilities::fixed_power<dim>(n_child_dofs_1d);
358 for (
unsigned int cell = 0; cell < n_owned_level_cells[to_level - 1];
361 const unsigned int n_lanes =
362 cell + vec_size > n_owned_level_cells[to_level - 1] ?
363 n_owned_level_cells[to_level - 1] - cell :
367 for (
unsigned int v = 0; v < n_lanes; ++v)
369 const unsigned int shift =
370 internal::MGTransfer::compute_shift_within_children<dim>(
371 parent_child_connect[to_level - 1][cell + v].second,
372 fe_degree + 1 - element_is_continuous,
374 const unsigned int *indices =
375 &level_dof_indices[to_level - 1]
376 [parent_child_connect[to_level - 1][cell + v]
382 for (
unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
383 for (
unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
384 for (
unsigned int i = 0; i < degree_size; ++i, ++m)
386 indices[c * n_scalar_cell_dofs +
387 k * n_child_dofs_1d * n_child_dofs_1d +
388 j * n_child_dofs_1d + i]);
391 for (std::vector<unsigned short>::const_iterator i =
392 dirichlet_indices[to_level - 1][cell + v].begin();
393 i != dirichlet_indices[to_level - 1][cell + v].end();
395 evaluation_data[*i][v] = 0.;
400 degree_size * n_child_dofs_1d);
402 if (element_is_continuous)
414 do_forward(prolongation_matrix_1d,
415 evaluation_data.begin() +
416 c * Utilities::fixed_power<dim>(degree_size),
417 evaluation_data.begin() + c * n_scalar_cell_dofs,
420 weight_dofs_on_child<dim, degree, Number>(
421 &weights_on_refined[to_level - 1][(cell / vec_size) * three_to_dim],
424 evaluation_data.begin());
436 do_forward(prolongation_matrix_1d,
437 evaluation_data.begin() +
438 c * Utilities::fixed_power<dim>(degree_size),
439 evaluation_data.begin() + c * n_scalar_cell_dofs,
445 const unsigned int *indices =
446 &level_dof_indices[to_level][cell * n_child_cell_dofs];
447 for (
unsigned int v = 0; v < n_lanes; ++v)
449 for (
unsigned int i = 0; i < n_child_cell_dofs; ++i)
451 indices += n_child_cell_dofs;
458 template <
int dim,
typename Number>
459 template <
int degree>
462 const unsigned int from_level,
467 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
468 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
469 const unsigned int n_scalar_cell_dofs =
470 Utilities::fixed_power<dim>(n_child_dofs_1d);
473 for (
unsigned int cell = 0; cell < n_owned_level_cells[from_level - 1];
476 const unsigned int n_lanes =
477 cell + vec_size > n_owned_level_cells[from_level - 1] ?
478 n_owned_level_cells[from_level - 1] - cell :
483 const unsigned int *indices =
484 &level_dof_indices[from_level][cell * n_child_cell_dofs];
485 for (
unsigned int v = 0; v < n_lanes; ++v)
487 for (
unsigned int i = 0; i < n_child_cell_dofs; ++i)
489 indices += n_child_cell_dofs;
494 degree_size * n_child_dofs_1d);
496 if (element_is_continuous)
498 weight_dofs_on_child<dim, degree, Number>(
499 &weights_on_refined[from_level - 1]
500 [(cell / vec_size) * three_to_dim],
503 evaluation_data.data());
512 do_backward(prolongation_matrix_1d,
514 evaluation_data.begin() + c * n_scalar_cell_dofs,
515 evaluation_data.begin() +
516 c * Utilities::fixed_power<dim>(degree_size),
530 do_backward(prolongation_matrix_1d,
532 evaluation_data.begin() + c * n_scalar_cell_dofs,
533 evaluation_data.begin() +
534 c * Utilities::fixed_power<dim>(degree_size),
540 for (
unsigned int v = 0; v < n_lanes; ++v)
542 const unsigned int shift =
543 internal::MGTransfer::compute_shift_within_children<dim>(
544 parent_child_connect[from_level - 1][cell + v].second,
545 fe_degree + 1 - element_is_continuous,
548 parent_child_connect[from_level - 1][cell + v].first *
550 n_child_cell_dofs - 1,
551 level_dof_indices[from_level - 1].size());
552 const unsigned int *indices =
553 &level_dof_indices[from_level - 1]
554 [parent_child_connect[from_level - 1][cell + v]
561 for (std::vector<unsigned short>::const_iterator i =
562 dirichlet_indices[from_level - 1][cell + v].begin();
563 i != dirichlet_indices[from_level - 1][cell + v].end();
565 evaluation_data[*i][v] = 0.;
567 for (
unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
568 for (
unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
569 for (
unsigned int i = 0; i < degree_size; ++i, ++m)
571 indices[c * n_scalar_cell_dofs +
572 k * n_child_dofs_1d * n_child_dofs_1d +
573 j * n_child_dofs_1d + i]) +=
574 evaluation_data[m][v];
582 template <
int dim,
typename Number>
600 template <
int dim,
typename Number>
610 template <
int dim,
typename Number>
612 const std::vector<MGConstrainedDoFs> &mg_c)
613 : same_for_all(false)
615 for (
const auto &constrained_block_dofs : mg_c)
621 template <
int dim,
typename Number>
627 ExcMessage(
"This object was initialized with support for usage with " 628 "one DoFHandler for each block, but this method assumes " 629 "that the same DoFHandler is used for all the blocks!"));
632 matrix_free_transfer_vector[0].initialize_constraints(mg_c);
637 template <
int dim,
typename Number>
640 const std::vector<MGConstrainedDoFs> &mg_c)
643 ExcMessage(
"This object was initialized with support for using " 644 "the same DoFHandler for all the blocks, but this " 645 "method assumes that there is a separate DoFHandler " 649 for (
unsigned int i = 0; i < mg_c.size(); ++i)
650 matrix_free_transfer_vector[i].initialize_constraints(mg_c[i]);
655 template <
int dim,
typename Number>
659 matrix_free_transfer_vector.clear();
664 template <
int dim,
typename Number>
670 matrix_free_transfer_vector[0].build(mg_dof);
675 template <
int dim,
typename Number>
681 for (
unsigned int i = 0; i < mg_dof.size(); ++i)
682 matrix_free_transfer_vector[i].build(*mg_dof[i]);
687 template <
int dim,
typename Number>
690 const unsigned int to_level,
694 const unsigned int n_blocks = src.
n_blocks();
700 for (
unsigned int b = 0; b < n_blocks; ++b)
702 const unsigned int data_block = same_for_all ? 0 : b;
703 matrix_free_transfer_vector[data_block].prolongate(to_level,
711 template <
int dim,
typename Number>
714 const unsigned int from_level,
718 const unsigned int n_blocks = src.
n_blocks();
724 for (
unsigned int b = 0; b < n_blocks; ++b)
726 const unsigned int data_block = same_for_all ? 0 : b;
727 matrix_free_transfer_vector[data_block].restrict_and_add(from_level,
735 template <
int dim,
typename Number>
739 std::size_t total_memory_consumption = 0;
740 for (
const auto &el : matrix_free_transfer_vector)
741 total_memory_consumption += el.memory_consumption();
742 return total_memory_consumption;
748 #include "mg_transfer_matrix_free.inst" 751 DEAL_II_NAMESPACE_CLOSE
void copy_locally_owned_data_from(const Vector< Number2, MemorySpace > &src)
size_type local_size() const
void do_restrict_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
#define AssertDimension(dim1, dim2)
std::size_t memory_consumption() const
void build(const DoFHandler< dim, dim > &mg_dof)
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
std::size_t memory_consumption() const
Number local_element(const size_type local_index) const
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< Number > &src) const override
constexpr unsigned int pow(const unsigned int base, const int iexp)
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
void do_prolongate_add(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
SmartPointer< const MGConstrainedDoFs, MGLevelGlobalTransfer< LinearAlgebra::distributed::Vector< Number > > > mg_constrained_dofs
unsigned int n_blocks() const
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< Number > &src) const override
std::vector< MGTransferMatrixFree< dim, Number > > matrix_free_transfer_vector
MGTransferBlockMatrixFree()=default
static ::ExceptionBase & ExcNotImplemented()
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
BlockType & block(const unsigned int i)
void build(const DoFHandler< dim, dim > &mg_dof)
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)