ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
parabolic_module_gmg_operators.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2023 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
10#include <loop.h>
11#include <observer_pointer.h>
12#include <offline_data.h>
13#include <simd.h>
14
15#include "../euler/hyperbolic_system.h"
16#include "parabolic_system.h"
17
18#include <deal.II/base/vectorization.h>
19#include <deal.II/lac/diagonal_matrix.h>
20#include <deal.II/matrix_free/fe_evaluation.h>
21#include <deal.II/matrix_free/tools.h>
22#include <deal.II/multigrid/mg_base.h>
23#include <deal.II/multigrid/mg_transfer_matrix_free.h>
24
25/*
26 * FIXME: generalize and make these operators equation independent and
27 * refactor into ../parabolic_module_gmg_operators.h
28 */
29
30namespace ryujin
31{
32 namespace NavierStokes
33 {
35
44 template <int dim, typename Number>
46 {
47 public:
51 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
52
57 dealii::LinearAlgebra::distributed::BlockVector<Number>;
58
62 DiagonalMatrix() = default;
63
68 template <typename Vector>
69 void reinit(const Vector &lumped_mass_matrix,
70 const vector_type &density,
71 const dealii::AffineConstraints<Number> &affine_constraints)
72 {
73 diagonal.reinit(density, true);
74
75 const auto n_owned = density.get_partitioner()->locally_owned_size();
76
77 const auto body_invert = [&](auto sentinel, const unsigned int i) {
78 using T = decltype(sentinel);
79
80 T m_i;
81 if constexpr (std::is_same_v<Vector, vector_type>) {
82 m_i = read_entry<T>(lumped_mass_matrix, i);
83 } else {
84 m_i = lumped_mass_matrix.template read_entry<T>(i);
85 }
86
87 const auto rho_i = read_entry<T>(density, i);
88 write_entry<T>(diagonal, Number(1.0) / (rho_i * m_i), i);
89 };
90
91 cpu_simd_loop<Number>("", body_invert, 0, n_owned, n_owned);
92
93 /*
94 * Fix up diagonal entries for constrained degrees of freedom due to
95 * periodic boundary conditions.
96 */
97 affine_constraints.set_zero(diagonal);
98 }
99
104 {
105 return diagonal;
106 }
107
112 {
113 return diagonal_block;
114 }
115
119 void vmult(vector_type &dst, const vector_type &src) const
120 {
121 AssertDimension(diagonal_block.size(), 0);
122 DEAL_II_OPENMP_SIMD_PRAGMA
123 for (unsigned int i = 0;
124 i < diagonal.get_partitioner()->locally_owned_size();
125 ++i)
126 dst.local_element(i) =
127 diagonal.local_element(i) * src.local_element(i);
128 }
129
133 void vmult(block_vector_type &dst, const block_vector_type &src) const
134 {
135 AssertDimension(dim, dst.n_blocks());
136 AssertDimension(dim, src.n_blocks());
137 if (diagonal_block.size() == 0) {
138 DEAL_II_OPENMP_SIMD_PRAGMA
139 for (unsigned int i = 0;
140 i < diagonal.get_partitioner()->locally_owned_size();
141 ++i)
142 for (unsigned int d = 0; d < dim; ++d)
143 dst.block(d).local_element(i) =
144 diagonal.local_element(i) * src.block(d).local_element(i);
145 } else
146 for (unsigned int d = 0; d < dim; ++d) {
147 DEAL_II_OPENMP_SIMD_PRAGMA
148 for (unsigned int i = 0;
149 i < src.block(d).get_partitioner()->locally_owned_size();
150 ++i)
151 dst.block(d).local_element(i) =
152 diagonal_block.block(d).local_element(i) *
153 src.block(d).local_element(i);
154 }
155 }
156
157 private:
158 vector_type diagonal;
159 block_vector_type diagonal_block;
160 };
161
162
169 template <int dim, typename Number, typename Number2>
170 class VelocityMatrix : public dealii::EnableObserverPointer
171 {
172 public:
173 // FIXME: refactor
174 static constexpr unsigned int order_fe = 1;
175 static constexpr unsigned int order_quad = 2;
176
177 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
179 dealii::LinearAlgebra::distributed::BlockVector<Number>;
180
181 VelocityMatrix() = default;
182
184 const ParabolicSystem &parabolic_system,
185 const OfflineData<dim, Number2> &offline_data,
186 const dealii::MatrixFree<dim, Number> &matrix_free,
187 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
188 const Number theta_x_tau,
189 const unsigned int level = dealii::numbers::invalid_unsigned_int)
190 {
191 parabolic_system_ = &parabolic_system;
192 offline_data_ = &offline_data;
193 matrix_free_ = &matrix_free;
194 density_ = &density;
195 theta_x_tau_ = theta_x_tau;
196 level_ = level;
197 }
198
199 void Tvmult(block_vector_type &dst, const block_vector_type &src) const
200 {
201 vmult(dst, src);
202 }
203
204 void vmult(block_vector_type &dst, const block_vector_type &src) const
205 {
206 /* Apply action of m_i rho_i V_i: */
207
208 /* FIXME: we should really clean up this mess: */
209 const auto get_lumped_mass = [&](auto sentinel, unsigned int i) {
210 using T = decltype(sentinel);
211 if constexpr (std::is_same_v<Number, Number2>) {
212 if constexpr (std::is_same_v<Number, float>) {
213 if (level_ == dealii::numbers::invalid_unsigned_int) {
214 const auto lumped = offline_data_->lumped_mass_matrix().view();
215 return lumped.template read_entry<T>(i);
216 } else {
217 const auto &level_lumped =
218 offline_data_->level_lumped_mass_matrix()[level_];
219 return read_entry<T>(level_lumped, i);
220 }
221 } else {
222 Assert(level_ == dealii::numbers::invalid_unsigned_int,
223 dealii::ExcInternalError());
224 const auto lumped = offline_data_->lumped_mass_matrix().view();
225 return lumped.template read_entry<T>(i);
226 }
227 } else {
228 const auto &level_lumped =
229 offline_data_->level_lumped_mass_matrix()[level_];
230 return read_entry<T>(level_lumped, i);
231 }
232 };
233
234 const unsigned int n_owned =
235 dst.block(0).get_partitioner()->locally_owned_size();
236
237 const auto body_mass = [&](auto sentinel, unsigned int i) {
238 using T = decltype(sentinel);
239
240 const auto m_i = get_lumped_mass(T(), i);
241
242 const auto rho_i = read_entry<T>(*density_, i);
243 for (unsigned int d = 0; d < dim; ++d) {
244 const auto temp = read_entry<T>(src.block(d), i);
245 write_entry<T>(dst.block(d), m_i * rho_i * temp, i);
246 }
247 };
248
249 cpu_simd_loop<Number>("", body_mass, 0, n_owned, n_owned);
250
251 /* Apply action of stress tensor: + theta * \sum_j B_ij V_j: */
252
253 const auto integrator = [this](const auto &data,
254 auto &dst,
255 const auto &src,
256 const auto range) {
257 dealii::FEEvaluation<dim, order_fe, order_quad, dim, Number> velocity(
258 data);
259
260 for (unsigned int cell = range.first; cell < range.second; ++cell) {
261 velocity.reinit(cell);
262 velocity.read_dof_values(src);
263 apply_local_operator(velocity);
264 velocity.distribute_local_to_global(dst);
265 }
266 };
267
268 matrix_free_->template cell_loop<block_vector_type, block_vector_type>(
269 integrator, dst, src, /* zero destination */ false);
270
271 /* (5.4a) Fix up constrained degrees of freedom: */
272
273 const auto &boundary_map =
274 level_ == dealii::numbers::invalid_unsigned_int
275 ? offline_data_->boundary_map()
276 : offline_data_->level_boundary_map()[level_];
277
278 for (auto entry : boundary_map) {
279 // [i, normal, normal_mass, boundary_mass, id, position] = entry
280 const auto i = std::get<0>(entry);
281 if (i >= n_owned)
282 continue;
283
284 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
285 const auto id = std::get<4>(entry);
286
287 if (id == Boundary::slip) {
288 dealii::Tensor<1, dim, Number> V_i;
289 for (unsigned int d = 0; d < dim; ++d)
290 V_i[d] = dst.block(d).local_element(i);
291
292 /* replace normal component by source */
293 V_i -= 1. * (V_i * normal) * normal;
294 for (unsigned int d = 0; d < dim; ++d) {
295 const auto src_d = src.block(d).local_element(i);
296 V_i += 1. * (src_d * normal[d]) * normal;
297 }
298
299 for (unsigned int d = 0; d < dim; ++d)
300 dst.block(d).local_element(i) = V_i[d];
301
302 } else if (id == Boundary::no_slip || id == Boundary::dirichlet) {
303
304 /* set dst to src vector: */
305 for (unsigned int d = 0; d < dim; ++d)
306 dst.block(d).local_element(i) = src.block(d).local_element(i);
307 }
308 }
309 }
310
312 std::shared_ptr<DiagonalMatrix<dim, Number>> &matrix) const
313 {
314 Assert(level_ != dealii::numbers::invalid_unsigned_int,
315 dealii::ExcNotImplemented());
316 matrix = std::make_shared<DiagonalMatrix<dim, Number>>();
317 block_vector_type &vector = matrix->get_block_vector();
318 vector.reinit(dim);
319 for (unsigned int d = 0; d < dim; ++d)
320 matrix_free_->initialize_dof_vector(vector.block(d));
321 vector.collect_sizes();
322
323 dealii::MatrixFreeTools::compute_diagonal(
324 *matrix_free_,
325 vector,
326 &VelocityMatrix::template apply_local_operator<
327 dealii::FEEvaluation<dim, -1, 0, dim, Number>>,
328 this);
329
330 const auto &lumped_mass_matrix =
331 offline_data_->level_lumped_mass_matrix()[level_];
332 const unsigned int n_owned =
333 lumped_mass_matrix.get_partitioner()->locally_owned_size();
334
335 const auto body_invert = [&](auto sentinel, const unsigned int i) {
336 using T = decltype(sentinel);
337 const auto m_i = lumped_mass_matrix.local_element(i);
338 const auto rho_i = density_->local_element(i);
339 for (unsigned int d = 0; d < dim; ++d)
340 write_entry(vector.block(d),
341 Number(1.) /
342 (m_i * rho_i + read_entry<T>(vector.block(d), i)),
343 i);
344 };
345
346 cpu_simd_loop<Number>("", body_invert, 0, n_owned, n_owned);
347
348 const auto &boundary_map = offline_data_->level_boundary_map()[level_];
349
350 for (auto entry : boundary_map) {
351 // [i, normal, normal_mass, boundary_mass, id, position] = entry
352 const auto i = std::get<0>(entry);
353 if (i >= n_owned)
354 continue;
355
356 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
357 const auto id = std::get<4>(entry);
358
359 if (id == Boundary::slip) {
360 dealii::Tensor<1, dim, Number> V_i;
361 for (unsigned int d = 0; d < dim; ++d)
362 V_i[d] = vector.block(d).local_element(i);
363
364 /* replace normal component by 1. */
365 V_i -= 1. * (V_i * normal) * normal;
366 for (unsigned int d = 0; d < dim; ++d) {
367 V_i += 1. * (1. * normal[d]) * normal;
368 }
369
370 for (unsigned int d = 0; d < dim; ++d)
371 vector.block(d).local_element(i) = V_i[d];
372
373 } else if (id == Boundary::no_slip || id == Boundary::dirichlet) {
374
375 /* set dst to src vector: */
376 for (unsigned int d = 0; d < dim; ++d)
377 vector.block(d).local_element(i) = 1.;
378 }
379 }
380 }
381
382 private:
383 const ParabolicSystem *parabolic_system_;
384 const OfflineData<dim, Number2> *offline_data_;
385 const dealii::MatrixFree<dim, Number> *matrix_free_;
386 const vector_type *density_;
387 Number theta_x_tau_;
388 unsigned int level_;
389
390 template <typename Evaluator>
391 void apply_local_operator(Evaluator &velocity) const
392 {
393 const Number mu = parabolic_system_->mu();
394 const Number lambda = parabolic_system_->lambda();
395
396 velocity.evaluate(dealii::EvaluationFlags::gradients);
397
398 for (const unsigned int q : velocity.quadrature_point_indices()) {
399 if constexpr (dim == 1) {
400 /* Workaround: no symmetric gradient for dim == 1: */
401 const auto gradient = velocity.get_gradient(q);
402 auto S = (4. / 3. * mu + lambda) * gradient;
403 velocity.submit_gradient(theta_x_tau_ * S, q);
404
405 } else {
406
407 const auto symmetric_gradient = velocity.get_symmetric_gradient(q);
408 const auto divergence = trace(symmetric_gradient);
409 // S = (2 mu nabla^S(v) + (lambda - 2/3*mu) div(v) Id) : nabla phi
410 auto S = 2. * mu * symmetric_gradient;
411 for (unsigned int d = 0; d < dim; ++d)
412 S[d][d] += (lambda - 2. / 3. * mu) * divergence;
413 velocity.submit_symmetric_gradient(theta_x_tau_ * S, q);
414 }
415 }
416
417 velocity.integrate(dealii::EvaluationFlags::gradients);
418 }
419 };
420
421
425 template <int dim, typename Number>
427 : public dealii::MGTransferBase<
428 dealii::LinearAlgebra::distributed::BlockVector<Number>>
429 {
430 public:
431 using scalar_type = dealii::LinearAlgebra::distributed::Vector<Number>;
433 dealii::LinearAlgebra::distributed::BlockVector<Number>;
434
436
437 void build(const dealii::DoFHandler<dim> &dof_handler,
438 const dealii::MGConstrainedDoFs &mg_constrained_dofs,
439 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
440 &matrix_free)
441 {
442 transfer_.initialize_constraints(mg_constrained_dofs);
443 transfer_.build(dof_handler);
444 level_matrix_free_ = &matrix_free;
445 scalar_vector.resize(matrix_free.min_level(), matrix_free.max_level());
446 for (unsigned int level = matrix_free.min_level();
447 level < matrix_free.max_level();
448 ++level)
449 matrix_free[level].initialize_dof_vector(scalar_vector[level]);
450 }
451
452 void prolongate(const unsigned int to_level,
453 vector_type &dst,
454 const vector_type &src) const override
455 {
456 for (unsigned int block = 0; block < src.n_blocks(); ++block)
457 transfer_.prolongate(to_level, dst.block(block), src.block(block));
458 }
459
460 void restrict_and_add(const unsigned int to_level,
461 vector_type &dst,
462 const vector_type &src) const override
463 {
464 for (unsigned int block = 0; block < src.n_blocks(); ++block)
465 transfer_.restrict_and_add(
466 to_level, dst.block(block), src.block(block));
467 }
468
469 template <typename Number2>
471 const dealii::DoFHandler<dim> &dof_handler,
472 dealii::MGLevelObject<scalar_type> &dst,
473 const dealii::LinearAlgebra::distributed::Vector<Number2> &src) const
474 {
475 if (dst[dst.min_level()].size() == 0)
476 for (unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
477 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
478 transfer_.interpolate_to_mg(dof_handler, dst, src);
479 }
480
481 template <typename Number2>
482 void
483 copy_to_mg(const dealii::DoFHandler<dim> &dof_handler,
484 dealii::MGLevelObject<vector_type> &dst,
485 const dealii::LinearAlgebra::distributed::BlockVector<Number2>
486 &src) const
487 {
488 if (dst[dst.min_level()].size() == 0)
489 for (unsigned int l = dst.min_level(); l <= dst.max_level(); ++l) {
490 dst[l].reinit(src.n_blocks());
491 for (unsigned int block = 0; block < src.n_blocks(); ++block)
492 (*level_matrix_free_)[l].initialize_dof_vector(
493 dst[l].block(block));
494 dst[l].collect_sizes();
495 }
496
497 for (unsigned int block = 0; block < src.n_blocks(); ++block) {
498 transfer_.copy_to_mg(dof_handler, scalar_vector, src.block(block));
499 for (unsigned int level = dst.min_level(); level <= dst.max_level();
500 ++level)
501 dst[level].block(block).copy_locally_owned_data_from(
502 scalar_vector[level]);
503 }
504 }
505
506 template <typename Number2>
508 const dealii::DoFHandler<dim> &dof_handler,
509 dealii::LinearAlgebra::distributed::BlockVector<Number2> &dst,
510 const dealii::MGLevelObject<vector_type> &src) const
511 {
512 for (unsigned int block = 0; block < dst.n_blocks(); ++block) {
513 for (unsigned int level = src.min_level(); level <= src.max_level();
514 ++level)
515 scalar_vector[level].copy_locally_owned_data_from(
516 src[level].block(block));
517 transfer_.copy_from_mg(dof_handler, dst.block(block), scalar_vector);
518 }
519 }
520
521 private:
522 dealii::MGTransferMatrixFree<dim, Number> transfer_;
523 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
524 *level_matrix_free_;
525 mutable dealii::MGLevelObject<scalar_type> scalar_vector;
526 };
527
528
532 template <int dim, typename Number, typename Number2>
533 class EnergyMatrix : public dealii::EnableObserverPointer
534 {
535 public:
536 // FIXME: refactor
537 static constexpr unsigned int order_fe = 1;
538 static constexpr unsigned int order_quad = 2;
539
540 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
541
542 EnergyMatrix() = default;
543
545 const OfflineData<dim, Number2> &offline_data,
546 const dealii::MatrixFree<dim, Number> &matrix_free,
547 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
548 const Number time_factor,
549 const unsigned int level = dealii::numbers::invalid_unsigned_int)
550 {
551 offline_data_ = &offline_data;
552 matrix_free_ = &matrix_free;
553 density_ = &density;
554 factor_ = time_factor;
555 level_ = level;
556 }
557
558 void Tvmult(vector_type &dst, const vector_type &src) const
559 {
560 vmult(dst, src);
561 }
562
563 dealii::types::global_dof_index m() const
564 {
565 return density_->size();
566 }
567
568 Number el(const unsigned int, const unsigned int) const
569 {
570 Assert(false, dealii::ExcNotImplemented());
571 return Number();
572 }
573
574 void vmult(vector_type &dst, const vector_type &src) const
575 {
576 /* Apply action of m_i rho_i V_i: */
577
578 /* FIXME: we should really clean up this mess: */
579 const auto get_lumped_mass = [&](auto sentinel, unsigned int i) {
580 using T = decltype(sentinel);
581 if constexpr (std::is_same_v<Number, Number2>) {
582 if constexpr (std::is_same_v<Number, float>) {
583 if (level_ == dealii::numbers::invalid_unsigned_int) {
584 const auto lumped = offline_data_->lumped_mass_matrix().view();
585 return lumped.template read_entry<T>(i);
586 } else {
587 const auto &level_lumped =
588 offline_data_->level_lumped_mass_matrix()[level_];
589 return read_entry<T>(level_lumped, i);
590 }
591 } else {
592 Assert(level_ == dealii::numbers::invalid_unsigned_int,
593 dealii::ExcInternalError());
594 const auto lumped = offline_data_->lumped_mass_matrix().view();
595 return lumped.template read_entry<T>(i);
596 }
597 } else {
598 const auto &level_lumped =
599 offline_data_->level_lumped_mass_matrix()[level_];
600 return read_entry<T>(level_lumped, i);
601 }
602 };
603
604 const unsigned int n_owned =
605 dst.get_partitioner()->locally_owned_size();
606
607 const auto body_mass = [&](auto sentinel, unsigned int i) {
608 using T = decltype(sentinel);
609 const auto m_i = get_lumped_mass(T(), i);
610 const auto rho_i = read_entry<T>(*density_, i);
611 const auto e_i = read_entry<T>(src, i);
612 write_entry<T>(dst, m_i * rho_i * e_i, i);
613 };
614
615 cpu_simd_loop<Number>("", body_mass, 0, n_owned, n_owned);
616
617 /* Apply action of diffusion operator \sum_j beta_ij e_j: */
618
619 const auto integrator = [this](const auto &data,
620 auto &dst,
621 const auto &src,
622 const auto range) {
623 dealii::FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(
624 data);
625
626 for (unsigned int cell = range.first; cell < range.second; ++cell) {
627 energy.reinit(cell);
628 energy.read_dof_values(src);
629 apply_local_operator(energy);
630 energy.distribute_local_to_global(dst);
631 }
632 };
633
634 matrix_free_->template cell_loop<vector_type, vector_type>(
635 integrator, dst, src, /* zero destination */ false);
636
637 /* Fix up constrained degrees of freedom: */
638
639 const auto &boundary_map =
640 (level_ == dealii::numbers::invalid_unsigned_int)
641 ? offline_data_->boundary_map()
642 : offline_data_->level_boundary_map()[level_];
643
644 for (auto entry : boundary_map) {
645 const auto i = std::get<0>(entry);
646 if (i >= n_owned)
647 continue;
648
649 const auto id = std::get<4>(entry);
650 if (id == Boundary::dirichlet)
651 dst.local_element(i) = src.local_element(i);
652 }
653 }
654
656 std::shared_ptr<dealii::DiagonalMatrix<vector_type>> &matrix) const
657 {
658 Assert(level_ != dealii::numbers::invalid_unsigned_int,
659 dealii::ExcNotImplemented());
660 matrix = std::make_shared<dealii::DiagonalMatrix<vector_type>>();
661 vector_type &vector = matrix->get_vector();
662 matrix_free_->initialize_dof_vector(vector);
663
664 const vector_type &lumped_mass_matrix =
665 offline_data_->level_lumped_mass_matrix()[level_];
666
667 dealii::MatrixFreeTools::compute_diagonal(
668 *matrix_free_,
669 vector,
670 &EnergyMatrix::template apply_local_operator<
671 dealii::FEEvaluation<dim, -1, 0, dim, Number>>,
672 this);
673
674 const unsigned int n_owned =
675 lumped_mass_matrix.get_partitioner()->locally_owned_size();
676
677 const auto body_invert = [&](auto sentinel, const unsigned int i) {
678 using T = decltype(sentinel);
679
680 const auto m_i = read_entry<T>(lumped_mass_matrix, i);
681 const auto rho_i = read_entry<T>(*density_, i);
682 write_entry<T>(
683 vector, Number(1.) / (m_i * rho_i + read_entry<T>(vector, i)), i);
684 };
685 cpu_simd_loop<Number>("", body_invert, 0, n_owned, n_owned);
686
687 const auto &boundary_map = offline_data_->level_boundary_map()[level_];
688
689 for (auto entry : boundary_map) {
690 const auto i = std::get<0>(entry);
691 if (i >= n_owned)
692 continue;
693
694 const auto id = std::get<4>(entry);
695 if (id == Boundary::dirichlet)
696 vector.local_element(i) = 1.;
697 }
698 }
699
700 private:
701 const OfflineData<dim, Number2> *offline_data_;
702 const dealii::MatrixFree<dim, Number> *matrix_free_;
703 const dealii::LinearAlgebra::distributed::Vector<Number> *density_;
704 Number factor_;
705 unsigned int level_;
706
707 template <typename Evaluator>
708 void apply_local_operator(Evaluator &energy) const
709 {
710 energy.evaluate(dealii::EvaluationFlags::gradients);
711 for (unsigned int q = 0; q < energy.n_q_points; ++q) {
712 energy.submit_gradient(factor_ * energy.get_gradient(q), q);
713 }
714 energy.integrate(dealii::EvaluationFlags::gradients);
715 }
716 };
717
718
722 template <int dim, typename Number>
723 class MGTransferEnergy : public dealii::MGTransferMatrixFree<dim, Number>
724 {
725 public:
726 void build(const dealii::DoFHandler<dim> &dof_handler,
727 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
728 &matrix_free)
729 {
730 dealii::MGTransferMatrixFree<dim, Number>::build(dof_handler);
731 level_matrix_free_ = &matrix_free;
732 }
733
734 template <typename Number2>
736 const dealii::DoFHandler<dim> &dof_handler,
737 dealii::MGLevelObject<
738 dealii::LinearAlgebra::distributed::Vector<Number>> &dst,
739 const dealii::LinearAlgebra::distributed::Vector<Number2> &src) const
740 {
741 if (dst[dst.min_level()].size() == 0)
742 for (unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
743 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
744 dealii::MGTransferMatrixFree<dim, Number>::copy_to_mg(
745 dof_handler, dst, src);
746 }
747
748 private:
749 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
750 *level_matrix_free_;
751 };
752
753 } // namespace NavierStokes
754} /* namespace ryujin */
755
756#undef locally_owned_size
void vmult(vector_type &dst, const vector_type &src) const
void vmult(block_vector_type &dst, const block_vector_type &src) const
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
dealii::LinearAlgebra::distributed::BlockVector< Number > block_vector_type
void reinit(const Vector &lumped_mass_matrix, const vector_type &density, const dealii::AffineConstraints< Number > &affine_constraints)
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
void compute_diagonal(std::shared_ptr< dealii::DiagonalMatrix< vector_type > > &matrix) const
void Tvmult(vector_type &dst, const vector_type &src) const
void vmult(vector_type &dst, const vector_type &src) const
Number el(const unsigned int, const unsigned int) const
dealii::types::global_dof_index m() const
void initialize(const OfflineData< dim, Number2 > &offline_data, const dealii::MatrixFree< dim, Number > &matrix_free, const dealii::LinearAlgebra::distributed::Vector< Number > &density, const Number time_factor, const unsigned int level=dealii::numbers::invalid_unsigned_int)
void build(const dealii::DoFHandler< dim > &dof_handler, const dealii::MGLevelObject< dealii::MatrixFree< dim, Number > > &matrix_free)
void copy_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< dealii::LinearAlgebra::distributed::Vector< Number > > &dst, const dealii::LinearAlgebra::distributed::Vector< Number2 > &src) const
void prolongate(const unsigned int to_level, vector_type &dst, const vector_type &src) const override
void copy_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< vector_type > &dst, const dealii::LinearAlgebra::distributed::BlockVector< Number2 > &src) const
void restrict_and_add(const unsigned int to_level, vector_type &dst, const vector_type &src) const override
dealii::LinearAlgebra::distributed::Vector< Number > scalar_type
dealii::LinearAlgebra::distributed::BlockVector< Number > vector_type
void interpolate_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< scalar_type > &dst, const dealii::LinearAlgebra::distributed::Vector< Number2 > &src) const
void build(const dealii::DoFHandler< dim > &dof_handler, const dealii::MGConstrainedDoFs &mg_constrained_dofs, const dealii::MGLevelObject< dealii::MatrixFree< dim, Number > > &matrix_free)
void copy_from_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::LinearAlgebra::distributed::BlockVector< Number2 > &dst, const dealii::MGLevelObject< vector_type > &src) const
void vmult(block_vector_type &dst, const block_vector_type &src) const
dealii::LinearAlgebra::distributed::BlockVector< Number > block_vector_type
void initialize(const ParabolicSystem &parabolic_system, const OfflineData< dim, Number2 > &offline_data, const dealii::MatrixFree< dim, Number > &matrix_free, const dealii::LinearAlgebra::distributed::Vector< Number > &density, const Number theta_x_tau, const unsigned int level=dealii::numbers::invalid_unsigned_int)
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
void Tvmult(block_vector_type &dst, const block_vector_type &src) const
void compute_diagonal(std::shared_ptr< DiagonalMatrix< dim, Number > > &matrix) const
const auto & boundary_map() const
const auto & level_lumped_mass_matrix() const
const auto & level_boundary_map() const
const auto & lumped_mass_matrix() const
DEAL_II_ALWAYS_INLINE void write_entry(V &vector, const T &values, unsigned int i)
Definition simd.h:513