Reference documentation for deal.II version 9.3.3
\(\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
20
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
42template <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
52template <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
65template <int dim, typename Number>
66void
68 const MGConstrainedDoFs &mg_c)
69{
70 this->mg_constrained_dofs = &mg_c;
71}
72
73
74
75template <int dim, typename Number>
76void
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
95template <int dim, typename Number>
96void
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
181template <int dim, typename Number>
182void
184 const unsigned int to_level,
187{
188 dst = 0;
189 prolongate_and_add(to_level, dst, src);
190}
191
192
193
194template <int dim, typename Number>
195void
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)
269}
270
271
272
273template <int dim, typename Number>
274void
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)
347}
348
349
350
351namespace
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
386template <int dim, typename Number>
387template <int degree>
388void
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.
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
531template <int dim, typename Number>
532template <int degree>
533void
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
663template <int dim, typename Number>
664std::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
681template <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
691template <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
702template <int dim, typename Number>
703void
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
718template <int dim, typename Number>
719void
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
736template <int dim, typename Number>
737void
739{
740 matrix_free_transfer_vector.clear();
741}
742
743
744
745template <int dim, typename Number>
746void
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
756template <int dim, typename Number>
757void
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
768template <int dim, typename Number>
769void
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
792template <int dim, typename Number>
793void
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
816template <int dim, typename Number>
817void
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
840template <int dim, typename Number>
841std::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:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
Point< 2 > second
Definition: grid_out.cc:4588
Point< 2 > first
Definition: grid_out.cc:4587
unsigned int level
Definition: grid_out.cc:4590
unsigned int n_blocks() const
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
#define Assert(cond, exc)
Definition: exceptions.h:1465
#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
virtual void compress(::VectorOperation::values operation) override
const std::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
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, unsignedint >::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