Reference documentation for deal.II version 9.5.0
\(\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\}}\)
Loading...
Searching...
No Matches
mg_transfer_matrix_free.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2016 - 2023 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
33
36#include <deal.II/multigrid/mg_transfer_matrix_free.templates.h>
37
38#include <algorithm>
39
41
42
43template <int dim, typename Number>
45 : fe_degree(0)
46 , element_is_continuous(false)
47 , n_components(0)
48 , n_child_cell_dofs(0)
49{}
50
51
52
53template <int dim, typename Number>
55 const MGConstrainedDoFs &mg_c)
56 : fe_degree(0)
57 , element_is_continuous(false)
58 , n_components(0)
59 , n_child_cell_dofs(0)
60{
61 this->mg_constrained_dofs = &mg_c;
62}
63
64
65
66template <int dim, typename Number>
67void
69 const MGConstrainedDoFs &mg_c)
70{
71 this->mg_constrained_dofs = &mg_c;
72}
73
74
75
76template <int dim, typename Number>
77void
79{
82 fe_degree = 0;
83 element_is_continuous = false;
84 n_components = 0;
85 n_child_cell_dofs = 0;
86 level_dof_indices.clear();
87 parent_child_connect.clear();
88 dirichlet_indices.clear();
89 n_owned_level_cells.clear();
90 prolongation_matrix_1d.clear();
91 evaluation_data.clear();
92 weights_on_refined.clear();
93}
94
95
96
97template <int dim, typename Number>
98void
100 const DoFHandler<dim, dim> &dof_handler,
101 const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
102 &external_partitioners)
103{
104 Assert(dof_handler.has_level_dofs(),
106 "The underlying DoFHandler object has not had its "
107 "distribute_mg_dofs() function called, but this is a prerequisite "
108 "for multigrid transfers. You will need to call this function, "
109 "probably close to where you already call distribute_dofs()."));
110 if (external_partitioners.size() > 0)
111 {
112 Assert(this->initialize_dof_vector == nullptr,
113 ExcMessage("An initialize_dof_vector function has already "
114 "been registered in the constructor!"));
115
116 this->initialize_dof_vector =
117 [external_partitioners](
118 const unsigned int level,
120 vec.reinit(external_partitioners[level]);
121 };
122 }
123
124 this->fill_and_communicate_copy_indices(dof_handler);
125
126 vector_partitioners.resize(0,
127 dof_handler.get_triangulation().n_global_levels() -
128 1);
129 for (unsigned int level = 0; level <= this->ghosted_level_vector.max_level();
130 ++level)
131 vector_partitioners[level] =
132 this->ghosted_level_vector[level].get_partitioner();
133
134 std::vector<std::vector<Number>> weights_unvectorized;
135
137
138 internal::MGTransfer::setup_transfer<dim, Number>(
139 dof_handler,
140 this->mg_constrained_dofs,
141 external_partitioners,
142 elem_info,
143 level_dof_indices,
144 parent_child_connect,
145 n_owned_level_cells,
146 dirichlet_indices,
147 weights_unvectorized,
148 this->copy_indices_global_mine,
149 vector_partitioners);
150
151 // reinit the ghosted level vector in case its partitioner differs from the
152 // one the user intends to use externally
153 this->ghosted_level_vector.resize(0, vector_partitioners.max_level());
154 for (unsigned int level = 0; level <= vector_partitioners.max_level();
155 ++level)
156 if (external_partitioners.size() == vector_partitioners.max_level() + 1 &&
157 external_partitioners[level].get() == vector_partitioners[level].get())
158 this->ghosted_level_vector[level].reinit(0);
159 else
160 this->ghosted_level_vector[level].reinit(vector_partitioners[level]);
161
162 // unpack element info data
163 fe_degree = elem_info.fe_degree;
164 element_is_continuous = elem_info.element_is_continuous;
165 n_components = elem_info.n_components;
166 n_child_cell_dofs = elem_info.n_child_cell_dofs;
167
168 // duplicate and put into vectorized array
169 prolongation_matrix_1d.resize(elem_info.prolongation_matrix_1d.size());
170 for (unsigned int i = 0; i < elem_info.prolongation_matrix_1d.size(); ++i)
171 prolongation_matrix_1d[i] = elem_info.prolongation_matrix_1d[i];
172
173 // reshuffle into aligned vector of vectorized arrays
174 const unsigned int vec_size = VectorizedArray<Number>::size();
175 const unsigned int n_levels =
176 dof_handler.get_triangulation().n_global_levels();
177
178 const unsigned int n_weights_per_cell = Utilities::fixed_power<dim>(3);
179 weights_on_refined.resize(n_levels - 1);
180 for (unsigned int level = 1; level < n_levels; ++level)
181 {
182 weights_on_refined[level - 1].resize(
183 ((n_owned_level_cells[level - 1] + vec_size - 1) / vec_size) *
184 n_weights_per_cell);
185
186 for (unsigned int c = 0; c < n_owned_level_cells[level - 1]; ++c)
187 {
188 const unsigned int comp = c / vec_size;
189 const unsigned int v = c % vec_size;
190 for (unsigned int i = 0; i < n_weights_per_cell; ++i)
191 {
192 weights_on_refined[level - 1][comp * n_weights_per_cell + i][v] =
193 weights_unvectorized[level - 1][c * n_weights_per_cell + i];
194 }
195 }
196 }
197
198 evaluation_data.resize(n_child_cell_dofs);
199}
200
201
202
203template <int dim, typename Number>
204void
206 const DoFHandler<dim, dim> &dof_handler,
207 const std::function<void(const unsigned int,
209 &initialize_dof_vector)
210{
211 if (initialize_dof_vector)
212 {
213 const unsigned int n_levels =
214 dof_handler.get_triangulation().n_global_levels();
215
216 std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
217 external_partitioners(n_levels);
218
219 for (unsigned int level = 0; level < n_levels; ++level)
220 {
222 initialize_dof_vector(level, vector);
223 external_partitioners[level] = vector.get_partitioner();
224 }
225
226 build(dof_handler, external_partitioners);
227 }
228 else
229 {
230 build(dof_handler);
231 }
232}
233
234
235
236template <int dim, typename Number>
237void
239 const unsigned int to_level,
242{
243 dst = 0;
244 prolongate_and_add(to_level, dst, src);
245}
246
247
248
249template <int dim, typename Number>
250void
252 const unsigned int to_level,
255{
256 Assert((to_level >= 1) && (to_level <= level_dof_indices.size()),
257 ExcIndexRange(to_level, 1, level_dof_indices.size() + 1));
258
259 const bool src_inplace = src.get_partitioner().get() ==
260 this->vector_partitioners[to_level - 1].get();
261 if (src_inplace == false)
262 {
263 if (this->ghosted_level_vector[to_level - 1].get_partitioner().get() !=
264 this->vector_partitioners[to_level - 1].get())
265 this->ghosted_level_vector[to_level - 1].reinit(
266 this->vector_partitioners[to_level - 1]);
267 this->ghosted_level_vector[to_level - 1].copy_locally_owned_data_from(
268 src);
269 }
270
271 const bool dst_inplace =
272 dst.get_partitioner().get() == this->vector_partitioners[to_level].get();
273 if (dst_inplace == false)
274 {
275 if (this->ghosted_level_vector[to_level].get_partitioner().get() !=
276 this->vector_partitioners[to_level].get())
277 this->ghosted_level_vector[to_level].reinit(
278 this->vector_partitioners[to_level]);
279 AssertDimension(this->ghosted_level_vector[to_level].locally_owned_size(),
280 dst.locally_owned_size());
281 this->ghosted_level_vector[to_level] = 0.;
282 }
283
285 src_inplace ? src : this->ghosted_level_vector[to_level - 1];
287 dst_inplace ? dst : this->ghosted_level_vector[to_level];
288
289 src_vec.update_ghost_values();
290 // the implementation in do_prolongate_add is templated in the degree of the
291 // element (for efficiency reasons), so we need to find the appropriate
292 // kernel here...
293 if (fe_degree == 0)
294 do_prolongate_add<0>(to_level, dst_vec, src_vec);
295 else if (fe_degree == 1)
296 do_prolongate_add<1>(to_level, dst_vec, src_vec);
297 else if (fe_degree == 2)
298 do_prolongate_add<2>(to_level, dst_vec, src_vec);
299 else if (fe_degree == 3)
300 do_prolongate_add<3>(to_level, dst_vec, src_vec);
301 else if (fe_degree == 4)
302 do_prolongate_add<4>(to_level, dst_vec, src_vec);
303 else if (fe_degree == 5)
304 do_prolongate_add<5>(to_level, dst_vec, src_vec);
305 else if (fe_degree == 6)
306 do_prolongate_add<6>(to_level, dst_vec, src_vec);
307 else if (fe_degree == 7)
308 do_prolongate_add<7>(to_level, dst_vec, src_vec);
309 else if (fe_degree == 8)
310 do_prolongate_add<8>(to_level, dst_vec, src_vec);
311 else if (fe_degree == 9)
312 do_prolongate_add<9>(to_level, dst_vec, src_vec);
313 else if (fe_degree == 10)
314 do_prolongate_add<10>(to_level, dst_vec, src_vec);
315 else
316 do_prolongate_add<-1>(to_level, dst_vec, src_vec);
317
319 if (dst_inplace == false)
320 dst += dst_vec;
321
322 if (src_inplace == true)
324}
325
326
327
328template <int dim, typename Number>
329void
331 const unsigned int from_level,
334{
335 Assert((from_level >= 1) && (from_level <= level_dof_indices.size()),
336 ExcIndexRange(from_level, 1, level_dof_indices.size() + 1));
337
338 const bool src_inplace =
339 src.get_partitioner().get() == this->vector_partitioners[from_level].get();
340 if (src_inplace == false)
341 {
342 if (this->ghosted_level_vector[from_level].get_partitioner().get() !=
343 this->vector_partitioners[from_level].get())
344 this->ghosted_level_vector[from_level].reinit(
345 this->vector_partitioners[from_level]);
346 this->ghosted_level_vector[from_level].copy_locally_owned_data_from(src);
347 }
348
349 const bool dst_inplace = dst.get_partitioner().get() ==
350 this->vector_partitioners[from_level - 1].get();
351 if (dst_inplace == false)
352 {
353 if (this->ghosted_level_vector[from_level - 1].get_partitioner().get() !=
354 this->vector_partitioners[from_level - 1].get())
355 this->ghosted_level_vector[from_level - 1].reinit(
356 this->vector_partitioners[from_level - 1]);
358 this->ghosted_level_vector[from_level - 1].locally_owned_size(),
359 dst.locally_owned_size());
360 this->ghosted_level_vector[from_level - 1] = 0.;
361 }
362
364 src_inplace ? src : this->ghosted_level_vector[from_level];
366 dst_inplace ? dst : this->ghosted_level_vector[from_level - 1];
367
368 src_vec.update_ghost_values();
369
370 if (fe_degree == 0)
371 do_restrict_add<0>(from_level, dst_vec, src_vec);
372 else if (fe_degree == 1)
373 do_restrict_add<1>(from_level, dst_vec, src_vec);
374 else if (fe_degree == 2)
375 do_restrict_add<2>(from_level, dst_vec, src_vec);
376 else if (fe_degree == 3)
377 do_restrict_add<3>(from_level, dst_vec, src_vec);
378 else if (fe_degree == 4)
379 do_restrict_add<4>(from_level, dst_vec, src_vec);
380 else if (fe_degree == 5)
381 do_restrict_add<5>(from_level, dst_vec, src_vec);
382 else if (fe_degree == 6)
383 do_restrict_add<6>(from_level, dst_vec, src_vec);
384 else if (fe_degree == 7)
385 do_restrict_add<7>(from_level, dst_vec, src_vec);
386 else if (fe_degree == 8)
387 do_restrict_add<8>(from_level, dst_vec, src_vec);
388 else if (fe_degree == 9)
389 do_restrict_add<9>(from_level, dst_vec, src_vec);
390 else if (fe_degree == 10)
391 do_restrict_add<10>(from_level, dst_vec, src_vec);
392 else
393 // go to the non-templated version of the evaluator
394 do_restrict_add<-1>(from_level, dst_vec, src_vec);
395
397 if (dst_inplace == false)
398 dst += dst_vec;
399
400 if (src_inplace == true)
402}
403
404
405
406template <int dim, typename Number>
407template <int degree>
408void
410 const unsigned int to_level,
413{
414 const unsigned int vec_size = VectorizedArray<Number>::size();
415 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
416 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
417 const unsigned int n_scalar_cell_dofs =
418 Utilities::fixed_power<dim>(n_child_dofs_1d);
419 constexpr unsigned int three_to_dim = Utilities::pow(3, dim);
420
421 // If we have user defined MG constraints, we must create
422 // a non-const, ghosted version of the source vector to distribute
423 // constraints.
426 if (this->mg_constrained_dofs != nullptr &&
427 this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
428 .get_local_lines()
429 .size() > 0)
430 {
432
433 // Distribute any user defined constraints
434 this->mg_constrained_dofs->get_user_constraint_matrix(to_level - 1)
435 .distribute(copy_src);
436
437 // Re-initialize new ghosted vector with correct constraints
438 new_src.reinit(copy_src);
439 new_src = copy_src;
440 new_src.update_ghost_values();
441
442 to_use = &new_src;
443 }
444
445 for (unsigned int cell = 0; cell < n_owned_level_cells[to_level - 1];
446 cell += vec_size)
447 {
448 const unsigned int n_lanes =
449 (cell + vec_size > n_owned_level_cells[to_level - 1]) ?
450 (n_owned_level_cells[to_level - 1] - cell) :
451 vec_size;
452
453 // read from source vector
454 for (unsigned int v = 0; v < n_lanes; ++v)
455 {
456 const unsigned int shift =
457 internal::MGTransfer::compute_shift_within_children<dim>(
458 parent_child_connect[to_level - 1][cell + v].second,
459 fe_degree + 1 - element_is_continuous,
460 fe_degree);
461 const unsigned int *indices =
462 &level_dof_indices[to_level - 1]
463 [parent_child_connect[to_level - 1][cell + v]
464 .first *
465 n_child_cell_dofs +
466 shift];
467 for (unsigned int c = 0, m = 0; c < n_components; ++c)
468 {
469 for (unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
470 for (unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
471 for (unsigned int i = 0; i < degree_size; ++i, ++m)
472 evaluation_data[m][v] = to_use->local_element(
473 indices[c * n_scalar_cell_dofs +
474 k * n_child_dofs_1d * n_child_dofs_1d +
475 j * n_child_dofs_1d + i]);
476
477 // apply Dirichlet boundary conditions on parent cell
478 for (std::vector<unsigned short>::const_iterator i =
479 dirichlet_indices[to_level - 1][cell + v].begin();
480 i != dirichlet_indices[to_level - 1][cell + v].end();
481 ++i)
482 evaluation_data[*i][v] = 0.;
483 }
484 }
485
486 AssertDimension(prolongation_matrix_1d.size(),
487 degree_size * n_child_dofs_1d);
488 // perform tensorized operation
489 if (element_is_continuous)
490 {
491 // must go through the components backwards because we want to write
492 // the output to the same array as the input
493 for (int c = n_components - 1; c >= 0; --c)
497 dim,
498 degree + 1,
499 2 * degree + 1>::do_forward(1,
500 prolongation_matrix_1d,
501 evaluation_data.begin() +
502 c * Utilities::fixed_power<dim>(
503 degree_size),
504 evaluation_data.begin() +
505 c * n_scalar_cell_dofs,
506 fe_degree + 1,
507 2 * fe_degree + 1);
509 degree != -1 ? 2 * degree + 1 :
510 -1,
512 &weights_on_refined[to_level - 1][(cell / vec_size) * three_to_dim],
513 n_components,
514 2 * fe_degree + 1,
515 evaluation_data.begin());
516 }
517 else
518 {
519 for (int c = n_components - 1; c >= 0; --c)
523 dim,
524 degree + 1,
525 2 * degree + 2>::do_forward(1,
526 prolongation_matrix_1d,
527 evaluation_data.begin() +
528 c * Utilities::fixed_power<dim>(
529 degree_size),
530 evaluation_data.begin() +
531 c * n_scalar_cell_dofs,
532 fe_degree + 1,
533 2 * fe_degree + 2);
534 }
535
536 // write into dst vector
537 const unsigned int *indices =
538 &level_dof_indices[to_level][cell * n_child_cell_dofs];
539 for (unsigned int v = 0; v < n_lanes; ++v)
540 {
541 for (unsigned int i = 0; i < n_child_cell_dofs; ++i)
542 dst.local_element(indices[i]) += evaluation_data[i][v];
543 indices += n_child_cell_dofs;
544 }
545 }
546}
547
548
549
550template <int dim, typename Number>
551template <int degree>
552void
554 const unsigned int from_level,
557{
558 const unsigned int vec_size = VectorizedArray<Number>::size();
559 const unsigned int degree_size = (degree > -1 ? degree : fe_degree) + 1;
560 const unsigned int n_child_dofs_1d = 2 * degree_size - element_is_continuous;
561 const unsigned int n_scalar_cell_dofs =
562 Utilities::fixed_power<dim>(n_child_dofs_1d);
563 constexpr unsigned int three_to_dim = Utilities::pow(3, dim);
564
565 for (unsigned int cell = 0; cell < n_owned_level_cells[from_level - 1];
566 cell += vec_size)
567 {
568 const unsigned int n_lanes =
569 (cell + vec_size > n_owned_level_cells[from_level - 1]) ?
570 (n_owned_level_cells[from_level - 1] - cell) :
571 vec_size;
572
573 // read from source vector
574 {
575 const unsigned int *indices =
576 &level_dof_indices[from_level][cell * n_child_cell_dofs];
577 for (unsigned int v = 0; v < n_lanes; ++v)
578 {
579 for (unsigned int i = 0; i < n_child_cell_dofs; ++i)
580 evaluation_data[i][v] = src.local_element(indices[i]);
581 indices += n_child_cell_dofs;
582 }
583 }
584
585 AssertDimension(prolongation_matrix_1d.size(),
586 degree_size * n_child_dofs_1d);
587 // perform tensorized operation
588 if (element_is_continuous)
589 {
591 degree != -1 ? 2 * degree + 1 :
592 -1,
594 &weights_on_refined[from_level - 1]
595 [(cell / vec_size) * three_to_dim],
596 n_components,
597 2 * fe_degree + 1,
598 evaluation_data.data());
599 for (unsigned int c = 0; c < n_components; ++c)
603 dim,
604 degree + 1,
605 2 * degree + 1>::do_backward(1,
606 prolongation_matrix_1d,
607 false,
608 evaluation_data.begin() +
609 c * n_scalar_cell_dofs,
610 evaluation_data.begin() +
611 c * Utilities::fixed_power<dim>(
612 degree_size),
613 fe_degree + 1,
614 2 * fe_degree + 1);
615 }
616 else
617 {
618 for (unsigned int c = 0; c < n_components; ++c)
622 dim,
623 degree + 1,
624 2 * degree + 2>::do_backward(1,
625 prolongation_matrix_1d,
626 false,
627 evaluation_data.begin() +
628 c * n_scalar_cell_dofs,
629 evaluation_data.begin() +
630 c * Utilities::fixed_power<dim>(
631 degree_size),
632 fe_degree + 1,
633 2 * fe_degree + 2);
634 }
635
636 // write into dst vector
637 for (unsigned int v = 0; v < n_lanes; ++v)
638 {
639 const unsigned int shift =
640 internal::MGTransfer::compute_shift_within_children<dim>(
641 parent_child_connect[from_level - 1][cell + v].second,
642 fe_degree + 1 - element_is_continuous,
643 fe_degree);
645 parent_child_connect[from_level - 1][cell + v].first *
646 n_child_cell_dofs +
647 n_child_cell_dofs - 1,
648 level_dof_indices[from_level - 1].size());
649 const unsigned int *indices =
650 &level_dof_indices[from_level - 1]
651 [parent_child_connect[from_level - 1][cell + v]
652 .first *
653 n_child_cell_dofs +
654 shift];
655 for (unsigned int c = 0, m = 0; c < n_components; ++c)
656 {
657 // apply Dirichlet boundary conditions on parent cell
658 for (std::vector<unsigned short>::const_iterator i =
659 dirichlet_indices[from_level - 1][cell + v].begin();
660 i != dirichlet_indices[from_level - 1][cell + v].end();
661 ++i)
662 evaluation_data[*i][v] = 0.;
663
664 for (unsigned int k = 0; k < (dim > 2 ? degree_size : 1); ++k)
665 for (unsigned int j = 0; j < (dim > 1 ? degree_size : 1); ++j)
666 for (unsigned int i = 0; i < degree_size; ++i, ++m)
667 dst.local_element(
668 indices[c * n_scalar_cell_dofs +
669 k * n_child_dofs_1d * n_child_dofs_1d +
670 j * n_child_dofs_1d + i]) +=
671 evaluation_data[m][v];
672 }
673 }
674 }
675}
676
677
678
679template <int dim, typename Number>
680std::size_t
682{
683 std::size_t memory = MGLevelGlobalTransfer<
684 LinearAlgebra::distributed::Vector<Number>>::memory_consumption();
685 memory += MemoryConsumption::memory_consumption(level_dof_indices);
686 memory += MemoryConsumption::memory_consumption(parent_child_connect);
687 memory += MemoryConsumption::memory_consumption(n_owned_level_cells);
688 memory += MemoryConsumption::memory_consumption(prolongation_matrix_1d);
689 memory += MemoryConsumption::memory_consumption(evaluation_data);
690 memory += MemoryConsumption::memory_consumption(weights_on_refined);
691 memory += MemoryConsumption::memory_consumption(dirichlet_indices);
692 return memory;
693}
694
695
696
697template <int dim, typename Number>
699 const MGConstrainedDoFs &mg_c)
701 Number,
702 MGTransferMatrixFree<dim, Number>>(true)
703{
704 this->matrix_free_transfer_vector.emplace_back(mg_c);
705}
706
707
708
709template <int dim, typename Number>
711 const std::vector<MGConstrainedDoFs> &mg_c)
713 Number,
714 MGTransferMatrixFree<dim, Number>>(false)
715{
716 for (const auto &constrained_block_dofs : mg_c)
717 this->matrix_free_transfer_vector.emplace_back(constrained_block_dofs);
718}
719
720
721
722template <int dim, typename Number>
723void
725 const MGConstrainedDoFs &mg_c)
726{
727 Assert(this->same_for_all,
728 ExcMessage("This object was initialized with support for usage with "
729 "one DoFHandler for each block, but this method assumes "
730 "that the same DoFHandler is used for all the blocks!"));
731 AssertDimension(this->matrix_free_transfer_vector.size(), 1);
732
733 this->matrix_free_transfer_vector[0].initialize_constraints(mg_c);
734}
735
736
737
738template <int dim, typename Number>
739void
741 const std::vector<MGConstrainedDoFs> &mg_c)
742{
743 Assert(!this->same_for_all,
744 ExcMessage("This object was initialized with support for using "
745 "the same DoFHandler for all the blocks, but this "
746 "method assumes that there is a separate DoFHandler "
747 "for each block!"));
748 AssertDimension(this->matrix_free_transfer_vector.size(), mg_c.size());
749
750 for (unsigned int i = 0; i < mg_c.size(); ++i)
751 this->matrix_free_transfer_vector[i].initialize_constraints(mg_c[i]);
752}
753
754
755
756template <int dim, typename Number>
757void
759 const DoFHandler<dim, dim> &dof_handler)
760{
761 AssertDimension(this->matrix_free_transfer_vector.size(), 1);
762 this->matrix_free_transfer_vector[0].build(dof_handler);
763}
764
765
766
767template <int dim, typename Number>
768void
770 const std::vector<const DoFHandler<dim, dim> *> &dof_handler)
771{
772 AssertDimension(this->matrix_free_transfer_vector.size(), dof_handler.size());
773 for (unsigned int i = 0; i < dof_handler.size(); ++i)
774 this->matrix_free_transfer_vector[i].build(*dof_handler[i]);
775}
776
777
778
779template <int dim, typename Number>
780std::size_t
782{
783 std::size_t total_memory_consumption = 0;
784 for (const auto &el : this->matrix_free_transfer_vector)
785 total_memory_consumption += el.memory_consumption();
786 return total_memory_consumption;
787}
788
789
790
791template <int dim, typename Number>
794 const unsigned int b) const
795{
796 return matrix_free_transfer_vector[b];
797}
798
799
800
801template <int dim, typename Number>
802void
804{
805 this->matrix_free_transfer_vector.clear();
806}
807
808
809
810// explicit instantiation
811#include "mg_transfer_matrix_free.inst"
812
813
const Triangulation< dim, spacedim > & get_triangulation() const
bool has_level_dofs() const
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)
SmartPointer< const MGConstrainedDoFs, MGLevelGlobalTransfer< LinearAlgebra::distributed::Vector< Number > > > mg_constrained_dofs
std::vector< MGTransferMatrixFree< dim, Number > > matrix_free_transfer_vector
MGTransferBlockMatrixFree()=default
const MGTransferMatrixFree< dim, Number > & get_matrix_free_transfer(const unsigned int b) const override
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:472
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:473
Point< 2 > second
Definition grid_out.cc:4616
Point< 2 > first
Definition grid_out.cc:4615
unsigned int level
Definition grid_out.cc:4618
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::enable_if_t< std::is_fundamental< T >::value, std::size_t > memory_consumption(const T &t)
constexpr T pow(const T base, const int iexp)
Definition utilities.h:447
void weight_fe_q_dofs_by_entity(const Number *weights, const unsigned int n_components, const int n_points_1d_non_template, Number *data)