PolyDEAL
 
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) XXXX - YYYY by the polyDEAL authors
5//
6// This file is part of the polyDEAL library.
7//
8// Detailed license information governing the source code
9// can be found in LICENSE.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#ifndef utils_h
15#define utils_h
16
17#include <deal.II/base/point.h>
18
20
28
32
34
35#include <multigrid_amg.h>
36
37
38
39template <int dim, typename RtreeType>
41template <int, int>
43
44
45
46namespace Utils
47{
48 template <typename T>
49 inline constexpr T
50 constexpr_pow(T num, unsigned int pow)
51 {
52 return (pow >= sizeof(unsigned int) * 8) ? 0 :
53 pow == 0 ? 1 :
54 num * constexpr_pow(num, pow - 1);
55 }
56
57
58
63 struct Graph
64 {
65 std::vector<types::global_cell_index> nodes;
66 std::vector<std::vector<types::global_cell_index>> adjacency;
67
68 void
70 {
71 std::cout << "Graph information" << std::endl;
72 for (const auto &node : nodes)
73 {
74 std::cout << "Neighbors for node " << node << std::endl;
75 for (const auto &neigh_node : adjacency[node])
76 std::cout << neigh_node << std::endl;
77 }
78 }
79 };
80
81
82
95 template <int dim, int spacedim, typename MatrixType>
96 void
100 MatrixType &matrix)
101 {
102 using NumberType = typename MatrixType::value_type;
103 // First, check that we support the matrix types
104 static constexpr bool is_trilinos_matrix =
105 std::is_same_v<TrilinosWrappers::SparseMatrix, MatrixType>;
106 static constexpr bool is_serial_matrix =
107 std::is_same_v<SparseMatrix<NumberType>, MatrixType>;
108 static constexpr bool is_supported_matrix =
109 is_trilinos_matrix || is_serial_matrix;
110 static_assert(is_supported_matrix);
111 if constexpr (is_trilinos_matrix)
112 Assert(matrix.m() == 0, ExcInternalError());
113 if constexpr (is_serial_matrix)
114 Assert(sp.empty() && matrix.empty(),
115 ExcMessage(
116 "The destination matrix and its sparsity pattern must the empty "
117 "upon calling this function."));
118
119 Assert(coarse_ah.n_dofs() < fine_ah.n_dofs(), ExcInternalError());
120 AssertDimension(dim, spacedim);
121
122 // Get information from the handlers
123 const DoFHandler<dim, spacedim> &coarse_agglo_dh = coarse_ah.agglo_dh;
124 const DoFHandler<dim, spacedim> &fine_agglo_dh = fine_ah.agglo_dh;
125
126 const Mapping<dim, spacedim> &mapping = fine_ah.get_mapping();
127 const FiniteElement<dim, spacedim> &fe = coarse_ah.get_fe();
128 const Triangulation<dim, spacedim> &tria = coarse_ah.get_triangulation();
129 const auto &fine_bboxes = fine_ah.get_local_bboxes();
130 const auto &coarse_bboxes = coarse_ah.get_local_bboxes();
131
132 const IndexSet &locally_owned_dofs_fine =
133 fine_agglo_dh.locally_owned_dofs();
134 const IndexSet locally_relevant_dofs_fine =
136
137 const IndexSet &locally_owned_dofs_coarse =
138 coarse_agglo_dh.locally_owned_dofs();
139
140 std::conditional_t<is_trilinos_matrix,
143 dsp;
144
145 if constexpr (is_trilinos_matrix)
146 dsp.reinit(locally_owned_dofs_fine,
147 locally_owned_dofs_coarse,
148 tria.get_communicator());
149 else
150 dsp.reinit(fine_agglo_dh.n_dofs(),
151 coarse_agglo_dh.n_dofs(),
152 locally_relevant_dofs_fine);
153
154 const unsigned int dofs_per_cell = fe.dofs_per_cell;
155 std::vector<types::global_dof_index> agglo_dof_indices(dofs_per_cell);
156 std::vector<types::global_dof_index> standard_dof_indices(dofs_per_cell);
157 std::vector<types::global_dof_index> output_dof_indices(dofs_per_cell);
158
159 const std::vector<Point<dim>> &unit_support_points =
161 Quadrature<dim> quad(unit_support_points);
162 FEValues<dim, spacedim> output_fe_values(mapping,
163 fe,
164 quad,
166
167 std::vector<types::global_dof_index> local_dof_indices_coarse(
168 dofs_per_cell);
169 std::vector<types::global_dof_index> local_dof_indices_child(dofs_per_cell);
170
171 for (const auto &polytope : coarse_ah.polytope_iterators())
172 if (polytope->is_locally_owned())
173 {
174 polytope->get_dof_indices(local_dof_indices_coarse);
175
176 // Get local children and their DoFs
177 const auto &children_polytopes = polytope->children();
178 for (const types::global_cell_index child_idx : children_polytopes)
179 {
180 const typename DoFHandler<dim>::active_cell_iterator &child_dh =
181 fine_ah.polytope_to_dh_iterator(child_idx);
182 child_dh->get_dof_indices(local_dof_indices_child);
183 for (const auto row : local_dof_indices_child)
184 dsp.add_entries(row,
185 local_dof_indices_coarse.begin(),
186 local_dof_indices_coarse.end());
187 }
188 }
189
190 const auto assemble_injection_matrix = [&]() {
191 FullMatrix<NumberType> local_matrix(dofs_per_cell, dofs_per_cell);
192 std::vector<Point<dim>> reference_q_points(dofs_per_cell);
193
194 // Dummy AffineConstraints, only needed for loc2glb
196 c.close();
197
198 for (const auto &polytope : coarse_ah.polytope_iterators())
199 if (polytope->is_locally_owned())
200 {
201 polytope->get_dof_indices(local_dof_indices_coarse);
202 const BoundingBox<dim> &coarse_bbox =
203 coarse_bboxes[polytope->index()];
204
205 // Get local children of the present polytope
206 const auto &children_polytopes = polytope->children();
207 for (const types::global_cell_index child_idx : children_polytopes)
208 {
209 const BoundingBox<dim> &fine_bbox = fine_bboxes[child_idx];
210 const typename DoFHandler<dim>::active_cell_iterator &child_dh =
211 fine_ah.polytope_to_dh_iterator(child_idx);
212 child_dh->get_dof_indices(local_dof_indices_child);
213
214 local_matrix = 0.;
215
216 // compute real location of support points
217 std::vector<Point<dim>> real_qpoints;
218 real_qpoints.reserve(unit_support_points.size());
219 for (const Point<dim> &p : unit_support_points)
220 real_qpoints.push_back(fine_bbox.unit_to_real(p));
221
222 for (unsigned int i = 0; i < local_dof_indices_coarse.size();
223 ++i)
224 {
225 const auto &p = coarse_bbox.real_to_unit(real_qpoints[i]);
226 for (unsigned int j = 0; j < local_dof_indices_child.size();
227 ++j)
228 {
229 local_matrix(i, j) = fe.shape_value(j, p);
230 }
231 }
232
233 c.distribute_local_to_global(local_matrix,
234 local_dof_indices_child,
235 local_dof_indices_coarse,
236 matrix);
237 }
238 }
239 };
240
241
242 if constexpr (is_trilinos_matrix)
243 {
244 dsp.compress();
245 matrix.reinit(dsp);
246 assemble_injection_matrix();
247 }
248 else if constexpr (is_serial_matrix)
249 {
250 sp.copy_from(dsp);
251 matrix.reinit(sp);
252 assemble_injection_matrix();
253 }
254 else
255 {
256 // PETSc types not implemented.
257 (void)coarse_ah;
258 (void)fine_ah;
259 (void)sp;
260 (void)matrix;
261 AssertThrow(false,
262 ExcNotImplemented(
263 "This injection does not support PETSc types."));
264 }
265
266 // If tria is distributed
267 if (dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
268 &tria) != nullptr)
269 matrix.compress(VectorOperation::add);
270 }
271
272
273
286 template <typename VectorType, typename MatrixType, typename SolverType>
287 class MGCoarseDirect : public MGCoarseGridBase<VectorType>
288 {
289 public:
290 explicit MGCoarseDirect(const MatrixType &matrix)
291 : direct_solver(TrilinosWrappers::SolverDirect::AdditionalData())
292 , coarse_matrix(matrix)
293 {
294 // Check if matrix types are supported
295 static constexpr bool is_serial_matrix =
296 std::is_same_v<SolverType, SparseDirectUMFPACK>;
297 static constexpr bool is_trilinos_matrix =
298 std::is_same_v<SolverType, TrilinosWrappers::SolverDirect>;
299 [[maybe_unused]] static constexpr bool is_matrix_type_supported =
300 is_serial_matrix || is_trilinos_matrix;
301 Assert(is_matrix_type_supported, ExcNotImplemented());
302
303 // Check on the vector types: standard deal.II vectors, LA::d::V, or
304 // Trilinos vectors.
305 if constexpr (is_serial_matrix)
306 {
307 [[maybe_unused]] static constexpr bool is_serial_vector =
308 std::is_same_v<VectorType,
309 dealii::Vector<typename MatrixType::value_type>>;
310 Assert(is_serial_vector, ExcNotImplemented());
311 }
312 else if constexpr (is_trilinos_matrix)
313 {
314 [[maybe_unused]] static constexpr bool is_supported_parallel_vector =
315 std::is_same_v<VectorType,
317 typename MatrixType::value_type>> ||
318 std::is_same_v<VectorType, TrilinosWrappers::MPI::Vector>;
319 Assert(is_supported_parallel_vector, ExcNotImplemented());
320 }
321 else
322 {
323 AssertThrow(false, ExcNotImplemented());
324 // DEAL_II_NOT_IMPLEMENTED(); //not available in older releases
325 }
326
327
328 // regardless of UMFPACK or Trilinos, both direct solvers need a call
329 // to `initialize()`.
330 direct_solver.initialize(coarse_matrix);
331 }
332
333
334 void
335 operator()(const unsigned int,
336 VectorType &dst,
337 const VectorType &src) const override
338 {
339 AssertDimension(coarse_matrix.n(), src.size());
340 AssertDimension(coarse_matrix.m(), dst.size());
341 const_cast<SolverType &>(direct_solver).solve(dst, src);
342 }
343
344
345 ~MGCoarseDirect() = default;
346
347 private:
348 SolverType direct_solver;
349 const MatrixType &coarse_matrix;
350 };
351
352
353
360 template <int dim,
361 int degree,
362 int n_qpoints,
363 int n_components,
364 typename number = double>
366 {
367 public:
368 using value_type = number;
371
372
374
375 void
376 reinit(const Mapping<dim> &mapping,
377 const DoFHandler<dim> &dof_handler,
378 const unsigned int level = numbers::invalid_unsigned_int)
379 {
380 fe_degree = dof_handler.get_fe().degree;
381
382 const QGauss<1> quad(n_qpoints);
383 typename MatrixFree<dim, number>::AdditionalData addit_data;
384 addit_data.tasks_parallel_scheme =
386 addit_data.tasks_block_size = 3;
387 addit_data.mg_level = level;
392 constraints.close();
393
394 data.reinit(mapping, dof_handler, constraints, quad, addit_data);
395
397 }
398
399 void
402 {
403 dst = 0;
404 vmult_add(dst, src);
405 }
406
407 void
410 {
411 dst = 0;
412 vmult_add(dst, src);
413 }
414
415 void
421
422 void
425 {
427 *data.get_dof_info(0).vector_partitioner))
428 {
430 src_copy.reinit(data.get_dof_info().vector_partitioner);
431 src_copy = src;
433 src_copy);
434 }
436 *data.get_dof_info(0).vector_partitioner))
437 {
439 dst_copy.reinit(data.get_dof_info().vector_partitioner);
440 dst_copy = dst;
441 dst.swap(dst_copy);
442 }
447 this,
448 dst,
449 src);
450 }
451
453 m() const
454 {
455 return data.get_vector_partitioner()->size();
456 }
457
459 n() const
460 {
461 return data.get_vector_partitioner()->size();
462 }
463
464 number
465 el(const unsigned int row, const unsigned int col) const
466 {
467 (void)row;
468 (void)col;
469 AssertThrow(false,
470 ExcMessage("Matrix-free does not allow for entry access"));
471 return number();
472 }
473
474 void
477 {
478 data.initialize_dof_vector(vector);
479 }
480
481
482 const DoFHandler<dim> &
484 {
485 return data.get_dof_handler();
486 }
487
488
489 const Triangulation<dim> &
491 {
492 return data.get_dof_handler().get_triangulation();
493 }
494
500
501
504 {
505 return &data;
506 }
507
508
509
512 {
513 // Boilerplate for SIP-DG form. TODO: unify interface.
515 const auto cell_operation = [&](auto &phi) {
516 phi.evaluate(EvaluationFlags::gradients);
517 for (unsigned int q = 0; q < phi.n_q_points; ++q)
518 phi.submit_gradient(phi.get_gradient(q), q);
519 phi.integrate(EvaluationFlags::gradients);
520 };
521
522 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
525
526 VectorizedArrayType sigmaF =
527 (std::abs(
528 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
529 std::abs(
530 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
531 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
532
533 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
534 {
535 VectorizedArrayType average_value =
536 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
537 VectorizedArrayType average_valgrad =
538 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
539 average_valgrad =
540 average_value * 2. * sigmaF - average_valgrad * 0.5;
541 phi_m.submit_normal_derivative(-average_value, q);
542 phi_p.submit_normal_derivative(-average_value, q);
543 phi_m.submit_value(average_valgrad, q);
544 phi_p.submit_value(-average_valgrad, q);
545 }
548 };
549
550 const auto boundary_operation = [&](auto &phi_m) {
552 VectorizedArrayType sigmaF =
553 std::abs(
554 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
555 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
556
557 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
558 {
559 VectorizedArrayType average_value = phi_m.get_value(q);
560 VectorizedArrayType average_valgrad =
561 -phi_m.get_normal_derivative(q);
562 average_valgrad += average_value * sigmaF * 2.0;
563 phi_m.submit_normal_derivative(-average_value, q);
564 phi_m.submit_value(average_valgrad, q);
565 }
566
568 };
569
570
572
573
574 // Check if matrix has already been set up.
575 if (system_matrix.m() == 0 && system_matrix.n() == 0)
576 {
577 // Set up sparsity pattern of system matrix.
578 const auto &dof_handler = data.get_dof_handler();
579
581 data.get_mg_level() != numbers::invalid_unsigned_int ?
582 dof_handler.locally_owned_mg_dofs(data.get_mg_level()) :
583 dof_handler.locally_owned_dofs(),
584 data.get_task_info().communicator);
585
586 if (data.get_mg_level() != numbers::invalid_unsigned_int)
588 dsp,
589 data.get_mg_level(),
591 else
593
594 dsp.compress();
596
597 // Assemble system matrix. Notice that degree 1 has been hardcoded.
598
600 degree,
601 n_qpoints,
602 n_components,
603 number,
605 data,
608 cell_operation,
609 face_operation,
610 boundary_operation);
611 }
612
613 return system_matrix;
614 }
615
616
617
618 void
620 {
621 // Boilerplate for SIP-DG form. TODO: unify interface.
623 const auto cell_operation = [&](auto &phi) {
624 phi.evaluate(EvaluationFlags::gradients);
625 for (unsigned int q = 0; q < phi.n_q_points; ++q)
626 phi.submit_gradient(phi.get_gradient(q), q);
627 phi.integrate(EvaluationFlags::gradients);
628 };
629
630 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
633
634 VectorizedArrayType sigmaF =
635 (std::abs(
636 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
637 std::abs(
638 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
639 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
640
641 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
642 {
643 VectorizedArrayType average_value =
644 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
645 VectorizedArrayType average_valgrad =
646 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
647 average_valgrad =
648 average_value * 2. * sigmaF - average_valgrad * 0.5;
649 phi_m.submit_normal_derivative(-average_value, q);
650 phi_p.submit_normal_derivative(-average_value, q);
651 phi_m.submit_value(average_valgrad, q);
652 phi_p.submit_value(-average_valgrad, q);
653 }
656 };
657
658 const auto boundary_operation = [&](auto &phi_m) {
660 VectorizedArrayType sigmaF =
661 std::abs(
662 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
663 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
664
665 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
666 {
667 VectorizedArrayType average_value = phi_m.get_value(q);
668 VectorizedArrayType average_valgrad =
669 -phi_m.get_normal_derivative(q);
670 average_valgrad += average_value * sigmaF * 2.0;
671 phi_m.submit_normal_derivative(-average_value, q);
672 phi_m.submit_value(average_valgrad, q);
673 }
674
676 };
677
678
680
681 // Check if matrix has already been set up.
682 AssertThrow((mg_matrix.m() == 0 && mg_matrix.n() == 0),
683 ExcInternalError());
684
685 // Set up sparsity pattern of system matrix.
686 const DoFHandler<dim> &dof_handler = data.get_dof_handler();
687
688 const IndexSet &system_partitioning = dof_handler.locally_owned_dofs();
689 const IndexSet system_relevant_set =
691
692
693 DynamicSparsityPattern dsp(dof_handler.n_dofs(),
694 dof_handler.n_dofs(),
695 system_relevant_set);
696 DoFTools::make_flux_sparsity_pattern(dof_handler, dsp);
697
699 dsp,
700 system_partitioning,
701 data.get_task_info().communicator,
702 system_relevant_set);
703 mg_matrix.reinit(system_partitioning,
704 dsp,
705 data.get_task_info().communicator);
706
707 // Assemble system matrix.
709 degree,
710 n_qpoints,
711 n_components,
712 number,
715 mg_matrix,
716 cell_operation,
717 face_operation,
718 boundary_operation);
719 }
720
721
722
723 void
725 {
726 const int dummy = 0;
727
728
729 data.template cell_loop<LinearAlgebra::distributed::Vector<number>, int>(
730 [](const auto &matrix_free, auto &dst, const auto &, const auto cells) {
731 FEEvaluation<dim, -1, 0, n_components, number> phi(matrix_free,
732 cells);
733 for (unsigned int cell = cells.first; cell < cells.second; ++cell)
734 {
735 phi.reinit(cell);
736 for (unsigned int q = 0; q < phi.n_q_points; ++q)
737 {
738 if constexpr (n_components == 1)
739 {
740 phi.submit_value(1.0, q);
741 }
742 else
743 {
745 for (unsigned int v = 0;
746 v < VectorizedArray<number>::size();
747 ++v)
748 {
749 for (unsigned int i = 0; i < n_components; i++)
750 temp[i][v] = 1.;
751 }
752 phi.submit_value(temp, q);
753 }
754 }
755
756 phi.integrate_scatter(EvaluationFlags::values, dst);
757 }
758 },
759 b,
760 dummy,
761 true);
762 }
763
764
765
766 void
768 {
769 data.initialize_dof_vector(inverse_diagonal_entries);
770 unsigned int dummy = 0;
774 this,
776 dummy);
777
778 for (unsigned int i = 0;
779 i < inverse_diagonal_entries.locally_owned_size();
780 ++i)
781 if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
782 inverse_diagonal_entries.local_element(i) =
783 1. / inverse_diagonal_entries.local_element(i);
784 }
785
786
787 private:
788 void
792 const std::pair<unsigned int, unsigned int> &cell_range) const
793 {
794 FEEvaluation<dim, -1, 0, 1, number> phi(data);
795
796 for (unsigned int cell = cell_range.first; cell < cell_range.second;
797 ++cell)
798 {
799 phi.reinit(cell);
800 phi.read_dof_values(src);
801 phi.evaluate(EvaluationFlags::gradients);
802 for (unsigned int q = 0; q < phi.n_q_points; ++q)
803 phi.submit_gradient(phi.get_gradient(q), q);
804 phi.integrate(EvaluationFlags::gradients);
805 phi.distribute_local_to_global(dst);
806 }
807 }
808
809 void
814 const std::pair<unsigned int, unsigned int> &face_range) const
815 {
816 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
817 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval_neighbor(data, false);
818
819 for (unsigned int face = face_range.first; face < face_range.second;
820 ++face)
821 {
822 fe_eval.reinit(face);
823 fe_eval_neighbor.reinit(face);
824
825 fe_eval.read_dof_values(src);
826 fe_eval.evaluate(EvaluationFlags::values |
828 fe_eval_neighbor.read_dof_values(src);
829 fe_eval_neighbor.evaluate(EvaluationFlags::values |
832 (std::abs((fe_eval.normal_vector(0) *
833 fe_eval.inverse_jacobian(0))[dim - 1]) +
834 std::abs((fe_eval.normal_vector(0) *
835 fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
836 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
837
838 for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
839 {
840 VectorizedArray<number> average_value =
841 (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
842 VectorizedArray<number> average_valgrad =
843 fe_eval.get_normal_derivative(q) +
844 fe_eval_neighbor.get_normal_derivative(q);
845 average_valgrad =
846 average_value * 2. * sigmaF - average_valgrad * 0.5;
847 fe_eval.submit_normal_derivative(-average_value, q);
848 fe_eval_neighbor.submit_normal_derivative(-average_value, q);
849 fe_eval.submit_value(average_valgrad, q);
850 fe_eval_neighbor.submit_value(-average_valgrad, q);
851 }
852 fe_eval.integrate(EvaluationFlags::values |
854 fe_eval.distribute_local_to_global(dst);
855 fe_eval_neighbor.integrate(EvaluationFlags::values |
857 fe_eval_neighbor.distribute_local_to_global(dst);
858 }
859 }
860
861 void
866 const std::pair<unsigned int, unsigned int> &face_range) const
867 {
868 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
869 for (unsigned int face = face_range.first; face < face_range.second;
870 ++face)
871 {
872 fe_eval.reinit(face);
873 fe_eval.read_dof_values(src);
874 fe_eval.evaluate(EvaluationFlags::values |
877 std::abs((fe_eval.normal_vector(0) *
878 fe_eval.inverse_jacobian(0))[dim - 1]) *
879 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
880
881 for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
882 {
883 VectorizedArray<number> average_value = fe_eval.get_value(q);
884 VectorizedArray<number> average_valgrad =
885 -fe_eval.get_normal_derivative(q);
886 average_valgrad += average_value * sigmaF * 2.0;
887 fe_eval.submit_normal_derivative(-average_value, q);
888 fe_eval.submit_value(average_valgrad, q);
889 }
890
891 fe_eval.integrate(EvaluationFlags::values |
893 fe_eval.distribute_local_to_global(dst);
894 }
895 }
896
897
898 void
902 const unsigned int &,
903 const std::pair<unsigned int, unsigned int> &cell_range) const
904 {
905 FEEvaluation<dim, -1, 0, 1, number> phi(data);
906 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
907 phi.dofs_per_cell);
908
909 for (unsigned int cell = cell_range.first; cell < cell_range.second;
910 ++cell)
911 {
912 phi.reinit(cell);
913
914 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
915 {
916 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
917 phi.begin_dof_values()[j] = VectorizedArray<number>();
918 phi.begin_dof_values()[i] = 1.;
919 phi.evaluate(EvaluationFlags::gradients);
920 for (unsigned int q = 0; q < phi.n_q_points; ++q)
921 phi.submit_gradient(phi.get_gradient(q), q);
922 phi.integrate(EvaluationFlags::gradients);
923 local_diagonal_vector[i] = phi.begin_dof_values()[i];
924 }
925 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
926 phi.begin_dof_values()[i] = local_diagonal_vector[i];
927 phi.distribute_local_to_global(dst);
928 }
929 }
930
931 void
935 const unsigned int &,
936 const std::pair<unsigned int, unsigned int> &face_range) const
937 {
938 FEFaceEvaluation<dim, -1, 0, 1, number> phi(data, true);
939 FEFaceEvaluation<dim, -1, 0, 1, number> phi_outer(data, false);
940 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
941 phi.dofs_per_cell);
942
943 for (unsigned int face = face_range.first; face < face_range.second;
944 ++face)
945 {
946 phi.reinit(face);
947 phi_outer.reinit(face);
948
950 (std::abs(
951 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
952 std::abs((phi.normal_vector(0) *
953 phi_outer.inverse_jacobian(0))[dim - 1])) *
954 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
955
956 // Compute phi part
957 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
958 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
959 phi_outer.evaluate(EvaluationFlags::values |
961 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
962 {
963 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
964 phi.begin_dof_values()[j] = VectorizedArray<number>();
965 phi.begin_dof_values()[i] = 1.;
966 phi.evaluate(EvaluationFlags::values |
968
969 for (unsigned int q = 0; q < phi.n_q_points; ++q)
970 {
971 VectorizedArray<number> average_value =
972 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
973 VectorizedArray<number> average_valgrad =
974 phi.get_normal_derivative(q) +
975 phi_outer.get_normal_derivative(q);
976 average_valgrad =
977 average_value * 2. * sigmaF - average_valgrad * 0.5;
978 phi.submit_normal_derivative(-average_value, q);
979 phi.submit_value(average_valgrad, q);
980 }
981 phi.integrate(EvaluationFlags::values |
983 local_diagonal_vector[i] = phi.begin_dof_values()[i];
984 }
985 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
986 phi.begin_dof_values()[i] = local_diagonal_vector[i];
987 phi.distribute_local_to_global(dst);
988
989 // Compute phi_outer part
990 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
991 phi.begin_dof_values()[j] = VectorizedArray<number>();
993 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
994 {
995 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
996 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
997 phi_outer.begin_dof_values()[i] = 1.;
998 phi_outer.evaluate(EvaluationFlags::values |
1000
1001 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1002 {
1003 VectorizedArray<number> average_value =
1004 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
1005 VectorizedArray<number> average_valgrad =
1006 phi.get_normal_derivative(q) +
1007 phi_outer.get_normal_derivative(q);
1008 average_valgrad =
1009 average_value * 2. * sigmaF - average_valgrad * 0.5;
1010 phi_outer.submit_normal_derivative(-average_value, q);
1011 phi_outer.submit_value(-average_valgrad, q);
1012 }
1013 phi_outer.integrate(EvaluationFlags::values |
1015 local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
1016 }
1017 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1018 phi_outer.begin_dof_values()[i] = local_diagonal_vector[i];
1019 phi_outer.distribute_local_to_global(dst);
1020 }
1021 }
1022
1023 void
1027 const unsigned int &,
1028 const std::pair<unsigned int, unsigned int> &face_range) const
1029 {
1030 FEFaceEvaluation<dim, -1, 0, 1, number> phi(data);
1031 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
1032 phi.dofs_per_cell);
1033
1034 for (unsigned int face = face_range.first; face < face_range.second;
1035 ++face)
1036 {
1037 phi.reinit(face);
1038
1040 std::abs(
1041 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) *
1042 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
1043
1044 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1045 {
1046 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1047 phi.begin_dof_values()[j] = VectorizedArray<number>();
1048 phi.begin_dof_values()[i] = 1.;
1049 phi.evaluate(EvaluationFlags::values |
1051
1052 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1053 {
1054 VectorizedArray<number> average_value = phi.get_value(q);
1055 VectorizedArray<number> average_valgrad =
1056 -phi.get_normal_derivative(q);
1057 average_valgrad += average_value * sigmaF * 2.0;
1058 phi.submit_normal_derivative(-average_value, q);
1059 phi.submit_value(average_valgrad, q);
1060 }
1061
1062 phi.integrate(EvaluationFlags::values |
1064 local_diagonal_vector[i] = phi.begin_dof_values()[i];
1065 }
1066 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1067 phi.begin_dof_values()[i] = local_diagonal_vector[i];
1068 phi.distribute_local_to_global(dst);
1069 }
1070 }
1071
1072
1073
1079 };
1080
1081
1082
1087 get_index(const std::vector<types::global_cell_index> &v,
1088 const types::global_cell_index index)
1089 {
1090 return std::distance(v.begin(), std::find(v.begin(), v.end(), index));
1091 }
1092
1093
1094
1095 template <int dim>
1096 void
1098 const std::vector<typename Triangulation<dim>::active_cell_iterator> &cells,
1099 Graph &g)
1100 {
1101 Assert(cells.size() > 0, ExcMessage("No cells to be agglomerated."));
1102 const unsigned int n_faces = cells[0]->n_faces();
1103
1104 std::vector<types::global_cell_index> vec_cells(cells.size());
1105 for (size_t i = 0; i < cells.size(); i++)
1106 vec_cells[i] = cells[i]->active_cell_index();
1107
1108 g.adjacency.resize(cells.size());
1109 for (const auto &cell : cells)
1110 {
1111 // std::cout << "Cell idx: " << cell->active_cell_index() << std::endl;
1112 // std::cout << "new idx: "
1113 // << get_index(vec_cells, cell->active_cell_index())
1114 // << std::endl;
1115 g.nodes.push_back(get_index(vec_cells, cell->active_cell_index()));
1116 for (unsigned int f = 0; f < n_faces; ++f)
1117 {
1118 const auto &neigh = cell->neighbor(f);
1119 if (neigh.state() == IteratorState::IteratorStates::valid &&
1120 std::find(cells.begin(), cells.end(), neigh) != std::end(cells))
1121 g.adjacency[get_index(vec_cells, cell->active_cell_index())]
1122 .push_back(get_index(vec_cells, neigh->active_cell_index()));
1123 }
1124 }
1125 }
1126
1127
1128
1129 inline void
1130 dfs(std::vector<types::global_cell_index> &comp,
1131 std::vector<bool> &visited,
1132 const Graph &g,
1134 {
1135 visited[v] = true;
1136 comp.push_back(v);
1137 for (const types::global_cell_index u : g.adjacency[v])
1138 {
1139 if (!visited[u])
1140 dfs(comp, visited, g, u);
1141 }
1142 }
1143
1144
1145
1146 void
1148 Graph &g,
1149 std::vector<std::vector<types::global_cell_index>> &connected_components)
1150 {
1151 Assert(g.nodes.size() > 0, ExcMessage("No nodes in this graph."));
1152 Assert(
1153 connected_components.size() == 0,
1154 ExcMessage(
1155 "Connected components have to be computed by the present function."));
1156
1157 std::vector<bool> visited(g.nodes.size()); // register visited node
1158 std::fill(visited.begin(), visited.end(), 0);
1159
1160
1162 {
1163 if (!visited[v])
1164 {
1165 connected_components.emplace_back();
1166 dfs(connected_components.back(), visited, g, v);
1167 }
1168 }
1169 }
1170
1171
1172
1173} // namespace Utils
1174
1175
1176
1177#endif
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
Point< spacedim, Number > real_to_unit(const Point< spacedim, Number > &point) const
Point< spacedim, Number > unit_to_real(const Point< spacedim, Number > &point) const
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
const IndexSet & locally_owned_dofs() const
types::global_dof_index n_dofs() const
void reinit(const size_type m, const size_type n, const IndexSet &rowset=IndexSet())
const unsigned int degree
const unsigned int dofs_per_cell
const std::vector< Point< dim > > & get_unit_support_points() const
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
void swap(Vector< Number, MemorySpace > &v) noexcept
bool partitioners_are_globally_compatible(const Utilities::MPI::Partitioner &part) const
void reinit(const size_type size, const bool omit_zeroing_entries=false)
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
bool empty() const
MPI_Comm get_communicator() const
Triangulation< dim, spacedim > & get_triangulation()
void reinit(const SparsityPatternType &sparsity_pattern)
const DoFHandler< dim, spacedim >::active_cell_iterator polytope_to_dh_iterator(const types::global_cell_index polytope_index) const
types::global_dof_index n_dofs() const noexcept
const Triangulation< dim, spacedim > & get_triangulation() const
const Mapping< dim > & get_mapping() const
const std::vector< BoundingBox< dim > > & get_local_bboxes() const
const FiniteElement< dim, spacedim > & get_fe() const
IteratorRange< agglomeration_iterator > polytope_iterators() const
DoFHandler< dim, spacedim > agglo_dh
const Triangulation< dim > & get_triangulation() const
Definition utils.h:490
void local_diagonal_boundary(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const unsigned int &, const std::pair< unsigned int, unsigned int > &face_range) const
Definition utils.h:1024
const DoFHandler< dim > & get_dof_handler() const
Definition utils.h:483
const LinearAlgebra::distributed::Vector< number > & get_matrix_diagonal_inverse() const
Definition utils.h:496
types::global_dof_index m() const
Definition utils.h:453
void vmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:400
LinearAlgebra::distributed::Vector< number > inverse_diagonal_entries
Definition utils.h:1075
TrilinosWrappers::SparseMatrix system_matrix
Definition utils.h:1077
MatrixFree< dim, number > data
Definition utils.h:1074
void get_system_matrix(TrilinosWrappers::SparseMatrix &mg_matrix) const
Definition utils.h:619
void local_diagonal_cell(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const unsigned int &, const std::pair< unsigned int, unsigned int > &cell_range) const
Definition utils.h:899
void local_apply_face(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src, const std::pair< unsigned int, unsigned int > &face_range) const
Definition utils.h:810
void rhs(LinearAlgebra::distributed::Vector< number > &b) const
Definition utils.h:724
void local_diagonal_face(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const unsigned int &, const std::pair< unsigned int, unsigned int > &face_range) const
Definition utils.h:932
void local_apply_boundary(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src, const std::pair< unsigned int, unsigned int > &face_range) const
Definition utils.h:862
void local_apply(const MatrixFree< dim, number > &data, LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src, const std::pair< unsigned int, unsigned int > &cell_range) const
Definition utils.h:789
types::global_dof_index n() const
Definition utils.h:459
void reinit(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const unsigned int level=numbers::invalid_unsigned_int)
Definition utils.h:376
void Tvmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:408
number el(const unsigned int row, const unsigned int col) const
Definition utils.h:465
const MatrixFree< dim, number > * get_matrix_free() const
Definition utils.h:503
void vmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:423
void Tvmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:416
AffineConstraints< number > constraints
Definition utils.h:1078
void initialize_dof_vector(LinearAlgebra::distributed::Vector< number > &vector) const
Definition utils.h:475
void compute_inverse_diagonal()
Definition utils.h:767
const TrilinosWrappers::SparseMatrix & get_system_matrix() const
Definition utils.h:511
const MatrixType & coarse_matrix
Definition utils.h:349
MGCoarseDirect(const MatrixType &matrix)
Definition utils.h:290
void operator()(const unsigned int, VectorType &dst, const VectorType &src) const override
Definition utils.h:335
SolverType direct_solver
Definition utils.h:348
unsigned int level
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrow(cond, exc)
void make_flux_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern)
update_JxW_values
update_gradients
update_quadrature_points
Expression pow(const Expression &base, const Expression &exponent)
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
void make_flux_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity, const unsigned int level, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true)
void compute_matrix(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const AffineConstraints< Number > &constraints, MatrixType &matrix, const std::function< void(FEEvaluation< dim, fe_degree, n_q_points_1d, n_components, Number, VectorizedArrayType > &)> &cell_operation, const unsigned int dof_no=0, const unsigned int quad_no=0, const unsigned int first_selected_component=0)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
void distribute_sparsity_pattern(DynamicSparsityPattern &dsp, const IndexSet &locally_owned_rows, const MPI_Comm mpi_comm, const IndexSet &locally_relevant_rows)
Definition utils.h:47
void create_graph_from_agglomerate(const std::vector< typename Triangulation< dim >::active_cell_iterator > &cells, Graph &g)
Definition utils.h:1097
void dfs(std::vector< types::global_cell_index > &comp, std::vector< bool > &visited, const Graph &g, const types::global_cell_index v)
Definition utils.h:1130
constexpr T constexpr_pow(T num, unsigned int pow)
Definition utils.h:50
void fill_injection_matrix(const AgglomerationHandler< dim, spacedim > &coarse_ah, const AgglomerationHandler< dim, spacedim > &fine_ah, SparsityPattern &sp, MatrixType &matrix)
Definition utils.h:97
void compute_connected_components(Graph &g, std::vector< std::vector< types::global_cell_index > > &connected_components)
Definition utils.h:1147
types::global_cell_index get_index(const std::vector< types::global_cell_index > &v, const types::global_cell_index index)
Definition utils.h:1087
static const unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
unsigned int global_cell_index
void swap(ObserverPointer< T, P > &t1, ObserverPointer< T, Q > &t2)
TasksParallelScheme tasks_parallel_scheme
UpdateFlags mapping_update_flags_inner_faces
UpdateFlags mapping_update_flags_boundary_faces
void print_graph() const
Definition utils.h:69
std::vector< std::vector< types::global_cell_index > > adjacency
Definition utils.h:66
std::vector< types::global_cell_index > nodes
Definition utils.h:65