39template <
int dim,
typename RtreeType>
52 return (
pow >=
sizeof(
unsigned int) * 8) ? 0 :
65 std::vector<types::global_cell_index>
nodes;
66 std::vector<std::vector<types::global_cell_index>>
adjacency;
71 std::cout <<
"Graph information" << std::endl;
72 for (
const auto &node :
nodes)
74 std::cout <<
"Neighbors for node " << node << std::endl;
75 for (
const auto &neigh_node :
adjacency[node])
76 std::cout << neigh_node << std::endl;
95 template <
int dim,
int spacedim,
typename MatrixType>
102 using NumberType =
typename MatrixType::value_type;
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)
116 "The destination matrix and its sparsity pattern must the empty "
117 "upon calling this function."));
132 const IndexSet &locally_owned_dofs_fine =
134 const IndexSet locally_relevant_dofs_fine =
137 const IndexSet &locally_owned_dofs_coarse =
140 std::conditional_t<is_trilinos_matrix,
145 if constexpr (is_trilinos_matrix)
146 dsp.
reinit(locally_owned_dofs_fine,
147 locally_owned_dofs_coarse,
150 dsp.reinit(fine_agglo_dh.
n_dofs(),
152 locally_relevant_dofs_fine);
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);
159 const std::vector<Point<dim>> &unit_support_points =
167 std::vector<types::global_dof_index> local_dof_indices_coarse(
169 std::vector<types::global_dof_index> local_dof_indices_child(dofs_per_cell);
172 if (polytope->is_locally_owned())
174 polytope->get_dof_indices(local_dof_indices_coarse);
177 const auto &children_polytopes = polytope->children();
182 child_dh->get_dof_indices(local_dof_indices_child);
183 for (
const auto row : local_dof_indices_child)
185 local_dof_indices_coarse.begin(),
186 local_dof_indices_coarse.end());
190 const auto assemble_injection_matrix = [&]() {
192 std::vector<Point<dim>> reference_q_points(dofs_per_cell);
199 if (polytope->is_locally_owned())
201 polytope->get_dof_indices(local_dof_indices_coarse);
203 coarse_bboxes[polytope->index()];
206 const auto &children_polytopes = polytope->children();
212 child_dh->get_dof_indices(local_dof_indices_child);
217 std::vector<Point<dim>> real_qpoints;
218 real_qpoints.reserve(unit_support_points.size());
219 for (
const Point<dim> &p : unit_support_points)
222 for (
unsigned int i = 0; i < local_dof_indices_coarse.size();
225 const auto &p = coarse_bbox.
real_to_unit(real_qpoints[i]);
226 for (
unsigned int j = 0; j < local_dof_indices_child.size();
234 local_dof_indices_child,
235 local_dof_indices_coarse,
242 if constexpr (is_trilinos_matrix)
246 assemble_injection_matrix();
248 else if constexpr (is_serial_matrix)
252 assemble_injection_matrix();
263 "This injection does not support PETSc types."));
286 template <
typename VectorType,
typename MatrixType,
typename SolverType>
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());
305 if constexpr (is_serial_matrix)
308 std::is_same_v<VectorType,
309 dealii::Vector<typename MatrixType::value_type>>;
312 else if constexpr (is_trilinos_matrix)
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());
337 const VectorType &src)
const override
364 typename number =
double>
427 *
data.get_dof_info(0).vector_partitioner))
430 src_copy.
reinit(
data.get_dof_info().vector_partitioner);
436 *
data.get_dof_info(0).vector_partitioner))
439 dst_copy.
reinit(
data.get_dof_info().vector_partitioner);
455 return data.get_vector_partitioner()->size();
461 return data.get_vector_partitioner()->size();
465 el(
const unsigned int row,
const unsigned int col)
const
470 ExcMessage(
"Matrix-free does not allow for entry access"));
478 data.initialize_dof_vector(vector);
485 return data.get_dof_handler();
515 const auto cell_operation = [&](
auto &phi) {
517 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
518 phi.submit_gradient(phi.get_gradient(q), q);
522 const auto face_operation = [&](
auto &phi_m,
auto &phi_p) {
528 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
530 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
533 for (
unsigned int q = 0; q < phi_m.n_q_points; ++q)
536 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
538 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
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);
550 const auto boundary_operation = [&](
auto &phi_m) {
554 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
557 for (
unsigned int q = 0; q < phi_m.n_q_points; ++q)
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);
578 const auto &dof_handler =
data.get_dof_handler();
582 dof_handler.locally_owned_mg_dofs(
data.get_mg_level()) :
583 dof_handler.locally_owned_dofs(),
584 data.get_task_info().communicator);
623 const auto cell_operation = [&](
auto &phi) {
625 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
626 phi.submit_gradient(phi.get_gradient(q), q);
630 const auto face_operation = [&](
auto &phi_m,
auto &phi_p) {
636 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) +
638 (phi_m.normal_vector(0) * phi_p.inverse_jacobian(0))[dim - 1])) *
641 for (
unsigned int q = 0; q < phi_m.n_q_points; ++q)
644 (phi_m.get_value(q) - phi_p.get_value(q)) * 0.5;
646 phi_m.get_normal_derivative(q) + phi_p.get_normal_derivative(q);
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);
658 const auto boundary_operation = [&](
auto &phi_m) {
662 (phi_m.normal_vector(0) * phi_m.inverse_jacobian(0))[dim - 1]) *
665 for (
unsigned int q = 0; q < phi_m.n_q_points; ++q)
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);
689 const IndexSet system_relevant_set =
695 system_relevant_set);
701 data.get_task_info().communicator,
702 system_relevant_set);
703 mg_matrix.
reinit(system_partitioning,
705 data.get_task_info().communicator);
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,
733 for (
unsigned int cell = cells.first; cell < cells.second; ++cell)
736 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
738 if constexpr (n_components == 1)
740 phi.submit_value(1.0, q);
745 for (
unsigned int v = 0;
746 v < VectorizedArray<number>::size();
749 for (
unsigned int i = 0; i < n_components; i++)
752 phi.submit_value(temp, q);
770 unsigned int dummy = 0;
778 for (
unsigned int i = 0;
792 const std::pair<unsigned int, unsigned int> &cell_range)
const
796 for (
unsigned int cell = cell_range.first; cell < cell_range.second;
800 phi.read_dof_values(src);
802 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
803 phi.submit_gradient(phi.get_gradient(q), q);
805 phi.distribute_local_to_global(dst);
814 const std::pair<unsigned int, unsigned int> &face_range)
const
819 for (
unsigned int face = face_range.first; face < face_range.second;
822 fe_eval.reinit(face);
823 fe_eval_neighbor.reinit(face);
825 fe_eval.read_dof_values(src);
828 fe_eval_neighbor.read_dof_values(src);
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])) *
838 for (
unsigned int q = 0; q < fe_eval.n_q_points; ++q)
841 (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
843 fe_eval.get_normal_derivative(q) +
844 fe_eval_neighbor.get_normal_derivative(q);
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);
854 fe_eval.distribute_local_to_global(dst);
857 fe_eval_neighbor.distribute_local_to_global(dst);
866 const std::pair<unsigned int, unsigned int> &face_range)
const
869 for (
unsigned int face = face_range.first; face < face_range.second;
872 fe_eval.reinit(face);
873 fe_eval.read_dof_values(src);
877 std::abs((fe_eval.normal_vector(0) *
878 fe_eval.inverse_jacobian(0))[dim - 1]) *
881 for (
unsigned int q = 0; q < fe_eval.n_q_points; ++q)
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);
893 fe_eval.distribute_local_to_global(dst);
902 const unsigned int &,
903 const std::pair<unsigned int, unsigned int> &cell_range)
const
909 for (
unsigned int cell = cell_range.first; cell < cell_range.second;
914 for (
unsigned int i = 0; i < phi.dofs_per_cell; ++i)
916 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
918 phi.begin_dof_values()[i] = 1.;
920 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
921 phi.submit_gradient(phi.get_gradient(q), q);
923 local_diagonal_vector[i] = phi.begin_dof_values()[i];
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);
935 const unsigned int &,
936 const std::pair<unsigned int, unsigned int> &face_range)
const
943 for (
unsigned int face = face_range.first; face < face_range.second;
947 phi_outer.reinit(face);
951 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
953 phi_outer.inverse_jacobian(0))[dim - 1])) *
957 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
961 for (
unsigned int i = 0; i < phi.dofs_per_cell; ++i)
963 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
965 phi.begin_dof_values()[i] = 1.;
969 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
972 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
974 phi.get_normal_derivative(q) +
975 phi_outer.get_normal_derivative(q);
977 average_value * 2. * sigmaF - average_valgrad * 0.5;
978 phi.submit_normal_derivative(-average_value, q);
979 phi.submit_value(average_valgrad, q);
983 local_diagonal_vector[i] = phi.begin_dof_values()[i];
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);
990 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
993 for (
unsigned int i = 0; i < phi.dofs_per_cell; ++i)
995 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
997 phi_outer.begin_dof_values()[i] = 1.;
1001 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
1004 (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
1006 phi.get_normal_derivative(q) +
1007 phi_outer.get_normal_derivative(q);
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);
1015 local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
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);
1027 const unsigned int &,
1028 const std::pair<unsigned int, unsigned int> &face_range)
const
1034 for (
unsigned int face = face_range.first; face < face_range.second;
1041 (phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) *
1044 for (
unsigned int i = 0; i < phi.dofs_per_cell; ++i)
1046 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
1048 phi.begin_dof_values()[i] = 1.;
1052 for (
unsigned int q = 0; q < phi.n_q_points; ++q)
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);
1064 local_diagonal_vector[i] = phi.begin_dof_values()[i];
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);
1090 return std::distance(v.begin(), std::find(v.begin(), v.end(), index));
1101 Assert(cells.size() > 0, ExcMessage(
"No cells to be agglomerated."));
1102 const unsigned int n_faces = cells[0]->n_faces();
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();
1109 for (
const auto &cell : cells)
1115 g.
nodes.push_back(
get_index(vec_cells, cell->active_cell_index()));
1116 for (
unsigned int f = 0; f < n_faces; ++f)
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))
1122 .push_back(
get_index(vec_cells, neigh->active_cell_index()));
1130 dfs(std::vector<types::global_cell_index> &comp,
1131 std::vector<bool> &visited,
1140 dfs(comp, visited, g, u);
1149 std::vector<std::vector<types::global_cell_index>> &connected_components)
1151 Assert(g.
nodes.size() > 0, ExcMessage(
"No nodes in this graph."));
1153 connected_components.size() == 0,
1155 "Connected components have to be computed by the present function."));
1157 std::vector<bool> visited(g.
nodes.size());
1158 std::fill(visited.begin(), visited.end(), 0);
1165 connected_components.emplace_back();
1166 dfs(connected_components.back(), visited, g, v);
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 zero_out_ghost_values() 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)
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
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
const DoFHandler< dim > & get_dof_handler() const
const LinearAlgebra::distributed::Vector< number > & get_matrix_diagonal_inverse() const
types::global_dof_index m() const
void vmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
LinearAlgebra::distributed::Vector< number > inverse_diagonal_entries
TrilinosWrappers::SparseMatrix system_matrix
MatrixFree< dim, number > data
void get_system_matrix(TrilinosWrappers::SparseMatrix &mg_matrix) const
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
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
void rhs(LinearAlgebra::distributed::Vector< number > &b) const
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
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
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
types::global_dof_index n() const
void reinit(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const unsigned int level=numbers::invalid_unsigned_int)
void Tvmult(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
number el(const unsigned int row, const unsigned int col) const
const MatrixFree< dim, number > * get_matrix_free() const
void vmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
void Tvmult_add(LinearAlgebra::distributed::Vector< number > &dst, const LinearAlgebra::distributed::Vector< number > &src) const
AffineConstraints< number > constraints
void initialize_dof_vector(LinearAlgebra::distributed::Vector< number > &vector) const
void compute_inverse_diagonal()
const TrilinosWrappers::SparseMatrix & get_system_matrix() const
~MGCoarseDirect()=default
const MatrixType & coarse_matrix
MGCoarseDirect(const MatrixType &matrix)
void operator()(const unsigned int, VectorType &dst, const VectorType &src) const override
#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)
Expression pow(const Expression &base, const Expression &exponent)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
void create_graph_from_agglomerate(const std::vector< typename Triangulation< dim >::active_cell_iterator > &cells, Graph &g)
void dfs(std::vector< types::global_cell_index > &comp, std::vector< bool > &visited, const Graph &g, const types::global_cell_index v)
constexpr T constexpr_pow(T num, unsigned int pow)
void fill_injection_matrix(const AgglomerationHandler< dim, spacedim > &coarse_ah, const AgglomerationHandler< dim, spacedim > &fine_ah, SparsityPattern &sp, MatrixType &matrix)
void compute_connected_components(Graph &g, std::vector< std::vector< types::global_cell_index > > &connected_components)
types::global_cell_index get_index(const std::vector< types::global_cell_index > &v, const types::global_cell_index index)
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
unsigned int tasks_block_size
std::vector< std::vector< types::global_cell_index > > adjacency
std::vector< types::global_cell_index > nodes