Reference documentation for deal.II version 9.3.2
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
mg_transfer_matrix_free.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/function.h>
18 #include <deal.II/base/logstream.h>
20 
22 #include <deal.II/dofs/dof_tools.h>
23 
24 #include <deal.II/fe/fe.h>
25 
26 #include <deal.II/grid/tria.h>
28 
30 
32 
36 
37 #include <algorithm>
38 
40 
41 
42 template <int dim, typename Number>
44  : fe_degree(0)
45  , element_is_continuous(false)
46  , n_components(0)
47  , n_child_cell_dofs(0)
48 {}
49 
50 
51 
52 template <int dim, typename Number>
54  const MGConstrainedDoFs &mg_c)
55  : fe_degree(0)
56  , element_is_continuous(false)
57  , n_components(0)
58  , n_child_cell_dofs(0)
59 {
60  this->mg_constrained_dofs = &mg_c;
61 }
62 
63 
64 
65 template <int dim, typename Number>
66 void
68  const MGConstrainedDoFs &mg_c)
69 {
70  this->mg_constrained_dofs = &mg_c;
71 }
72 
73 
74 
75 template <int dim, typename Number>
76 void
78 {
81  fe_degree = 0;
82  element_is_continuous = false;
83  n_components = 0;
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();
92 }
93 
94 
95 template <int dim, typename Number>
96 void
98  const DoFHandler<dim, dim> &dof_handler,
99  const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
100  &external_partitioners)
101 {
102  this->fill_and_communicate_copy_indices(dof_handler);
103 
104  vector_partitioners.resize(0,
105  dof_handler.get_triangulation().n_global_levels() -
106  1);
107  for (unsigned int level = 0; level <= this->ghosted_level_vector.max_level();
108  ++level)
109  vector_partitioners[level] =
110  this->ghosted_level_vector[level].get_partitioner();
111 
112  std::vector<std::vector<Number>> weights_unvectorized;
113 
115 
116  internal::MGTransfer::setup_transfer<dim, Number>(
117  dof_handler,
118  this->mg_constrained_dofs,
119  external_partitioners,
120  elem_info,
121  level_dof_indices,
122  parent_child_connect,
123  n_owned_level_cells,
124  dirichlet_indices,
125  weights_unvectorized,
126  this->copy_indices_global_mine,
127  vector_partitioners);
128 
129  // reinit the ghosted level vector in case its partitioner differs from the
130  // one the user intends to use externally
131  this->ghosted_level_vector.resize(0, vector_partitioners.max_level());
132  for (unsigned int level = 0; level <= vector_partitioners.max_level();
133  ++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);
137  else
138  this->ghosted_level_vector[level].reinit(vector_partitioners[level]);
139 
140  // unpack element info data
141  fe_degree = elem_info.fe_degree;
142  element_is_continuous = elem_info.element_is_continuous;
143  n_components = elem_info.n_components;
144  n_child_cell_dofs = elem_info.n_child_cell_dofs;
145 
146  // duplicate and put into vectorized array
147  prolongation_matrix_1d.resize(elem_info.prolongation_matrix_1d.size());
148  for (unsigned int i = 0; i < elem_info.prolongation_matrix_1d.size(); i++)
149  prolongation_matrix_1d[i] = elem_info.prolongation_matrix_1d[i];
150 
151  // reshuffle into aligned vector of vectorized arrays
152  const unsigned int vec_size = VectorizedArray<Number>::size();
153  const unsigned int n_levels =
154  dof_handler.get_triangulation().n_global_levels();
155 
156  const unsigned int n_weights_per_cell = Utilities::fixed_power<dim>(3);
157  weights_on_refined.resize(n_levels - 1);
158  for (unsigned int level = 1; level < n_levels; ++level)
159  {
160  weights_on_refined[level - 1].resize(
161  ((n_owned_level_cells[level - 1] + vec_size - 1) / vec_size) *
162  n_weights_per_cell);
163 
164  for (unsigned int c = 0; c < n_owned_level_cells[level - 1]; ++c)
165  {
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)
169  {
170  weights_on_refined[level - 1][comp * n_weights_per_cell + i][v] =
171  weights_unvectorized[level - 1][c * n_weights_per_cell + i];
172  }
173  }
174  }
175 
176  evaluation_data.resize(n_child_cell_dofs);
177 }
178 
179 
180 
181 template <int dim, typename Number>
182 void
184  const unsigned int to_level,
187 {
188  dst = 0;
189  prolongate_and_add(to_level, dst, src);
190 }
191 
192 
193 
194 template <int dim, typename Number>
195 void
197  const unsigned int to_level,
200 {
201  Assert((to_level >= 1) && (to_level <= level_dof_indices.size()),
202  ExcIndexRange(to_level, 1, level_dof_indices.size() + 1));
203 
204  const bool src_inplace = src.get_partitioner().get() ==
205  this->vector_partitioners[to_level - 1].get();
206  if (src_inplace == false)
207  {
208  if (this->ghosted_level_vector[to_level - 1].get_partitioner().get() !=
209  this->vector_partitioners[to_level - 1].get())
210  this->ghosted_level_vector[to_level - 1].reinit(
211  this->vector_partitioners[to_level - 1]);
212  this->ghosted_level_vector[to_level - 1].copy_locally_owned_data_from(
213  src);
214  }
215 
216  const bool dst_inplace =
217  dst.get_partitioner().get() == this->vector_partitioners[to_level].get();
218  if (dst_inplace == false)
219  {
220  if (this->ghosted_level_vector[to_level].get_partitioner().get() !=
221  this->vector_partitioners[to_level].get())
222  this->ghosted_level_vector[to_level].reinit(
223  this->vector_partitioners[to_level]);
224  AssertDimension(this->ghosted_level_vector[to_level].locally_owned_size(),
225  dst.locally_owned_size());
226  this->ghosted_level_vector[to_level] = 0.;
227  }
228 
230  src_inplace ? src : this->ghosted_level_vector[to_level - 1];
232  dst_inplace ? dst : this->ghosted_level_vector[to_level];
233 
234  src_vec.update_ghost_values();
235  // the implementation in do_prolongate_add is templated in the degree of the
236  // element (for efficiency reasons), so we need to find the appropriate
237  // kernel here...
238  if (fe_degree == 0)
239  do_prolongate_add<0>(to_level, dst_vec, src_vec);
240  else if (fe_degree == 1)
241  do_prolongate_add<1>(to_level, dst_vec, src_vec);
242  else if (fe_degree == 2)
243  do_prolongate_add<2>(to_level, dst_vec, src_vec);
244  else if (fe_degree == 3)
245  do_prolongate_add<3>(to_level, dst_vec, src_vec);
246  else if (fe_degree == 4)
247  do_prolongate_add<4>(to_level, dst_vec, src_vec);
248  else if (fe_degree == 5)
249  do_prolongate_add<5>(to_level, dst_vec, src_vec);
250  else if (fe_degree == 6)
251  do_prolongate_add<6>(to_level, dst_vec, src_vec);
252  else if (fe_degree == 7)
253  do_prolongate_add<7>(to_level, dst_vec, src_vec);
254  else if (fe_degree == 8)
255  do_prolongate_add<8>(to_level, dst_vec, src_vec);
256  else if (fe_degree == 9)
257  do_prolongate_add<9>(to_level, dst_vec, src_vec);
258  else if (fe_degree == 10)
259  do_prolongate_add<10>(to_level, dst_vec, src_vec);
260  else
261  do_prolongate_add<-1>(to_level, dst_vec, src_vec);
262 
264  if (dst_inplace == false)
265  dst += dst_vec;
266 
267  if (src_inplace == true)
268  src.zero_out_ghost_values();
269 }
270 
271 
272 
273 template <int dim, typename Number>
274 void
276  const unsigned int from_level,
279 {
280  Assert((from_level >= 1) && (from_level <= level_dof_indices.size()),
281  ExcIndexRange(from_level, 1, level_dof_indices.size() + 1));
282 
283  const bool src_inplace =
284  src.get_partitioner().get() == this->vector_partitioners[from_level].get();
285  if (src_inplace == false)
286  {
287  if (this->ghosted_level_vector[from_level].get_partitioner().get() !=
288  this->vector_partitioners[from_level].get())
289  this->ghosted_level_vector[from_level].reinit(
290  this->vector_partitioners[from_level]);
291  this->ghosted_level_vector[from_level].copy_locally_owned_data_from(src);
292  }
293 
294  const bool dst_inplace = dst.get_partitioner().get() ==
295  this->vector_partitioners[from_level - 1].get();
296  if (dst_inplace == false)
297  {
298  if (this->ghosted_level_vector[from_level - 1].get_partitioner().get() !=
299  this->vector_partitioners[from_level - 1].get())
300  this->ghosted_level_vector[from_level - 1].reinit(
301  this->vector_partitioners[from_level - 1]);
303  this->ghosted_level_vector[from_level - 1].locally_owned_size(),
304  dst.locally_owned_size());
305  this->ghosted_level_vector[from_level - 1] = 0.;
306  }
307 
309  src_inplace ? src : this->ghosted_level_vector[from_level];
311  dst_inplace ? dst : this->ghosted_level_vector[from_level - 1];
312 
313  src_vec.update_ghost_values();
314 
315  if (fe_degree == 0)
316  do_restrict_add<0>(from_level, dst_vec, src_vec);
317  else if (fe_degree == 1)
318  do_restrict_add<1>(from_level, dst_vec, src_vec);
319  else if (fe_degree == 2)
320  do_restrict_add<2>(from_level, dst_vec, src_vec);
321  else if (fe_degree == 3)
322  do_restrict_add<3>(from_level, dst_vec, src_vec);
323  else if (fe_degree == 4)
324  do_restrict_add<4>(from_level, dst_vec, src_vec);
325  else if (fe_degree == 5)
326  do_restrict_add<5>(from_level, dst_vec, src_vec);
327  else if (fe_degree == 6)
328  do_restrict_add<6>(from_level, dst_vec, src_vec);
329  else if (fe_degree == 7)
330  do_restrict_add<7>(from_level, dst_vec, src_vec);
331  else if (fe_degree == 8)
332  do_restrict_add<8>(from_level, dst_vec, src_vec);
333  else if (fe_degree == 9)
334  do_restrict_add<9>(from_level, dst_vec, src_vec);
335  else if (fe_degree == 10)
336  do_restrict_add<10>(from_level, dst_vec, src_vec);
337  else
338  // go to the non-templated version of the evaluator
339  do_restrict_add<-1>(from_level, dst_vec, src_vec);
340 
342  if (dst_inplace == false)
343  dst += dst_vec;
344 
345  if (src_inplace == true)
346  src.zero_out_ghost_values();
347 }
348 
349 
350 
351 namespace
352 {
353  template <int dim, int degree, typename Number>
354  void
355  weight_dofs_on_child(const VectorizedArray<Number> *weights,
356  const unsigned int n_components,
357  const unsigned int fe_degree,
359  {
360  Assert(fe_degree > 0, ExcNotImplemented());
361  Assert(fe_degree < 100, ExcNotImplemented());
362  const int loop_length = degree != -1 ? 2 * degree + 1 : 2 * fe_degree + 1;
363  unsigned int degree_to_3[100];
364  degree_to_3[0] = 0;
365  for (int i = 1; i < loop_length - 1; ++i)
366  degree_to_3[i] = 1;
367  degree_to_3[loop_length - 1] = 2;
368  for (unsigned int c = 0; c < n_components; ++c)
369  for (int k = 0; k < (dim > 2 ? loop_length : 1); ++k)
370  for (int j = 0; j < (dim > 1 ? loop_length : 1); ++j)
371  {
372  const unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
373  data[0] *= weights[shift];
374  // loop bound as int avoids compiler warnings in case loop_length
375  // == 1 (polynomial degree 0)
376  for (int i = 1; i < loop_length - 1; ++i)
377  data[i] *= weights[shift + 1];
378  data[loop_length - 1] *= weights[shift + 2];
379  data += loop_length;
380  }
381  }
382 } // namespace
383 
384 
385 
386 template <int dim, typename Number>
387 template <int degree>
388 void
390  const unsigned int to_level,
393 {
394  const unsigned int vec_size = VectorizedArray<Number>::size();
395  const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
396  const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
397  const unsigned int n_scalar_cell_dofs =
398  Utilities::fixed_power<dim>(n_child_dofs_1d);
399  constexpr unsigned int three_to_dim = Utilities::pow(3, dim);
400 
401  // If we have user defined MG constraints, we must create
402  // a non-const, ghosted version of the source vector to distribute
403  // constraints.
404  const LinearAlgebra::distributed::Vector<Number> *to_use = &src;
406  if (this->mg_constrained_dofs != nullptr &&
407  this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
408  .get_local_lines()
409  .size() > 0)
410  {
412 
413  // Distribute any user defined constraints
414  this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
415  .distribute(copy_src);
416 
417  // Re-initialize new ghosted vector with correct constraints
418  new_src.reinit(copy_src);
419  new_src = copy_src;
420  new_src.update_ghost_values();
421 
422  to_use = &new_src;
423  }
424 
425  for (unsigned int cell = 0; cell < n_owned_level_cells[to_level - 1];
426  cell += vec_size)
427  {
428  const unsigned int n_lanes =
429  (cell + vec_size > n_owned_level_cells[to_level - 1]) ?
430  (n_owned_level_cells[to_level - 1] - cell) :
431  vec_size;
432 
433  // read from source vector
434  for (unsigned int v = 0; v < n_lanes; ++v)
435  {
436  const unsigned int shift =
437  internal::MGTransfer::compute_shift_within_children<dim>(
438  parent_child_connect[to_level - 1][cell + v].second,
439  fe_degree + 1 - element_is_continuous,
440  fe_degree);
441  const unsigned int *indices =
442  &level_dof_indices[to_level - 1]
443  [parent_child_connect[to_level - 1][cell + v]
444  .first *
445  n_child_cell_dofs +
446  shift];
447  for (unsigned int c = 0, m = 0; c < n_components; ++c)
448  {
449  for (unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
450  for (unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
451  for (unsigned int i = 0; i < degree_size; ++i, ++m)
452  evaluation_data[m][v] = to_use->local_element(
453  indices[c * n_scalar_cell_dofs +
454  k * n_child_dofs_1d * n_child_dofs_1d +
455  j * n_child_dofs_1d + i]);
456 
457  // apply Dirichlet boundary conditions on parent cell
458  for (std::vector<unsigned short>::const_iterator i =
459  dirichlet_indices[to_level - 1][cell + v].begin();
460  i != dirichlet_indices[to_level - 1][cell + v].end();
461  ++i)
462  evaluation_data[*i][v] = 0.;
463  }
464  }
465 
466  AssertDimension(prolongation_matrix_1d.size(),
467  degree_size * n_child_dofs_1d);
468  // perform tensorized operation
469  if (element_is_continuous)
470  {
471  // must go through the components backwards because we want to write
472  // the output to the same array as the input
473  for (int c = n_components - 1; c >= 0; --c)
477  dim,
478  degree + 1,
479  2 * degree + 1,
481  VectorizedArray<Number>>::do_forward(1,
482  prolongation_matrix_1d,
483  evaluation_data.begin() +
485  dim>(degree_size),
486  evaluation_data.begin() +
487  c * n_scalar_cell_dofs,
488  fe_degree + 1,
489  2 * fe_degree + 1);
490  weight_dofs_on_child<dim, degree, Number>(
491  &weights_on_refined[to_level - 1][(cell / vec_size) * three_to_dim],
492  n_components,
493  fe_degree,
494  evaluation_data.begin());
495  }
496  else
497  {
498  for (int c = n_components - 1; c >= 0; --c)
502  dim,
503  degree + 1,
504  2 * degree + 2,
506  VectorizedArray<Number>>::do_forward(1,
507  prolongation_matrix_1d,
508  evaluation_data.begin() +
510  dim>(degree_size),
511  evaluation_data.begin() +
512  c * n_scalar_cell_dofs,
513  fe_degree + 1,
514  2 * fe_degree + 2);
515  }
516 
517  // write into dst vector
518  const unsigned int *indices =
519  &level_dof_indices[to_level][cell * n_child_cell_dofs];
520  for (unsigned int v = 0; v < n_lanes; ++v)
521  {
522  for (unsigned int i = 0; i < n_child_cell_dofs; ++i)
523  dst.local_element(indices[i]) += evaluation_data[i][v];
524  indices += n_child_cell_dofs;
525  }
526  }
527 }
528 
529 
530 
531 template <int dim, typename Number>
532 template <int degree>
533 void
535  const unsigned int from_level,
538 {
539  const unsigned int vec_size = VectorizedArray<Number>::size();
540  const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
541  const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
542  const unsigned int n_scalar_cell_dofs =
543  Utilities::fixed_power<dim>(n_child_dofs_1d);
544  constexpr unsigned int three_to_dim = Utilities::pow(3, dim);
545 
546  for (unsigned int cell = 0; cell < n_owned_level_cells[from_level - 1];
547  cell += vec_size)
548  {
549  const unsigned int n_lanes =
550  (cell + vec_size > n_owned_level_cells[from_level - 1]) ?
551  (n_owned_level_cells[from_level - 1] - cell) :
552  vec_size;
553 
554  // read from source vector
555  {
556  const unsigned int *indices =
557  &level_dof_indices[from_level][cell * n_child_cell_dofs];
558  for (unsigned int v = 0; v < n_lanes; ++v)
559  {
560  for (unsigned int i = 0; i < n_child_cell_dofs; ++i)
561  evaluation_data[i][v] = src.local_element(indices[i]);
562  indices += n_child_cell_dofs;
563  }
564  }
565 
566  AssertDimension(prolongation_matrix_1d.size(),
567  degree_size * n_child_dofs_1d);
568  // perform tensorized operation
569  if (element_is_continuous)
570  {
571  weight_dofs_on_child<dim, degree, Number>(
572  &weights_on_refined[from_level - 1]
573  [(cell / vec_size) * three_to_dim],
574  n_components,
575  fe_degree,
576  evaluation_data.data());
577  for (unsigned int c = 0; c < n_components; ++c)
581  dim,
582  degree + 1,
583  2 * degree + 1,
585  VectorizedArray<Number>>::do_backward(1,
586  prolongation_matrix_1d,
587  false,
588  evaluation_data.begin() +
589  c * n_scalar_cell_dofs,
590  evaluation_data.begin() +
591  c *
593  dim>(degree_size),
594  fe_degree + 1,
595  2 * fe_degree + 1);
596  }
597  else
598  {
599  for (unsigned int c = 0; c < n_components; ++c)
603  dim,
604  degree + 1,
605  2 * degree + 2,
607  VectorizedArray<Number>>::do_backward(1,
608  prolongation_matrix_1d,
609  false,
610  evaluation_data.begin() +
611  c * n_scalar_cell_dofs,
612  evaluation_data.begin() +
613  c *
615  dim>(degree_size),
616  fe_degree + 1,
617  2 * fe_degree + 2);
618  }
619 
620  // write into dst vector
621  for (unsigned int v = 0; v < n_lanes; ++v)
622  {
623  const unsigned int shift =
624  internal::MGTransfer::compute_shift_within_children<dim>(
625  parent_child_connect[from_level - 1][cell + v].second,
626  fe_degree + 1 - element_is_continuous,
627  fe_degree);
629  parent_child_connect[from_level - 1][cell + v].first *
630  n_child_cell_dofs +
631  n_child_cell_dofs - 1,
632  level_dof_indices[from_level - 1].size());
633  const unsigned int *indices =
634  &level_dof_indices[from_level - 1]
635  [parent_child_connect[from_level - 1][cell + v]
636  .first *
637  n_child_cell_dofs +
638  shift];
639  for (unsigned int c = 0, m = 0; c < n_components; ++c)
640  {
641  // apply Dirichlet boundary conditions on parent cell
642  for (std::vector<unsigned short>::const_iterator i =
643  dirichlet_indices[from_level - 1][cell + v].begin();
644  i != dirichlet_indices[from_level - 1][cell + v].end();
645  ++i)
646  evaluation_data[*i][v] = 0.;
647 
648  for (unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
649  for (unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
650  for (unsigned int i = 0; i < degree_size; ++i, ++m)
651  dst.local_element(
652  indices[c * n_scalar_cell_dofs +
653  k * n_child_dofs_1d * n_child_dofs_1d +
654  j * n_child_dofs_1d + i]) +=
655  evaluation_data[m][v];
656  }
657  }
658  }
659 }
660 
661 
662 
663 template <int dim, typename Number>
664 std::size_t
666 {
667  std::size_t memory = MGLevelGlobalTransfer<
669  memory += MemoryConsumption::memory_consumption(level_dof_indices);
670  memory += MemoryConsumption::memory_consumption(parent_child_connect);
671  memory += MemoryConsumption::memory_consumption(n_owned_level_cells);
672  memory += MemoryConsumption::memory_consumption(prolongation_matrix_1d);
673  memory += MemoryConsumption::memory_consumption(evaluation_data);
674  memory += MemoryConsumption::memory_consumption(weights_on_refined);
675  memory += MemoryConsumption::memory_consumption(dirichlet_indices);
676  return memory;
677 }
678 
679 
680 
681 template <int dim, typename Number>
683  const MGConstrainedDoFs &mg_c)
684  : same_for_all(true)
685 {
686  matrix_free_transfer_vector.emplace_back(mg_c);
687 }
688 
689 
690 
691 template <int dim, typename Number>
693  const std::vector<MGConstrainedDoFs> &mg_c)
694  : same_for_all(false)
695 {
696  for (const auto &constrained_block_dofs : mg_c)
697  matrix_free_transfer_vector.emplace_back(constrained_block_dofs);
698 }
699 
700 
701 
702 template <int dim, typename Number>
703 void
705  const MGConstrainedDoFs &mg_c)
706 {
707  Assert(same_for_all,
708  ExcMessage("This object was initialized with support for usage with "
709  "one DoFHandler for each block, but this method assumes "
710  "that the same DoFHandler is used for all the blocks!"));
711  AssertDimension(matrix_free_transfer_vector.size(), 1);
712 
713  matrix_free_transfer_vector[0].initialize_constraints(mg_c);
714 }
715 
716 
717 
718 template <int dim, typename Number>
719 void
721  const std::vector<MGConstrainedDoFs> &mg_c)
722 {
723  Assert(!same_for_all,
724  ExcMessage("This object was initialized with support for using "
725  "the same DoFHandler for all the blocks, but this "
726  "method assumes that there is a separate DoFHandler "
727  "for each block!"));
728  AssertDimension(matrix_free_transfer_vector.size(), mg_c.size());
729 
730  for (unsigned int i = 0; i < mg_c.size(); ++i)
731  matrix_free_transfer_vector[i].initialize_constraints(mg_c[i]);
732 }
733 
734 
735 
736 template <int dim, typename Number>
737 void
739 {
740  matrix_free_transfer_vector.clear();
741 }
742 
743 
744 
745 template <int dim, typename Number>
746 void
748  const DoFHandler<dim, dim> &dof_handler)
749 {
750  AssertDimension(matrix_free_transfer_vector.size(), 1);
751  matrix_free_transfer_vector[0].build(dof_handler);
752 }
753 
754 
755 
756 template <int dim, typename Number>
757 void
759  const std::vector<const DoFHandler<dim, dim> *> &dof_handler)
760 {
761  AssertDimension(matrix_free_transfer_vector.size(), dof_handler.size());
762  for (unsigned int i = 0; i < dof_handler.size(); ++i)
763  matrix_free_transfer_vector[i].build(*dof_handler[i]);
764 }
765 
766 
767 
768 template <int dim, typename Number>
769 void
771  const unsigned int to_level,
774 {
775  const unsigned int n_blocks = src.n_blocks();
777 
778  if (!same_for_all)
779  AssertDimension(matrix_free_transfer_vector.size(), n_blocks);
780 
781  for (unsigned int b = 0; b < n_blocks; ++b)
782  {
783  const unsigned int data_block = same_for_all ? 0 : b;
784  matrix_free_transfer_vector[data_block].prolongate(to_level,
785  dst.block(b),
786  src.block(b));
787  }
788 }
789 
790 
791 
792 template <int dim, typename Number>
793 void
795  const unsigned int to_level,
798 {
799  const unsigned int n_blocks = src.n_blocks();
801 
802  if (!same_for_all)
803  AssertDimension(matrix_free_transfer_vector.size(), n_blocks);
804 
805  for (unsigned int b = 0; b < n_blocks; ++b)
806  {
807  const unsigned int data_block = same_for_all ? 0 : b;
808  matrix_free_transfer_vector[data_block].prolongate_and_add(to_level,
809  dst.block(b),
810  src.block(b));
811  }
812 }
813 
814 
815 
816 template <int dim, typename Number>
817 void
819  const unsigned int from_level,
822 {
823  const unsigned int n_blocks = src.n_blocks();
825 
826  if (!same_for_all)
827  AssertDimension(matrix_free_transfer_vector.size(), n_blocks);
828 
829  for (unsigned int b = 0; b < n_blocks; ++b)
830  {
831  const unsigned int data_block = same_for_all ? 0 : b;
832  matrix_free_transfer_vector[data_block].restrict_and_add(from_level,
833  dst.block(b),
834  src.block(b));
835  }
836 }
837 
838 
839 
840 template <int dim, typename Number>
841 std::size_t
843 {
844  std::size_t total_memory_consumption = 0;
845  for (const auto &el : matrix_free_transfer_vector)
846  total_memory_consumption += el.memory_consumption();
847  return total_memory_consumption;
848 }
849 
850 
851 
852 // explicit instantiation
853 #include "mg_transfer_matrix_free.inst"
854 
855 
const Triangulation< dim, spacedim > & get_triangulation() const
SmartPointer< const MGConstrainedDoFs, MGLevelGlobalTransfer< LinearAlgebra::distributed::Vector< Number > > > mg_constrained_dofs
Definition: mg_transfer.h:586
std::vector< MGTransferMatrixFree< dim, Number > > matrix_free_transfer_vector
virtual void prolongate_and_add(const unsigned int to_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< 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
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< Number > &src) const override
std::size_t memory_consumption() const
MGTransferBlockMatrixFree()=default
void build(const DoFHandler< dim, dim > &dof_handler)
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
void do_restrict_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
void do_prolongate_add(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
void build(const DoFHandler< dim, dim > &dof_handler, const std::vector< std::shared_ptr< const Utilities::MPI::Partitioner >> &external_partitioners=std::vector< std::shared_ptr< const Utilities::MPI::Partitioner >>())
virtual void prolongate_and_add(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
std::size_t memory_consumption() const
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
virtual unsigned int n_global_levels() const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:396
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:397
Point< 2 > second
Definition: grid_out.cc:4588
Point< 2 > first
Definition: grid_out.cc:4587
unsigned int level
Definition: grid_out.cc:4590
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
unsigned int n_blocks() const
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcNotImplemented()
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1622
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
BlockType & block(const unsigned int i)
static ::ExceptionBase & ExcMessage(std::string arg1)
Number local_element(const size_type local_index) const
size_type locally_owned_size() const
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
virtual void compress(::VectorOperation::values operation) override
void reinit(const size_type size, const bool omit_zeroing_entries=false)
void shift(const Tensor< 1, spacedim > &shift_vector, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2022
std::enable_if< IsBlockVector< VectorType >::value, unsigned int >::type n_blocks(const VectorType &vector)
Definition: operators.h:49
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorType::value_type * begin(VectorType &V)
constexpr T pow(const T base, const int iexp)
Definition: utilities.h:461
T fixed_power(const T t)
Definition: utilities.h:1081
std::vector< Number > prolongation_matrix_1d