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_mpi_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
354 namespace Physics
355 {
356
357 enum class TimeStepping
358 {
361 };
362
364 {
365 double dt = 1e-4;
366 double penalty_constant = 10.;
367 double chi = 1e5;
368 double Cm = 1e-2;
369 double sigma = 12e-2;
370 double sigma_l = 0.;
371 double sigma_t = 0.;
372 double sigma_n = 0.;
373 bool use_fibers = false;
375 };
376
377 } // namespace Physics
378
380 {
387 template <int dim,
388 int degree,
389 int n_q_points,
390 int n_components,
391 typename number = double>
393 {
394 public:
395 using value_type = number;
398
399
401
402 void
403 reinit(const Mapping<dim> &mapping,
404 const DoFHandler<dim> &dof_handler,
405 const unsigned int level = numbers::invalid_unsigned_int)
406 {
407 fe_degree = dof_handler.get_fe().degree;
408
409 const QGauss<1> quad(n_q_points);
410 typename MatrixFree<dim, number>::AdditionalData addit_data;
411 addit_data.tasks_parallel_scheme =
413 addit_data.tasks_block_size = 3;
414 addit_data.mg_level = level;
419 constraints.close();
420
421 data.reinit(mapping, dof_handler, constraints, quad, addit_data);
422
424 }
425
426 void
429 {
430 dst = 0;
431 vmult_add(dst, src);
432 }
433
434 void
437 {
438 dst = 0;
439 vmult_add(dst, src);
440 }
441
442 void
448
449 void
452 {
454 *data.get_dof_info(0).vector_partitioner))
455 {
457 src_copy.reinit(data.get_dof_info().vector_partitioner);
458 src_copy = src;
460 src_copy);
461 }
463 *data.get_dof_info(0).vector_partitioner))
464 {
466 dst_copy.reinit(data.get_dof_info().vector_partitioner);
467 dst_copy = dst;
468 dst.swap(dst_copy);
469 }
474 this,
475 dst,
476 src);
477 }
478
480 m() const
481 {
482 return data.get_vector_partitioner()->size();
483 }
484
486 n() const
487 {
488 return data.get_vector_partitioner()->size();
489 }
490
491 number
492 el(const unsigned int row, const unsigned int col) const
493 {
494 (void)row;
495 (void)col;
496 AssertThrow(false,
497 ExcMessage("Matrix-free does not allow for entry access"));
498 return number();
499 }
500
501 void
504 {
505 data.initialize_dof_vector(vector);
506 }
507
508
509 const DoFHandler<dim> &
511 {
512 return data.get_dof_handler();
513 }
514
515
516 const Triangulation<dim> &
518 {
519 return data.get_dof_handler().get_triangulation();
520 }
521
527
528
531 {
532 return &data;
533 }
534
535
536
539 {
540 // Boilerplate for SIP-DG form. TODO: unify interface.
542 const auto cell_operation = [&](auto &phi) {
543 phi.evaluate(EvaluationFlags::gradients);
544 for (unsigned int q = 0; q < phi.n_q_points; ++q)
545 phi.submit_gradient(phi.get_gradient(q), q);
546 phi.integrate(EvaluationFlags::gradients);
547 };
548
549 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
552
553 VectorizedArrayType sigmaF =
554 (std::abs(
555 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
556 std::abs(
557 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
558 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
559
560 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
561 {
562 VectorizedArrayType jump_value =
563 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
564 VectorizedArrayType average_valgrad =
565 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
566 average_valgrad =
567 jump_value * 2. * sigmaF - average_valgrad * 0.5;
568 phi_m.submit_normal_derivative(-jump_value, q);
569 phi_p.submit_normal_derivative(-jump_value, q);
570 phi_m.submit_value(average_valgrad, q);
571 phi_p.submit_value(-average_valgrad, q);
572 }
575 };
576
577 const auto boundary_operation = [&](auto &phi_m) {
579 VectorizedArrayType sigmaF =
580 std::abs(
581 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
582 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
583
584 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
585 {
586 VectorizedArrayType jump_value = phi_m.get_value(q);
587 VectorizedArrayType average_valgrad =
588 -phi_m.get_normal_derivative(q);
589 average_valgrad += jump_value * sigmaF * 2.0;
590 phi_m.submit_normal_derivative(-jump_value, q);
591 phi_m.submit_value(average_valgrad, q);
592 }
593
595 };
596
597
599
600
601 // Check if matrix has already been set up.
602 if (system_matrix.m() == 0 && system_matrix.n() == 0)
603 {
604 // Set up sparsity pattern of system matrix.
605 const auto &dof_handler = data.get_dof_handler();
606
608 data.get_mg_level() != numbers::invalid_unsigned_int ?
609 dof_handler.locally_owned_mg_dofs(data.get_mg_level()) :
610 dof_handler.locally_owned_dofs(),
611 data.get_task_info().communicator);
612
613 if (data.get_mg_level() != numbers::invalid_unsigned_int)
615 dsp,
616 data.get_mg_level(),
618 else
620 dsp,
622
623 dsp.compress();
624 system_matrix.reinit(dsp);
625
626 // Assemble system matrix. Notice that degree 1 has been hardcoded.
627
629 degree,
630 n_q_points,
631 n_components,
632 number,
634 data,
637 cell_operation,
638 face_operation,
639 boundary_operation);
640 }
641
642 return system_matrix;
643 }
644
645
646
647 void
649 {
650 // Boilerplate for SIP-DG form. TODO: unify interface.
652 const auto cell_operation = [&](auto &phi) {
653 phi.evaluate(EvaluationFlags::gradients);
654 for (unsigned int q = 0; q < phi.n_q_points; ++q)
655 phi.submit_gradient(phi.get_gradient(q), q);
656 phi.integrate(EvaluationFlags::gradients);
657 };
658
659 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
662
663 VectorizedArrayType sigmaF =
664 (std::abs(
665 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
666 std::abs(
667 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
668 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
669
670 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
671 {
672 VectorizedArrayType jump_value =
673 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
674 VectorizedArrayType average_valgrad =
675 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
676 average_valgrad =
677 jump_value * 2. * sigmaF - average_valgrad * 0.5;
678 phi_m.submit_normal_derivative(-jump_value, q);
679 phi_p.submit_normal_derivative(-jump_value, q);
680 phi_m.submit_value(average_valgrad, q);
681 phi_p.submit_value(-average_valgrad, q);
682 }
685 };
686
687 const auto boundary_operation = [&](auto &phi_m) {
689 VectorizedArrayType sigmaF =
690 std::abs(
691 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
692 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
693
694 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
695 {
696 VectorizedArrayType jump_value = phi_m.get_value(q);
697 VectorizedArrayType average_valgrad =
698 -phi_m.get_normal_derivative(q);
699 average_valgrad += jump_value * sigmaF * 2.0;
700 phi_m.submit_normal_derivative(-jump_value, q);
701 phi_m.submit_value(average_valgrad, q);
702 }
703
705 };
706
707
709
710 // Check if matrix has already been set up.
711 AssertThrow((mg_matrix.m() == 0 && mg_matrix.n() == 0),
712 ExcInternalError());
713
714 // Set up sparsity pattern of system matrix.
715 const DoFHandler<dim> &dof_handler = data.get_dof_handler();
716
717 const IndexSet &system_partitioning = dof_handler.locally_owned_dofs();
718 const IndexSet system_relevant_set =
720
721
722 DynamicSparsityPattern dsp(dof_handler.n_dofs(),
723 dof_handler.n_dofs(),
724 system_relevant_set);
725 DoFTools::make_flux_sparsity_pattern(dof_handler, dsp);
726
728 dsp,
729 system_partitioning,
730 data.get_task_info().communicator,
731 system_relevant_set);
732 mg_matrix.reinit(system_partitioning,
733 dsp,
734 data.get_task_info().communicator);
735
736 // Assemble system matrix.
738 degree,
739 n_q_points,
740 n_components,
741 number,
743 data,
745 mg_matrix,
746 cell_operation,
747 face_operation,
748 boundary_operation);
749 }
750
751
752
753 void
755 {
756 const int dummy = 0;
757
758
759 data
760 .template cell_loop<LinearAlgebra::distributed::Vector<number>, int>(
761 [](const auto &matrix_free,
762 auto &dst,
763 const auto &,
764 const auto cells) {
765 FEEvaluation<dim, -1, 0, n_components, number> phi(matrix_free,
766 cells);
767 for (unsigned int cell = cells.first; cell < cells.second; ++cell)
768 {
769 phi.reinit(cell);
770 for (unsigned int q = 0; q < phi.n_q_points; ++q)
771 {
772 if constexpr (n_components == 1)
773 {
774 phi.submit_value(1.0, q);
775 }
776 else
777 {
779 for (unsigned int v = 0;
780 v < VectorizedArray<number>::size();
781 ++v)
782 {
783 for (unsigned int i = 0; i < n_components; i++)
784 temp[i][v] = 1.;
785 }
786 phi.submit_value(temp, q);
787 }
788 }
789
790 phi.integrate_scatter(EvaluationFlags::values, dst);
791 }
792 },
793 b,
794 dummy,
795 true);
796 }
797
798
799
800 void
802 {
803 data.initialize_dof_vector(inverse_diagonal_entries);
804 unsigned int dummy = 0;
808 this,
810 dummy);
811
812 for (unsigned int i = 0;
813 i < inverse_diagonal_entries.locally_owned_size();
814 ++i)
815 if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
816 inverse_diagonal_entries.local_element(i) =
817 1. / inverse_diagonal_entries.local_element(i);
818 }
819
820
821 private:
822 void
826 const std::pair<unsigned int, unsigned int> &cell_range) const
827 {
828 FEEvaluation<dim, -1, 0, 1, number> phi(data);
829
830 for (unsigned int cell = cell_range.first; cell < cell_range.second;
831 ++cell)
832 {
833 phi.reinit(cell);
834 phi.read_dof_values(src);
835 phi.evaluate(EvaluationFlags::gradients);
836 for (unsigned int q = 0; q < phi.n_q_points; ++q)
837 phi.submit_gradient(phi.get_gradient(q), q);
838 phi.integrate(EvaluationFlags::gradients);
839 phi.distribute_local_to_global(dst);
840 }
841 }
842
843 void
848 const std::pair<unsigned int, unsigned int> &face_range) const
849 {
850 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
851 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval_neighbor(data, false);
852
853 for (unsigned int face = face_range.first; face < face_range.second;
854 ++face)
855 {
856 fe_eval.reinit(face);
857 fe_eval_neighbor.reinit(face);
858
859 fe_eval.read_dof_values(src);
860 fe_eval.evaluate(EvaluationFlags::values |
862 fe_eval_neighbor.read_dof_values(src);
863 fe_eval_neighbor.evaluate(EvaluationFlags::values |
866 (std::abs((fe_eval.normal_vector(0) *
867 fe_eval.inverse_jacobian(0))[dim - 1]) +
868 std::abs((fe_eval.normal_vector(0) *
869 fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
870 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
871
872 for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
873 {
874 VectorizedArray<number> jump_value =
875 (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
876 VectorizedArray<number> average_valgrad =
877 fe_eval.get_normal_derivative(q) +
878 fe_eval_neighbor.get_normal_derivative(q);
879 average_valgrad =
880 jump_value * 2. * sigmaF - average_valgrad * 0.5;
881 fe_eval.submit_normal_derivative(-jump_value, q);
882 fe_eval_neighbor.submit_normal_derivative(-jump_value, q);
883 fe_eval.submit_value(average_valgrad, q);
884 fe_eval_neighbor.submit_value(-average_valgrad, q);
885 }
886 fe_eval.integrate(EvaluationFlags::values |
888 fe_eval.distribute_local_to_global(dst);
889 fe_eval_neighbor.integrate(EvaluationFlags::values |
891 fe_eval_neighbor.distribute_local_to_global(dst);
892 }
893 }
894
895 void
900 const std::pair<unsigned int, unsigned int> &face_range) const
901 {
902 FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
903 for (unsigned int face = face_range.first; face < face_range.second;
904 ++face)
905 {
906 fe_eval.reinit(face);
907 fe_eval.read_dof_values(src);
908 fe_eval.evaluate(EvaluationFlags::values |
911 std::abs((fe_eval.normal_vector(0) *
912 fe_eval.inverse_jacobian(0))[dim - 1]) *
913 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
914
915 for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
916 {
917 VectorizedArray<number> jump_value = fe_eval.get_value(q);
918 VectorizedArray<number> average_valgrad =
919 -fe_eval.get_normal_derivative(q);
920 average_valgrad += jump_value * sigmaF * 2.0;
921 fe_eval.submit_normal_derivative(-jump_value, q);
922 fe_eval.submit_value(average_valgrad, q);
923 }
924
925 fe_eval.integrate(EvaluationFlags::values |
927 fe_eval.distribute_local_to_global(dst);
928 }
929 }
930
931
932 void
936 const unsigned int &,
937 const std::pair<unsigned int, unsigned int> &cell_range) const
938 {
939 FEEvaluation<dim, -1, 0, 1, number> phi(data);
940 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
941 phi.dofs_per_cell);
942
943 for (unsigned int cell = cell_range.first; cell < cell_range.second;
944 ++cell)
945 {
946 phi.reinit(cell);
947
948 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
949 {
950 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
951 phi.begin_dof_values()[j] = VectorizedArray<number>();
952 phi.begin_dof_values()[i] = 1.;
953 phi.evaluate(EvaluationFlags::gradients);
954 for (unsigned int q = 0; q < phi.n_q_points; ++q)
955 phi.submit_gradient(phi.get_gradient(q), q);
956 phi.integrate(EvaluationFlags::gradients);
957 local_diagonal_vector[i] = phi.begin_dof_values()[i];
958 }
959 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
960 phi.begin_dof_values()[i] = local_diagonal_vector[i];
961 phi.distribute_local_to_global(dst);
962 }
963 }
964
965 void
969 const unsigned int &,
970 const std::pair<unsigned int, unsigned int> &face_range) const
971 {
972 FEFaceEvaluation<dim, -1, 0, 1, number> phi(data, true);
973 FEFaceEvaluation<dim, -1, 0, 1, number> phi_outer(data, false);
974 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
975 phi.dofs_per_cell);
976
977 for (unsigned int face = face_range.first; face < face_range.second;
978 ++face)
979 {
980 phi.reinit(face);
981 phi_outer.reinit(face);
982
984 (std::abs(
985 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
986 std::abs((phi.normal_vector(0) *
987 phi_outer.inverse_jacobian(0))[dim - 1])) *
988 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
989
990 // Compute phi part
991 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
992 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
993 phi_outer.evaluate(EvaluationFlags::values |
995 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
996 {
997 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
998 phi.begin_dof_values()[j] = VectorizedArray<number>();
999 phi.begin_dof_values()[i] = 1.;
1000 phi.evaluate(EvaluationFlags::values |
1002
1003 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1004 {
1005 VectorizedArray<number> jump_value =
1006 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
1007 VectorizedArray<number> average_valgrad =
1008 phi.get_normal_derivative(q) +
1009 phi_outer.get_normal_derivative(q);
1010 average_valgrad =
1011 jump_value * 2. * sigmaF - average_valgrad * 0.5;
1012 phi.submit_normal_derivative(-jump_value, q);
1013 phi.submit_value(average_valgrad, q);
1014 }
1015 phi.integrate(EvaluationFlags::values |
1017 local_diagonal_vector[i] = phi.begin_dof_values()[i];
1018 }
1019 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1020 phi.begin_dof_values()[i] = local_diagonal_vector[i];
1021 phi.distribute_local_to_global(dst);
1022
1023 // Compute phi_outer part
1024 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1025 phi.begin_dof_values()[j] = VectorizedArray<number>();
1027 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1028 {
1029 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1030 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
1031 phi_outer.begin_dof_values()[i] = 1.;
1032 phi_outer.evaluate(EvaluationFlags::values |
1034
1035 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1036 {
1037 VectorizedArray<number> jump_value =
1038 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
1039 VectorizedArray<number> average_valgrad =
1040 phi.get_normal_derivative(q) +
1041 phi_outer.get_normal_derivative(q);
1042 average_valgrad =
1043 jump_value * 2. * sigmaF - average_valgrad * 0.5;
1044 phi_outer.submit_normal_derivative(-jump_value, q);
1045 phi_outer.submit_value(-average_valgrad, q);
1046 }
1047 phi_outer.integrate(EvaluationFlags::values |
1049 local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
1050 }
1051 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1052 phi_outer.begin_dof_values()[i] = local_diagonal_vector[i];
1053 phi_outer.distribute_local_to_global(dst);
1054 }
1055 }
1056
1057 void
1061 const unsigned int &,
1062 const std::pair<unsigned int, unsigned int> &face_range) const
1063 {
1064 FEFaceEvaluation<dim, -1, 0, 1, number> phi(data);
1065 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
1066 phi.dofs_per_cell);
1067
1068 for (unsigned int face = face_range.first; face < face_range.second;
1069 ++face)
1070 {
1071 phi.reinit(face);
1072
1074 std::abs(
1075 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) *
1076 number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
1077
1078 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1079 {
1080 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1081 phi.begin_dof_values()[j] = VectorizedArray<number>();
1082 phi.begin_dof_values()[i] = 1.;
1083 phi.evaluate(EvaluationFlags::values |
1085
1086 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1087 {
1088 VectorizedArray<number> jump_value = phi.get_value(q);
1089 VectorizedArray<number> average_valgrad =
1090 -phi.get_normal_derivative(q);
1091 average_valgrad += jump_value * sigmaF * 2.0;
1092 phi.submit_normal_derivative(-jump_value, q);
1093 phi.submit_value(average_valgrad, q);
1094 }
1095
1096 phi.integrate(EvaluationFlags::values |
1098 local_diagonal_vector[i] = phi.begin_dof_values()[i];
1099 }
1100 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1101 phi.begin_dof_values()[i] = local_diagonal_vector[i];
1102 phi.distribute_local_to_global(dst);
1103 }
1104 }
1105
1106
1107
1113 };
1114
1115
1116
1120 template <int dim,
1121 int degree,
1122 int n_q_points,
1123 int n_components,
1124 typename number = double>
1126 {
1127 public:
1128 using value_type = number;
1132
1134 {
1135 parameters = parameters_;
1137 factor = (parameters.chi * parameters.Cm) / parameters.dt;
1138 else if (parameters.time_stepping == Utils::Physics::TimeStepping::BDF2)
1139 factor = (parameters.chi * parameters.Cm * 1.5) / parameters.dt;
1140 else
1142 };
1143
1144 void
1145 reinit(const Mapping<dim> &mapping,
1146 const DoFHandler<dim> &dof_handler,
1147 const unsigned int level = numbers::invalid_unsigned_int)
1148 {
1149 Assert(
1150 degree == dof_handler.get_fe().degree,
1151 ExcMessage(
1152 "Degree of the operator must match the degree of the DoFHandler"));
1153 fe_degree = dof_handler.get_fe().degree;
1154
1155 const QGauss<1> quad(n_q_points);
1156 typename MatrixFree<dim, number>::AdditionalData addit_data;
1157 addit_data.tasks_parallel_scheme =
1159 addit_data.tasks_block_size = 3;
1160 addit_data.mg_level = level;
1161 addit_data.mapping_update_flags =
1167 constraints.close();
1168
1169 data.reinit(mapping, dof_handler, constraints, quad, addit_data);
1170
1172 }
1173
1179 void
1180 reinit(const Mapping<dim> &mapping,
1181 const DoFHandler<dim> &dof_handler,
1182 const DoFHandler<dim> &fiber_dof_handler,
1183 const unsigned int level = numbers::invalid_unsigned_int)
1184 {
1185 Assert(
1186 degree == dof_handler.get_fe().degree,
1187 ExcMessage(
1188 "Degree of the operator must match the degree of the DoFHandler"));
1189 fe_degree = dof_handler.get_fe().degree;
1190
1191 const QGauss<1> quad(n_q_points);
1192 typename MatrixFree<dim, number>::AdditionalData addit_data;
1193 addit_data.tasks_parallel_scheme =
1195 addit_data.tasks_block_size = 3;
1196 addit_data.mg_level = level;
1197 addit_data.mapping_update_flags =
1203 constraints.close();
1204
1205 AffineConstraints<number> fiber_constraints;
1206 fiber_constraints.close();
1207
1208 data.reinit(mapping,
1209 std::vector<const DoFHandler<dim> *>{&dof_handler,
1210 &fiber_dof_handler},
1211 std::vector<const AffineConstraints<number> *>{
1212 &constraints, &fiber_constraints},
1213 quad,
1214 addit_data);
1215
1217 }
1218
1219
1227 void
1231 {
1232 // FEEvaluation for the fiber FESystem (dof_handler_index = 1).
1233 // Degree 1 is hardcoded for FE_Q(1) fibers; n_q_points from the
1234 // scalar operator is reused (over-integration is harmless).
1236 const unsigned int n_q = phi_fiber.n_q_points;
1237 const unsigned int n_batches = data.n_cell_batches();
1238
1239 fiber_f_data.resize(n_batches * n_q);
1240 fiber_s_data.resize(n_batches * n_q);
1241 fiber_n_data.resize(n_batches * n_q);
1242
1243 for (unsigned int cell = 0; cell < n_batches; ++cell)
1244 {
1245 phi_fiber.reinit(cell);
1246 const unsigned int base = cell * n_q;
1247
1248 // Read all three fiber fields for this cell batch
1249 phi_fiber.read_dof_values_plain(f0);
1251 for (unsigned int q = 0; q < n_q; ++q)
1252 fiber_f_data[base + q] = phi_fiber.get_value(q);
1253
1254 phi_fiber.read_dof_values_plain(s0);
1256 for (unsigned int q = 0; q < n_q; ++q)
1257 fiber_s_data[base + q] = phi_fiber.get_value(q);
1258
1259 phi_fiber.read_dof_values_plain(n0);
1261 for (unsigned int q = 0; q < n_q; ++q)
1262 fiber_n_data[base + q] = phi_fiber.get_value(q);
1263
1264 // Gram-Schmidt orthonormalization at each quadrature point
1265 for (unsigned int q = 0; q < n_q; ++q)
1266 {
1267 auto &fq = fiber_f_data[base + q];
1268 auto &sq = fiber_s_data[base + q];
1269 auto &nq = fiber_n_data[base + q];
1270
1271 fq /= fq.norm();
1272 sq -= (fq * sq) * fq;
1273 sq /= sq.norm();
1274 nq -= (fq * nq) * fq;
1275 nq -= (sq * nq) * sq;
1276 nq /= nq.norm();
1277 }
1278 }
1279
1280 // Precompute fiber directions at inner face quadrature points.
1281 // Since the fiber field is in continuous FE_Q(1), we can evaluate
1282 // from the interior side; the trace is unique.
1283 {
1285 true,
1286 1);
1287 const unsigned int n_fq = phi_face.n_q_points;
1288 const unsigned int n_f_inner = data.n_inner_face_batches();
1289
1290 fiber_f_face_data.resize(n_f_inner * n_fq);
1291 fiber_s_face_data.resize(n_f_inner * n_fq);
1292 fiber_n_face_data.resize(n_f_inner * n_fq);
1293
1294 for (unsigned int face = 0; face < n_f_inner; ++face)
1295 {
1296 phi_face.reinit(face);
1297 const unsigned int fbase = face * n_fq;
1298
1299 // Read all three fiber fields for this face batch
1300 phi_face.read_dof_values_plain(f0);
1302 for (unsigned int q = 0; q < n_fq; ++q)
1303 fiber_f_face_data[fbase + q] = phi_face.get_value(q);
1304
1305 phi_face.read_dof_values_plain(s0);
1307 for (unsigned int q = 0; q < n_fq; ++q)
1308 fiber_s_face_data[fbase + q] = phi_face.get_value(q);
1309
1310 phi_face.read_dof_values_plain(n0);
1312 for (unsigned int q = 0; q < n_fq; ++q)
1313 fiber_n_face_data[fbase + q] = phi_face.get_value(q);
1314
1315 // Gram-Schmidt orthonormalization at each face quadrature point
1316 for (unsigned int q = 0; q < n_fq; ++q)
1317 {
1318 auto &fq = fiber_f_face_data[fbase + q];
1319 auto &sq = fiber_s_face_data[fbase + q];
1320 auto &nq = fiber_n_face_data[fbase + q];
1321
1322 fq /= fq.norm();
1323 sq -= (fq * sq) * fq;
1324 sq /= sq.norm();
1325 nq -= (fq * nq) * fq;
1326 nq -= (sq * nq) * sq;
1327 nq /= nq.norm();
1328 }
1329 }
1330 }
1331 }
1332
1333 void
1336 {
1337 dst = 0;
1338 vmult_add(dst, src);
1339 }
1340
1341 void
1344 {
1345 dst = 0;
1346 vmult_add(dst, src);
1347 }
1348
1349 void
1355
1356 void
1359 {
1360 // When the operator is used inside a multigrid V-cycle the
1361 // smoother may hand us vectors whose partitioner comes from the
1362 // DoFHandler (locally_owned_dofs) rather than from the MatrixFree
1363 // object. In that case we transparently re-partition.
1365 *data.get_dof_info(0).vector_partitioner))
1366 {
1368 src_copy.reinit(data.get_dof_info(0).vector_partitioner);
1369 src_copy.copy_locally_owned_data_from(src);
1370 src_copy.update_ghost_values();
1372 src_copy);
1373 }
1375 *data.get_dof_info(0).vector_partitioner))
1376 {
1378 dst_copy.reinit(data.get_dof_info(0).vector_partitioner);
1379 dst_copy.copy_locally_owned_data_from(dst);
1380 dst.swap(dst_copy);
1381 }
1386 this,
1387 dst,
1388 src,
1389 /*zero_dst =*/false,
1392 }
1393
1395 m() const
1396 {
1397 return data.get_vector_partitioner()->size();
1398 }
1399
1401 n() const
1402 {
1403 return data.get_vector_partitioner()->size();
1404 }
1405
1406 number
1407 el(const unsigned int row, const unsigned int col) const
1408 {
1409 (void)row;
1410 (void)col;
1411 AssertThrow(false,
1412 ExcMessage("Matrix-free does not allow for entry access"));
1413 return number();
1414 }
1415
1416 void
1419 {
1420 data.initialize_dof_vector(vector);
1421 }
1422
1423
1424 const DoFHandler<dim> &
1426 {
1427 return data.get_dof_handler();
1428 }
1429
1430
1431 const Triangulation<dim> &
1433 {
1434 return data.get_dof_handler().get_triangulation();
1435 }
1436
1439 {
1441 }
1442
1443
1446 {
1447 return &data;
1448 }
1449
1450
1451
1454 {
1455 static_assert(dim != 3,
1456 "get_system_matrix() uses isotropic sigma and is only "
1457 "meant for the 2D example. Use the matrix-based "
1458 "assembly in monodomain_DG3D instead.");
1459
1460 // Boilerplate for SIP-DG form. TODO: unify interface.
1462
1463 const auto cell_operation = [&](auto &phi) {
1465 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1466 {
1467 // chi*Cm/dt M
1468 phi.submit_value(phi.get_value(q) * factor, q);
1469 // sigma K
1470 phi.submit_gradient(phi.get_gradient(q) * parameters.sigma, q);
1471 }
1473 };
1474
1475 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
1478
1479 VectorizedArrayType sigmaF =
1480 (std::abs(
1481 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
1482 std::abs(
1483 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
1484 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
1485
1486 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
1487 {
1488 VectorizedArrayType jump_value =
1489 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
1490 VectorizedArrayType average_valgrad =
1491 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
1492 average_valgrad =
1493 jump_value * 2. * sigmaF - average_valgrad * 0.5;
1494 phi_m.submit_normal_derivative(-parameters.sigma * jump_value, q);
1495 phi_p.submit_normal_derivative(-parameters.sigma * jump_value, q);
1496 phi_m.submit_value(parameters.sigma * average_valgrad, q);
1497 phi_p.submit_value(-parameters.sigma * average_valgrad, q);
1498 }
1501 };
1502
1503 // const auto boundary_operation = [&](auto &phi_m) {
1504 // (void)phi_m;
1505 // AssertThrow(
1506 // false,
1507 // ExcMessage(
1508 // "We have Neumann BCs only, so this should never be called."));
1509 // // Do nothing since we have homogeneous Neumann BCs
1510 // };
1511
1512
1514
1515
1516 // Check if matrix has already been set up.
1517 if (system_matrix.m() == 0 && system_matrix.n() == 0)
1518 {
1519 // Set up sparsity pattern of system matrix.
1520 const auto &dof_handler = data.get_dof_handler();
1521
1523 data.get_mg_level() != numbers::invalid_unsigned_int ?
1524 dof_handler.locally_owned_mg_dofs(data.get_mg_level()) :
1525 dof_handler.locally_owned_dofs(),
1526 data.get_task_info().communicator);
1527
1528 if (data.get_mg_level() != numbers::invalid_unsigned_int)
1530 dsp,
1531 data.get_mg_level(),
1532 constraints);
1533 else
1535 dsp,
1536 constraints);
1537
1538 dsp.compress();
1539 system_matrix.reinit(dsp);
1540
1541 // Assemble system matrix. Notice that degree 1 has been hardcoded.
1542
1544 degree,
1545 n_q_points,
1546 n_components,
1547 number,
1549 data,
1552 cell_operation,
1553 face_operation,
1554 nullptr /*boundary_operation*/);
1555 }
1556
1557 return system_matrix;
1558 }
1559
1560
1561
1562 void
1564 {
1565 static_assert(dim != 3,
1566 "get_system_matrix() uses isotropic sigma and is only "
1567 "meant for the 2D example. Use the matrix-based "
1568 "assembly in monodomain_DG3D instead.");
1569
1570 // Boilerplate for SIP-DG form. TODO: unify interface.
1572
1573 const auto cell_operation = [&](auto &phi) {
1575 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1576 {
1577 phi.submit_value(phi.get_value(q) * factor, q);
1578 phi.submit_gradient(phi.get_gradient(q) * parameters.sigma, q);
1579 }
1581 };
1582
1583 const auto face_operation = [&](auto &phi_m, auto &phi_p) {
1586
1587 VectorizedArrayType sigmaF =
1588 (std::abs(
1589 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
1590 std::abs(
1591 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
1592 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
1593
1594 for (unsigned int q = 0; q < phi_m.n_q_points; ++q)
1595 {
1596 VectorizedArrayType jump_value =
1597 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
1598 VectorizedArrayType average_valgrad =
1599 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
1600 average_valgrad =
1601 jump_value * 2. * sigmaF - average_valgrad * 0.5;
1602 phi_m.submit_normal_derivative(-parameters.sigma * jump_value, q);
1603 phi_p.submit_normal_derivative(-parameters.sigma * jump_value, q);
1604 phi_m.submit_value(parameters.sigma * average_valgrad, q);
1605 phi_p.submit_value(-parameters.sigma * average_valgrad, q);
1606 }
1609 };
1610
1611
1613
1614 // Check if matrix has already been set up.
1615 AssertThrow((mg_matrix.m() == 0 && mg_matrix.n() == 0),
1616 ExcInternalError());
1617
1618 // Set up sparsity pattern of system matrix.
1619 const DoFHandler<dim> &dof_handler = data.get_dof_handler();
1620
1621 const IndexSet &system_partitioning = dof_handler.locally_owned_dofs();
1622 const IndexSet system_relevant_set =
1624
1625
1626 DynamicSparsityPattern dsp(dof_handler.n_dofs(),
1627 dof_handler.n_dofs(),
1628 system_relevant_set);
1629 DoFTools::make_flux_sparsity_pattern(dof_handler, dsp);
1630
1632 dsp,
1633 system_partitioning,
1634 data.get_task_info().communicator,
1635 system_relevant_set);
1636 mg_matrix.reinit(system_partitioning,
1637 dsp,
1638 data.get_task_info().communicator);
1639
1640 // Assemble system matrix.
1642 degree,
1643 n_q_points,
1644 n_components,
1645 number,
1647 data,
1649 mg_matrix,
1650 cell_operation,
1651 face_operation,
1652 nullptr /*boundary_operation*/);
1653 }
1654
1655
1656 void
1658 {
1659 data.initialize_dof_vector(inverse_diagonal_entries);
1660 unsigned int dummy = 0;
1664 this,
1666 dummy);
1667
1668 for (unsigned int i = 0;
1669 i < inverse_diagonal_entries.locally_owned_size();
1670 ++i)
1671 if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
1672 inverse_diagonal_entries.local_element(i) =
1673 1. / inverse_diagonal_entries.local_element(i);
1674 }
1675
1676
1677
1678 void
1682 {
1684
1685 for (unsigned int cell = 0; cell < data.n_cell_batches(); ++cell)
1686 {
1687 phi.reinit(cell);
1688 phi.read_dof_values(src);
1690 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1691 phi.submit_value(phi.get_value(q) * factor, q);
1694 }
1696 }
1697
1698
1699
1700 void
1702 const LinearAlgebra::distributed::Vector<number> &solution_minus_ion,
1703 const Function<dim> &Iext) const
1704 {
1706
1707 for (unsigned int cell = 0; cell < data.n_cell_batches(); ++cell)
1708 {
1709 phi.reinit(cell);
1710 phi.read_dof_values(solution_minus_ion);
1712 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1713 {
1715 phi.quadrature_point(q);
1716 // evaluate the external current for each component in
1717 // VectorizedArray
1718 VectorizedArray<number> applied_current_value = 0.0;
1719 for (unsigned int v = 0; v < VectorizedArray<number>::size();
1720 ++v)
1721 {
1722 Point<dim> p;
1723 for (unsigned int d = 0; d < dim; ++d)
1724 p[d] = p_vect[d][v];
1725 applied_current_value[v] = Iext.value(p);
1726 }
1727
1728 // reaction_term = (parameters.chi * phi.get_value(q)) +
1729 // applied_current_value;
1730 phi.submit_value((parameters.chi * phi.get_value(q)) +
1731 applied_current_value,
1732 q);
1733 }
1736 }
1737 rhs.compress(VectorOperation::add);
1738 }
1739
1740
1741
1742 private:
1743 void
1747 const std::pair<unsigned int, unsigned int> &cell_range) const
1748 {
1750
1751 for (unsigned int cell = cell_range.first; cell < cell_range.second;
1752 ++cell)
1753 {
1754 phi.reinit(cell);
1755 phi.read_dof_values(src);
1757 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1758 {
1759 phi.submit_value(phi.get_value(q) * factor, q);
1760 phi.submit_gradient(
1761 apply_diffusion(phi.get_gradient(q), cell, q), q);
1762 }
1765 }
1766 }
1767
1768 void
1773 const std::pair<unsigned int, unsigned int> &face_range) const
1774 {
1776 data, true);
1778 fe_eval_neighbor(data, false);
1779
1780 for (unsigned int face = face_range.first; face < face_range.second;
1781 ++face)
1782 {
1783 fe_eval.reinit(face);
1784 fe_eval_neighbor.reinit(face);
1785
1786 fe_eval.read_dof_values(src);
1789 fe_eval_neighbor.read_dof_values(src);
1790 fe_eval_neighbor.evaluate(EvaluationFlags::values |
1793 (std::abs((fe_eval.normal_vector(0) *
1794 fe_eval.inverse_jacobian(0))[dim - 1]) +
1795 std::abs((fe_eval.normal_vector(0) *
1796 fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
1797 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
1798
1799 const number sigma_f = face_sigma();
1800 for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
1801 {
1802 const auto u_plus = fe_eval.get_value(q);
1803 const auto u_minus = fe_eval_neighbor.get_value(q);
1804 const auto jump_u = (u_plus - u_minus) * 0.5;
1805 const auto normal = fe_eval.normal_vector(q);
1806
1807 // Apply D to gradients from both sides and dot with normal
1808 // → {D gradu * n} = 0.5*(D gradu_plus*n + D gradu_minus*n)
1809 const auto D_grad_plus =
1810 apply_diffusion_face(fe_eval.get_gradient(q), face, q);
1811 const auto D_grad_minus =
1812 apply_diffusion_face(fe_eval_neighbor.get_gradient(q),
1813 face,
1814 q);
1815 const auto avg_D_grad_n =
1816 (D_grad_plus * normal + D_grad_minus * normal) * 0.5;
1817
1818 // D·n for the symmetry term:
1819 // -[u]*{D grad v*n} = -[u]*v*(Dn) (D is symmetric)
1820 const auto Dn = apply_diffusion_face(normal, face, q);
1821
1822 // Consistency: −{D gradu*n}[v]
1823 // Penalty: sigma_pen [u][v], sigma_pen = sigma_f * sigmaF
1824 const auto penalty_val = sigma_f * sigmaF * jump_u * 2.;
1825 fe_eval.submit_value(penalty_val - avg_D_grad_n, q);
1826 fe_eval_neighbor.submit_value(-penalty_val + avg_D_grad_n, q);
1827
1828 // Symmetry: −{D gradv*n}[u] = -grad v*(Dn) [u]/2
1829 fe_eval.submit_gradient(Dn * (-jump_u), q);
1830 fe_eval_neighbor.submit_gradient(Dn * (-jump_u), q);
1831 }
1834 fe_eval.distribute_local_to_global(dst);
1835 fe_eval_neighbor.integrate(EvaluationFlags::values |
1837 fe_eval_neighbor.distribute_local_to_global(dst);
1838 }
1839 }
1840
1841 void
1846 const std::pair<unsigned int, unsigned int> &face_range) const
1847 {
1848 (void)data;
1849 (void)dst;
1850 (void)src;
1851 (void)face_range;
1852 // Do nothing since we have homogeneous Neumann BCs
1853 }
1854
1855
1856 void
1860 const unsigned int &,
1861 const std::pair<unsigned int, unsigned int> &cell_range) const
1862 {
1864 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
1865 phi.dofs_per_cell);
1866
1867 for (unsigned int cell = cell_range.first; cell < cell_range.second;
1868 ++cell)
1869 {
1870 phi.reinit(cell);
1871
1872 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1873 {
1874 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1876 phi.begin_dof_values()[i] = 1.;
1879 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1880 {
1881 phi.submit_value(phi.get_value(q) * factor, q);
1882 phi.submit_gradient(
1883 apply_diffusion(phi.get_gradient(q), cell, q), q);
1884 }
1887 local_diagonal_vector[i] = phi.begin_dof_values()[i];
1888 }
1889 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1890 phi.begin_dof_values()[i] = local_diagonal_vector[i];
1892 }
1893 }
1894
1895 void
1899 const unsigned int &,
1900 const std::pair<unsigned int, unsigned int> &face_range) const
1901 {
1903 data, true);
1905 phi_outer(data, false);
1906 AlignedVector<VectorizedArray<number>> local_diagonal_vector(
1907 phi.dofs_per_cell);
1908
1909 for (unsigned int face = face_range.first; face < face_range.second;
1910 ++face)
1911 {
1912 phi.reinit(face);
1913 phi_outer.reinit(face);
1914
1916 (std::abs(
1917 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
1918 std::abs((phi.normal_vector(0) *
1919 phi_outer.inverse_jacobian(0))[dim - 1])) *
1920 (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
1921
1922 const number sigma_f = face_sigma();
1923
1924 // Compute phi part (u_plus = phi_i, u_minus = 0)
1925 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1926 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
1929 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1930 {
1931 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1933 phi.begin_dof_values()[i] = 1.;
1936
1937 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1938 {
1939 const auto u_plus = phi.get_value(q);
1940 const auto u_minus = phi_outer.get_value(q);
1941 const auto jump_u = (u_plus - u_minus) * 0.5;
1942 const auto normal = phi.normal_vector(q);
1943
1944 const auto D_grad_plus =
1945 apply_diffusion_face(phi.get_gradient(q), face, q);
1946 const auto D_grad_minus =
1947 apply_diffusion_face(phi_outer.get_gradient(q), face, q);
1948 const auto avg_D_grad_n =
1949 (D_grad_plus * normal + D_grad_minus * normal) * 0.5;
1950
1951 const auto Dn = apply_diffusion_face(normal, face, q);
1952
1953 const auto penalty_val = sigma_f * sigmaF * jump_u * 2.;
1954 phi.submit_value(penalty_val - avg_D_grad_n, q);
1955 phi.submit_gradient(Dn * (-jump_u), q);
1956 }
1959 local_diagonal_vector[i] = phi.begin_dof_values()[i];
1960 }
1961 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1962 phi.begin_dof_values()[i] = local_diagonal_vector[i];
1964
1965 // Compute phi_outer part (u_plus = 0, u_minus = phi_i)
1966 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1969 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1970 {
1971 for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1972 phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
1973 phi_outer.begin_dof_values()[i] = 1.;
1976
1977 for (unsigned int q = 0; q < phi.n_q_points; ++q)
1978 {
1979 const auto u_plus = phi.get_value(q);
1980 const auto u_minus = phi_outer.get_value(q);
1981 const auto jump_u = (u_plus - u_minus) * 0.5;
1982 const auto normal = phi.normal_vector(q);
1983
1984 const auto D_grad_plus =
1985 apply_diffusion_face(phi.get_gradient(q), face, q);
1986 const auto D_grad_minus =
1987 apply_diffusion_face(phi_outer.get_gradient(q), face, q);
1988 const auto avg_D_grad_n =
1989 (D_grad_plus * normal + D_grad_minus * normal) * 0.5;
1990
1991 const auto Dn = apply_diffusion_face(normal, face, q);
1992
1993 const auto penalty_val = sigma_f * sigmaF * jump_u * 2.;
1994 phi_outer.submit_value(-penalty_val + avg_D_grad_n, q);
1995 phi_outer.submit_gradient(Dn * (-jump_u), q);
1996 }
1999 local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
2000 }
2001 for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
2002 phi_outer.begin_dof_values()[i] = local_diagonal_vector[i];
2003 phi_outer.distribute_local_to_global(dst);
2004 }
2005 }
2006
2007 void
2011 const unsigned int &,
2012 const std::pair<unsigned int, unsigned int> &face_range) const
2013 {
2014 (void)data;
2015 (void)dst;
2016 (void)face_range;
2017 // Do nothing since we have homogeneous Neumann BCs
2018 }
2019
2020
2021
2022 // Total quadrature points per cell (compile-time constant)
2023 static constexpr unsigned int n_q_points_total =
2024 constexpr_pow(static_cast<unsigned int>(n_q_points),
2025 static_cast<unsigned int>(dim));
2026
2027 // Total quadrature points per face (compile-time constant)
2028 static constexpr unsigned int n_face_q_points_total =
2029 constexpr_pow(static_cast<unsigned int>(n_q_points),
2030 static_cast<unsigned int>(dim - 1));
2031
2040 const unsigned int cell,
2041 const unsigned int q) const
2042 {
2043 if (parameters.use_fibers && !fiber_f_data.empty())
2044 {
2045 const unsigned int idx = cell * n_q_points_total + q;
2046 const auto &f = fiber_f_data[idx];
2047 const auto &s = fiber_s_data[idx];
2048 const auto &nv = fiber_n_data[idx];
2049 return VectorizedArrayType(parameters.sigma_l) * (f * grad) * f +
2050 VectorizedArrayType(parameters.sigma_t) * (s * grad) * s +
2051 VectorizedArrayType(parameters.sigma_n) * (nv * grad) * nv;
2052 }
2053 else
2054 {
2055 return grad * VectorizedArrayType(parameters.sigma);
2056 }
2057 }
2058
2067 number
2069 {
2070 return parameters.use_fibers ?
2071 parameters.sigma_l + parameters.sigma_t + parameters.sigma_n :
2072 parameters.sigma;
2073 }
2074
2082 const unsigned int face,
2083 const unsigned int q) const
2084 {
2085 if (parameters.use_fibers && !fiber_f_face_data.empty())
2086 {
2087 const unsigned int idx = face * n_face_q_points_total + q;
2088 const auto &f = fiber_f_face_data[idx];
2089 const auto &s = fiber_s_face_data[idx];
2090 const auto &nv = fiber_n_face_data[idx];
2091 return VectorizedArrayType(parameters.sigma_l) * (f * vec) * f +
2092 VectorizedArrayType(parameters.sigma_t) * (s * vec) * s +
2093 VectorizedArrayType(parameters.sigma_n) * (nv * vec) * nv;
2094 }
2095 else
2096 {
2097 return vec * VectorizedArrayType(parameters.sigma);
2098 }
2099 }
2100
2101
2108 double factor;
2109
2110 // Precomputed fiber directions at cell quadrature points
2114
2115 // Precomputed fiber directions at inner face quadrature points
2119 };
2120
2121
2122
2123 } // namespace MatrixFreeOperators
2124
2125
2126
2131 get_index(const std::vector<types::global_cell_index> &v,
2132 const types::global_cell_index index)
2133 {
2134 return std::distance(v.begin(), std::find(v.begin(), v.end(), index));
2135 }
2136
2137
2138
2139 template <int dim>
2140 void
2142 const std::vector<typename Triangulation<dim>::active_cell_iterator> &cells,
2143 Graph &g)
2144 {
2145 Assert(cells.size() > 0, ExcMessage("No cells to be agglomerated."));
2146 const unsigned int n_faces = cells[0]->n_faces();
2147
2148 std::vector<types::global_cell_index> vec_cells(cells.size());
2149 for (size_t i = 0; i < cells.size(); i++)
2150 vec_cells[i] = cells[i]->active_cell_index();
2151
2152 g.adjacency.resize(cells.size());
2153 for (const auto &cell : cells)
2154 {
2155 // std::cout << "Cell idx: " << cell->active_cell_index() <<
2156 // std::endl; std::cout << "new idx: "
2157 // << get_index(vec_cells, cell->active_cell_index())
2158 // << std::endl;
2159 g.nodes.push_back(get_index(vec_cells, cell->active_cell_index()));
2160 for (unsigned int f = 0; f < n_faces; ++f)
2161 {
2162 const auto &neigh = cell->neighbor(f);
2163 if (neigh.state() == IteratorState::IteratorStates::valid &&
2164 std::find(cells.begin(), cells.end(), neigh) != std::end(cells))
2165 g.adjacency[get_index(vec_cells, cell->active_cell_index())]
2166 .push_back(get_index(vec_cells, neigh->active_cell_index()));
2167 }
2168 }
2169 }
2170
2171
2172
2173 inline void
2174 dfs(std::vector<types::global_cell_index> &comp,
2175 std::vector<bool> &visited,
2176 const Graph &g,
2178 {
2179 visited[v] = true;
2180 comp.push_back(v);
2181 for (const types::global_cell_index u : g.adjacency[v])
2182 {
2183 if (!visited[u])
2184 dfs(comp, visited, g, u);
2185 }
2186 }
2187
2188
2189
2190 void
2192 Graph &g,
2193 std::vector<std::vector<types::global_cell_index>> &connected_components)
2194 {
2195 Assert(g.nodes.size() > 0, ExcMessage("No nodes in this graph."));
2196 Assert(
2197 connected_components.size() == 0,
2198 ExcMessage(
2199 "Connected components have to be computed by the present function."));
2200
2201 std::vector<bool> visited(g.nodes.size()); // register visited node
2202 std::fill(visited.begin(), visited.end(), 0);
2203
2204
2206 {
2207 if (!visited[v])
2208 {
2209 connected_components.emplace_back();
2210 dfs(connected_components.back(), visited, g, v);
2211 }
2212 }
2213 }
2214
2215
2216} // namespace Utils
2217
2218
2219
2220#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())
gradient_type get_gradient(const unsigned int q_point) const
void submit_gradient(const gradient_type grad_in, const unsigned int q_point)
void submit_value(const value_type val_in, const unsigned int q_point)
void distribute_local_to_global(VectorType &dst, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip()) const
void read_dof_values_plain(const VectorType &src, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
value_type get_value(const unsigned int q_point) const
void read_dof_values(const VectorType &src, const unsigned int first_index=0, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Tensor< 2, dim, VectorizedArrayType > inverse_jacobian(const unsigned int q_point) const
Tensor< 1, dim, VectorizedArrayType > normal_vector(const unsigned int q_point) const
Point< dim, VectorizedArrayType > quadrature_point(const unsigned int q) const
const VectorizedArrayType * begin_dof_values() const
const unsigned int n_q_points
void reinit(const unsigned int cell_batch_index)
void evaluate(const EvaluationFlags::EvaluationFlags evaluation_flag)
const unsigned int dofs_per_cell
void integrate(const EvaluationFlags::EvaluationFlags integration_flag)
void reinit(const unsigned int face_batch_number)
const unsigned int n_q_points
const unsigned int dofs_per_cell
void evaluate(const EvaluationFlags::EvaluationFlags evaluation_flag)
void integrate(const EvaluationFlags::EvaluationFlags integration_flag, const bool sum_into_values=false)
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
virtual RangeNumberType value(const Point< dim > &p, const unsigned int component=0) const
void swap(Vector< Number, MemorySpace > &v) noexcept
void compress(VectorOperation::values operation)
bool partitioners_are_globally_compatible(const Utilities::MPI::Partitioner &part) const
void copy_locally_owned_data_from(const Vector< Number2, MemorySpace > &src)
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
virtual MPI_Comm get_mpi_communicator() const
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 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
void Tvmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:435
LinearAlgebra::distributed::Vector< number > inverse_diagonal_entries
Definition utils.h:1109
AffineConstraints< number > constraints
Definition utils.h:1112
void rhs(LinearAlgebra::distributed::Vector< number > &b) const
Definition utils.h:754
void vmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:450
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:966
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:1058
TrilinosWrappers::SparseMatrix system_matrix
Definition utils.h:1111
number el(const unsigned int row, const unsigned int col) const
Definition utils.h:492
void initialize_dof_vector(LinearAlgebra::distributed::Vector< number > &vector) const
Definition utils.h:502
void reinit(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const unsigned int level=numbers::invalid_unsigned_int)
Definition utils.h:403
VectorizedArray< number > VectorizedArrayType
Definition utils.h:396
const Triangulation< dim > & get_triangulation() const
Definition utils.h:517
const LinearAlgebra::distributed::Vector< number > & get_matrix_diagonal_inverse() const
Definition utils.h:523
const DoFHandler< dim > & get_dof_handler() const
Definition utils.h:510
const MatrixFree< dim, number > * get_matrix_free() const
Definition utils.h:530
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:933
void vmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:427
void get_system_matrix(TrilinosWrappers::SparseMatrix &mg_matrix) const
Definition utils.h:648
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:896
types::global_dof_index n() const
Definition utils.h:486
const TrilinosWrappers::SparseMatrix & get_system_matrix() const
Definition utils.h:538
void Tvmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:443
LinearAlgebra::distributed::Vector< number > VectorType
Definition utils.h:397
types::global_dof_index m() const
Definition utils.h:480
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:823
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:844
Tensor< 1, dim, VectorizedArrayType > apply_diffusion(const Tensor< 1, dim, VectorizedArrayType > &grad, const unsigned int cell, const unsigned int q) const
Definition utils.h:2039
Physics::BilinearFormParameters parameters
Definition utils.h:2107
AlignedVector< Tensor< 1, dim, VectorizedArrayType > > FiberArray
Definition utils.h:1131
void rhs(LinearAlgebra::distributed::Vector< number > &rhs, const LinearAlgebra::distributed::Vector< number > &solution_minus_ion, const Function< dim > &Iext) const
Definition utils.h:1701
MonodomainOperatorDG(const Physics::BilinearFormParameters &parameters_)
Definition utils.h:1133
const DoFHandler< dim > & get_dof_handler() const
Definition utils.h:1425
void reinit(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const DoFHandler< dim > &fiber_dof_handler, const unsigned int level=numbers::invalid_unsigned_int)
Definition utils.h:1180
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:1769
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:1744
Tensor< 1, dim, VectorizedArrayType > apply_diffusion_face(const Tensor< 1, dim, VectorizedArrayType > &vec, const unsigned int face, const unsigned int q) const
Definition utils.h:2081
const LinearAlgebra::distributed::Vector< number > & get_matrix_diagonal_inverse() const
Definition utils.h:1438
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:1896
const MatrixFree< dim, number > * get_matrix_free() const
Definition utils.h:1445
void reinit(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const unsigned int level=numbers::invalid_unsigned_int)
Definition utils.h:1145
TrilinosWrappers::SparseMatrix system_matrix
Definition utils.h:2105
LinearAlgebra::distributed::Vector< number > inverse_diagonal_entries
Definition utils.h:2103
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:1857
VectorizedArray< number > VectorizedArrayType
Definition utils.h:1129
AffineConstraints< number > constraints
Definition utils.h:2106
void Tvmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:1350
static constexpr unsigned int n_face_q_points_total
Definition utils.h:2028
void apply_mass_term(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:1679
const TrilinosWrappers::SparseMatrix & get_system_matrix() const
Definition utils.h:1453
number el(const unsigned int row, const unsigned int col) const
Definition utils.h:1407
LinearAlgebra::distributed::Vector< number > VectorType
Definition utils.h:1130
types::global_dof_index m() const
Definition utils.h:1395
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:1842
void precompute_fibers(const LinearAlgebra::distributed::Vector< number > &f0, const LinearAlgebra::distributed::Vector< number > &s0, const LinearAlgebra::distributed::Vector< number > &n0)
Definition utils.h:1228
void get_system_matrix(TrilinosWrappers::SparseMatrix &mg_matrix) const
Definition utils.h:1563
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:2008
void vmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:1357
void vmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:1334
types::global_dof_index n() const
Definition utils.h:1401
void initialize_dof_vector(LinearAlgebra::distributed::Vector< number > &vector) const
Definition utils.h:1417
void Tvmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
Definition utils.h:1342
static constexpr unsigned int n_q_points_total
Definition utils.h:2023
const Triangulation< dim > & get_triangulation() const
Definition utils.h:1432
EnableObserverPointer Subscriptor
#define DEAL_II_NOT_IMPLEMENTED()
unsigned int level
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrow(cond, exc)
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
typename ActiveSelector::active_cell_iterator active_cell_iterator
void make_flux_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern)
update_values
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_handler_index=0, const unsigned int quadrature_index=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)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
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:2141
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:2174
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:2191
types::global_cell_index get_index(const std::vector< types::global_cell_index > &v, const types::global_cell_index index)
Definition utils.h:2131
constexpr 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
UpdateFlags mapping_update_flags
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