/**
* The mg_constrained_dofs of the level systems.
*/
- SmartPointer<const MGConstrainedDoFs, MGLevelGlobalTransfer<VectorType>>
- mg_constrained_dofs;
+ SmartPointer<const MGConstrainedDoFs> mg_constrained_dofs;
private:
/**
/**
* The mg_constrained_dofs of the level systems.
*/
- SmartPointer<
- const MGConstrainedDoFs,
- MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number>>>
- mg_constrained_dofs;
+ SmartPointer<const MGConstrainedDoFs> mg_constrained_dofs;
/**
* In the function copy_to_mg, we need to access ghosted entries of the
*/
bool fine_element_is_continuous;
+public:
/**
* Partitioner needed by the intermediate vector.
*/
*/
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
+protected:
/**
* Internal vector needed for collecting all degrees of freedom of the fine
* cells. It is only initialized if the fine-level DoF indices touch DoFs
*
* The implementation of this class is explained in detail in @cite munch2022gc.
*/
-template <int dim, typename VectorType>
-class MGTransferGlobalCoarsening : public dealii::MGTransferBase<VectorType>
+template <int dim, typename Number>
+class MGTransferMF : public dealii::MGLevelGlobalTransfer<
+ LinearAlgebra::distributed::Vector<Number>>
{
public:
/**
* Value type.
*/
- using Number = typename VectorType::value_type;
+ using VectorType = LinearAlgebra::distributed::Vector<Number>;
/**
* Default constructor.
+ *
+ * @note See also MGTransferMatrixFree.
*/
- MGTransferGlobalCoarsening() = default;
+ MGTransferMF() = default;
/**
* @name Global coarsening.
* std::unique_ptr to the actual transfer operator.
*/
template <typename MGTwoLevelTransferObject>
- MGTransferGlobalCoarsening(
- const MGLevelObject<MGTwoLevelTransferObject> &transfer,
- const std::function<void(const unsigned int, VectorType &)>
- &initialize_dof_vector = {});
+ MGTransferMF(const MGLevelObject<MGTwoLevelTransferObject> &transfer,
+ const std::function<void(const unsigned int, VectorType &)>
+ &initialize_dof_vector = {});
/**
* Set two-level transfers.
*
* @note See also MGTransferMatrixFree.
*/
- MGTransferGlobalCoarsening(const MGConstrainedDoFs &mg_constrained_dofs);
+ MGTransferMF(const MGConstrainedDoFs &mg_constrained_dofs);
/**
* Initialize the constraints to be used in build().
/**
* Like the above function but with a user-provided DoFHandler as
* additional argument. However, this DoFHandler is not used internally, but
- * is required to be able to use MGTransferGlobalCoarsening and
+ * is required to be able to use MGTransferMF and
* MGTransferMatrixFree as template argument.
*/
template <class InVector>
unsigned int
max_level() const;
+ /**
+ * Clear all data fields and brings the class into a condition similar
+ * to after having called the default constructor.
+ */
+ void
+ clear();
+
/** @} */
private:
/**
* Function to initialize internal level vectors.
*/
+ template <class InVector>
void
- initialize_dof_vector(const unsigned int level, VectorType &vector) const;
-
- /**
- * MGConstrainedDoFs passed during build().
- *
- * @note See also MGTransferMatrixFree.
- */
- SmartPointer<const MGConstrainedDoFs> mg_constrained_dofs;
+ initialize_dof_vector(const unsigned int level,
+ VectorType & vector,
+ const InVector & vector_reference,
+ const bool omit_zeroing_entries) const;
/**
* Internal transfer operator.
/**
* This class works with LinearAlgebra::distributed::BlockVector and
* performs exactly the same transfer operations for each block as
- * MGTransferGlobalCoarsening.
+ * MGTransferMF.
*/
-template <int dim, typename VectorType>
-class MGTransferBlockGlobalCoarsening
- : public MGTransferBlockMatrixFreeBase<
- dim,
- typename VectorType::value_type,
- MGTransferGlobalCoarsening<dim, VectorType>>
+template <int dim, typename Number>
+class MGTransferBlockMF
+ : public MGTransferBlockMatrixFreeBase<dim, Number, MGTransferMF<dim, Number>>
{
public:
/**
* Constructor.
*/
- MGTransferBlockGlobalCoarsening(
- const MGTransferGlobalCoarsening<dim, VectorType> &transfer_operator);
+ MGTransferBlockMF(const MGTransferMF<dim, Number> &transfer_operator);
+
+ /**
+ * Constructor.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ MGTransferBlockMF() = default;
+
+ /**
+ * Constructor.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ MGTransferBlockMF(const MGConstrainedDoFs &mg_constrained_dofs);
+
+ /**
+ * Constructor.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ MGTransferBlockMF(const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
+
+ /**
+ * Initialize the constraints to be used in build().
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ void
+ initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs);
+
+ /**
+ * Same as above for the case that each block has its own DoFHandler.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ void
+ initialize_constraints(
+ const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
+
+ /**
+ * Actually build the information for the prolongation for each level.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ void
+ build(const DoFHandler<dim> &dof_handler);
+
+ /**
+ * Same as above for the case that each block has its own DoFHandler.
+ *
+ * @note See also MGTransferBlockMatrixFree.
+ */
+ void
+ build(const std::vector<const DoFHandler<dim> *> &dof_handler);
protected:
- const MGTransferGlobalCoarsening<dim, VectorType> &
+ const MGTransferMF<dim, Number> &
get_matrix_free_transfer(const unsigned int b) const override;
private:
+ /**
+ * Internal non-block version of transfer operation.
+ */
+ std::vector<MGTransferMF<dim, Number>> transfer_operators_internal;
+
/**
* Non-block version of transfer operation.
*/
- const MGTransferGlobalCoarsening<dim, VectorType> &transfer_operator;
+ std::vector<SmartPointer<const MGTransferMF<dim, Number>>> transfer_operators;
};
+template <int dim, typename VectorType>
+using MGTransferGlobalCoarsening =
+ MGTransferMF<dim, typename VectorType::value_type>;
+
+template <int dim, typename VectorType>
+using MGTransferBlockGlobalCoarsening =
+ MGTransferBlockMF<dim, typename VectorType::value_type>;
+
+
+
#ifndef DOXYGEN
/* ----------------------- Inline functions --------------------------------- */
-template <int dim, typename VectorType>
+template <int dim, typename Number>
template <typename MGTwoLevelTransferObject>
-MGTransferGlobalCoarsening<dim, VectorType>::MGTransferGlobalCoarsening(
+MGTransferMF<dim, Number>::MGTransferMF(
const MGLevelObject<MGTwoLevelTransferObject> &transfer,
const std::function<void(const unsigned int, VectorType &)>
&initialize_dof_vector)
-template <int dim, typename VectorType>
-MGTransferGlobalCoarsening<dim, VectorType>::MGTransferGlobalCoarsening(
- const MGConstrainedDoFs &mg_constrained_dofs)
-{
- this->initialize_constraints(mg_constrained_dofs);
-}
-
-
-
-template <int dim, typename VectorType>
+template <int dim, typename Number>
template <typename MGTwoLevelTransferObject>
void
-MGTransferGlobalCoarsening<dim, VectorType>::intitialize_two_level_transfers(
+MGTransferMF<dim, Number>::intitialize_two_level_transfers(
const MGLevelObject<MGTwoLevelTransferObject> &transfer)
{
this->intitialize_transfer_references(transfer);
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::initialize_constraints(
- const MGConstrainedDoFs &mg_constrained_dofs)
-{
- this->mg_constrained_dofs = &mg_constrained_dofs;
-}
-
-
-
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::intitialize_internal_transfer(
- const DoFHandler<dim> & dof_handler,
- const SmartPointer<const MGConstrainedDoFs> &mg_constrained_dofs)
-{
- const unsigned int min_level = 0;
- const unsigned int max_level =
- dof_handler.get_triangulation().n_global_levels() - 1;
-
- MGLevelObject<AffineConstraints<typename VectorType::value_type>> constraints(
- min_level, max_level);
-
- if (mg_constrained_dofs)
- for (unsigned int l = min_level; l <= max_level; ++l)
- mg_constrained_dofs->merge_constraints(
- constraints[l],
- l,
- /*add_boundary_indices*/ true,
- /*add_refinement_edge_indices*/ false,
- /*add_level_constraints*/ true,
- /*add_user_constraints*/ true);
-
- this->internal_transfer.resize(min_level, max_level);
-
- for (unsigned int l = min_level; l < max_level; ++l)
- internal_transfer[l + 1].reinit_geometric_transfer(
- dof_handler, dof_handler, constraints[l + 1], constraints[l], l + 1, l);
-}
-
-
-
-template <int dim, typename VectorType>
+template <int dim, typename Number>
template <typename MGTwoLevelTransferObject>
void
-MGTransferGlobalCoarsening<dim, VectorType>::intitialize_transfer_references(
+MGTransferMF<dim, Number>::intitialize_transfer_references(
const MGLevelObject<MGTwoLevelTransferObject> &transfer)
{
const unsigned int min_level = transfer.min_level();
-template <int dim, typename VectorType>
+template <int dim, typename Number>
+template <class InVector>
void
-MGTransferGlobalCoarsening<dim, VectorType>::build(
- const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
- &external_partitioners)
+MGTransferMF<dim, Number>::initialize_dof_vector(
+ const unsigned int level,
+ VectorType & vec,
+ const InVector & vec_reference,
+ const bool omit_zeroing_entries) const
{
- this->external_partitioners = external_partitioners;
+ std::shared_ptr<const Utilities::MPI::Partitioner> partitioner;
- if (this->external_partitioners.size() > 0)
+ if (external_partitioners.empty())
{
- const unsigned int min_level = transfer.min_level();
- const unsigned int max_level = transfer.max_level();
-
- AssertDimension(this->external_partitioners.size(), transfer.n_levels());
-
- for (unsigned int l = min_level + 1; l <= max_level; ++l)
- transfer[l]->enable_inplace_operations_if_possible(
- this->external_partitioners[l - 1 - min_level],
- this->external_partitioners[l - min_level]);
+ partitioner = vec_reference.get_partitioner();
}
-}
-
-
-
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::build(
- const std::function<void(const unsigned int, VectorType &)>
- &initialize_dof_vector)
-{
- if (initialize_dof_vector)
+ else
{
- const unsigned int min_level = transfer.min_level();
- const unsigned int max_level = transfer.max_level();
- const unsigned int n_levels = transfer.n_levels();
+ Assert(transfer.min_level() <= level && level <= transfer.max_level(),
+ ExcInternalError());
- std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
- external_partitioners(n_levels);
+ partitioner = external_partitioners[level - transfer.min_level()];
+ }
- for (unsigned int l = min_level; l <= max_level; ++l)
- {
- LinearAlgebra::distributed::Vector<typename VectorType::value_type>
- vector;
- initialize_dof_vector(l, vector);
- external_partitioners[l - min_level] = vector.get_partitioner();
- }
+ // check if vectors are already correctly initalized
- this->build(external_partitioners);
- }
- else
+ // yes: same partitioners are used
+ if (vec.get_partitioner().get() == partitioner.get())
{
- this->build();
+ if (omit_zeroing_entries == false)
+ vec = 0;
+ return; // nothing to do
}
-}
-
+ // yes: vectors are compatible
+ if (vec.size() == partitioner->size() &&
+ vec.locally_owned_size() == partitioner->locally_owned_size())
+ {
+ if (omit_zeroing_entries == false)
+ vec = 0;
+ return; // nothing to do
+ }
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::build(
- const DoFHandler<dim> &dof_handler,
- const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
- &external_partitioners)
-{
- this->intitialize_internal_transfer(dof_handler, mg_constrained_dofs);
- this->intitialize_transfer_references(internal_transfer);
- this->build(external_partitioners);
+ // no
+ vec.reinit(partitioner, omit_zeroing_entries);
}
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::build(
- const DoFHandler<dim> &dof_handler,
- const std::function<void(const unsigned int, VectorType &)>
- &initialize_dof_vector)
-{
- this->intitialize_internal_transfer(dof_handler, mg_constrained_dofs);
- this->intitialize_transfer_references(internal_transfer);
- this->build(initialize_dof_vector);
-}
-
-
-
-template <int dim, typename VectorType>
+template <int dim, typename Number>
+template <class InVector>
void
-MGTransferGlobalCoarsening<dim, VectorType>::initialize_dof_vector(
- const unsigned int level,
- VectorType & vec) const
+MGTransferMF<dim, Number>::copy_to_mg(const DoFHandler<dim> & dof_handler,
+ MGLevelObject<VectorType> &dst,
+ const InVector & src) const
{
- AssertDimension(transfer.n_levels(), external_partitioners.size());
- AssertIndexRange(level, transfer.max_level() + 1);
-
- const auto &external_partitioner =
- external_partitioners[level - transfer.min_level()];
-
- if (vec.get_partitioner().get() != external_partitioner.get())
- vec.reinit(external_partitioner);
-}
+ (void)dof_handler;
+ for (unsigned int level = dst.min_level(); level <= dst.max_level(); ++level)
+ {
+ const bool zero_out_values =
+ (this->perform_plain_copy == false &&
+ this->perform_renumbered_plain_copy == false) ||
+ level != dst.max_level();
+ this->initialize_dof_vector(level, dst[level], src, !zero_out_values);
+ }
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::prolongate(
- const unsigned int to_level,
- VectorType & dst,
- const VectorType & src) const
-{
- dst = 0;
- prolongate_and_add(to_level, dst, src);
-}
+ if (this->perform_plain_copy)
+ {
+ dst[dst.max_level()].copy_locally_owned_data_from(src);
+ }
+ else if (this->perform_renumbered_plain_copy)
+ {
+ auto &dst_level = dst[dst.max_level()];
+ for (unsigned int i = 0; i < this->copy_indices.back().n_cols(); ++i)
+ dst_level.local_element(this->copy_indices.back()(1, i)) =
+ src.local_element(i);
+ }
+ else
+ {
+ this->ghosted_global_vector = src;
+ this->ghosted_global_vector.update_ghost_values();
+ for (unsigned int l = dst.max_level() + 1; l != dst.min_level();)
+ {
+ --l;
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::prolongate_and_add(
- const unsigned int to_level,
- VectorType & dst,
- const VectorType & src) const
-{
- this->transfer[to_level]->prolongate_and_add(dst, src);
-}
+ auto &dst_level = dst[l];
+ const auto copy_unknowns = [&](const auto &indices) {
+ for (unsigned int i = 0; i < indices.n_cols(); ++i)
+ dst_level.local_element(indices(1, i)) =
+ this->ghosted_global_vector.local_element(indices(0, i));
+ };
+ copy_unknowns(this->copy_indices[l]);
+ copy_unknowns(this->copy_indices_level_mine[l]);
-template <int dim, typename VectorType>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::restrict_and_add(
- const unsigned int from_level,
- VectorType & dst,
- const VectorType & src) const
-{
- this->transfer[from_level]->restrict_and_add(dst, src);
+ dst_level.compress(VectorOperation::insert);
+ }
+ }
}
-template <int dim, typename VectorType>
-template <class InVector>
+template <int dim, typename Number>
+template <class OutVector>
void
-MGTransferGlobalCoarsening<dim, VectorType>::copy_to_mg(
- const DoFHandler<dim> & dof_handler,
- MGLevelObject<VectorType> &dst,
- const InVector & src) const
+MGTransferMF<dim, Number>::copy_from_mg(
+ const DoFHandler<dim> & dof_handler,
+ OutVector & dst,
+ const MGLevelObject<VectorType> &src) const
{
(void)dof_handler;
- for (unsigned int level = dst.min_level(); level <= dst.max_level(); ++level)
+ if (this->perform_plain_copy)
{
- initialize_dof_vector(level, dst[level]);
-
- if (level == dst.max_level())
- dst[level].copy_locally_owned_data_from(src);
- else
- dst[level] = 0.0;
+ dst.zero_out_ghost_values();
+ dst.copy_locally_owned_data_from(src[src.max_level()]);
}
-}
+ else if (this->perform_renumbered_plain_copy)
+ {
+ const auto &src_level = src[src.max_level()];
+ dst.zero_out_ghost_values();
+ for (unsigned int i = 0; i < this->copy_indices.back().n_cols(); ++i)
+ dst.local_element(i) =
+ src_level.local_element(this->copy_indices.back()(1, i));
+ }
+ else
+ {
+ dst = 0;
+ for (unsigned int l = src.min_level(); l <= src.max_level(); ++l)
+ {
+ auto &ghosted_vector = this->ghosted_level_vector[l];
+ if (this->ghosted_level_vector[l].size() > 0)
+ ghosted_vector = src[l];
+ const auto *const ghosted_vector_ptr =
+ (this->ghosted_level_vector[l].size() > 0) ? &ghosted_vector :
+ &src[l];
-template <int dim, typename VectorType>
-template <class OutVector>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::copy_from_mg(
- const DoFHandler<dim> & dof_handler,
- OutVector & dst,
- const MGLevelObject<VectorType> &src) const
-{
- (void)dof_handler;
+ ghosted_vector_ptr->update_ghost_values();
+
+ const auto copy_unknowns = [&](const auto &indices) {
+ for (unsigned int i = 0; i < indices.n_cols(); ++i)
+ dst.local_element(indices(0, i)) =
+ ghosted_vector_ptr->local_element(indices(1, i));
+ };
- dst.copy_locally_owned_data_from(src[src.max_level()]);
+ copy_unknowns(this->copy_indices[l]);
+ copy_unknowns(this->copy_indices_global_mine[l]);
+ }
+ dst.compress(VectorOperation::insert);
+ }
}
-template <int dim, typename VectorType>
+template <int dim, typename Number>
template <class InVector>
void
-MGTransferGlobalCoarsening<dim, VectorType>::interpolate_to_mg(
- MGLevelObject<VectorType> &dst,
- const InVector & src) const
+MGTransferMF<dim, Number>::interpolate_to_mg(MGLevelObject<VectorType> &dst,
+ const InVector &src) const
{
const unsigned int min_level = transfer.min_level();
const unsigned int max_level = transfer.max_level();
AssertDimension(max_level, dst.max_level());
for (unsigned int level = min_level; level <= max_level; ++level)
- initialize_dof_vector(level, dst[level]);
-
- dst[transfer.max_level()].copy_locally_owned_data_from(src);
-
- for (unsigned int l = max_level; l > min_level; --l)
- this->transfer[l]->interpolate(dst[l - 1], dst[l]);
-}
+ {
+ const bool zero_out_values = false;
+ this->initialize_dof_vector(level, dst[level], src, !zero_out_values);
+ }
+ if (this->perform_plain_copy)
+ {
+ dst[max_level].copy_locally_owned_data_from(src);
+ for (unsigned int l = max_level; l > min_level; --l)
+ this->transfer[l]->interpolate(dst[l - 1], dst[l]);
+ }
+ else if (this->perform_renumbered_plain_copy)
+ {
+ auto &dst_level = dst[max_level];
-template <int dim, typename VectorType>
-template <class InVector>
-void
-MGTransferGlobalCoarsening<dim, VectorType>::interpolate_to_mg(
- const DoFHandler<dim> & dof_handler,
- MGLevelObject<VectorType> &dst,
- const InVector & src) const
-{
- (void)dof_handler;
+ for (unsigned int i = 0; i < this->solution_copy_indices.back().n_cols();
+ ++i)
+ dst_level.local_element(this->solution_copy_indices.back()(1, i)) =
+ src.local_element(i);
- this->interpolate_to_mg(dst, src);
-}
+ for (unsigned int l = max_level; l > min_level; --l)
+ this->transfer[l]->interpolate(dst[l - 1], dst[l]);
+ }
+ else
+ {
+ this->solution_ghosted_global_vector = src;
+ this->solution_ghosted_global_vector.update_ghost_values();
+ for (unsigned int l = max_level + 1; l != min_level;)
+ {
+ --l;
+ auto &dst_level = dst[l];
-template <int dim, typename VectorType>
-std::size_t
-MGTransferGlobalCoarsening<dim, VectorType>::memory_consumption() const
-{
- std::size_t size = 0;
+ const auto copy_unknowns = [&](const auto &indices) {
+ for (unsigned int i = 0; i < indices.n_cols(); ++i)
+ dst_level.local_element(indices(1, i)) =
+ this->solution_ghosted_global_vector.local_element(
+ indices(0, i));
+ };
- const unsigned int min_level = transfer.min_level();
- const unsigned int max_level = transfer.max_level();
+ copy_unknowns(this->solution_copy_indices[l]);
+ copy_unknowns(this->solution_copy_indices_level_mine[l]);
- for (unsigned int l = min_level + 1; l <= max_level; ++l)
- size += this->transfer[l]->memory_consumption();
+ dst_level.compress(VectorOperation::insert);
- return size;
+ if (l != min_level)
+ this->transfer[l]->interpolate(dst[l - 1], dst[l]);
+ }
+ }
}
-template <int dim, typename VectorType>
-inline unsigned int
-MGTransferGlobalCoarsening<dim, VectorType>::min_level() const
+template <int dim, typename Number>
+template <class InVector>
+void
+MGTransferMF<dim, Number>::interpolate_to_mg(const DoFHandler<dim> &dof_handler,
+ MGLevelObject<VectorType> &dst,
+ const InVector &src) const
{
- return transfer.min_level();
-}
-
-
+ (void)dof_handler;
-template <int dim, typename VectorType>
-inline unsigned int
-MGTransferGlobalCoarsening<dim, VectorType>::max_level() const
-{
- return transfer.max_level();
+ this->interpolate_to_mg(dst, src);
}
#endif
(mg_level_coarse + 1 == mg_level_fine),
ExcNotImplemented());
- if (mg_level_fine != numbers::invalid_unsigned_int)
- AssertIndexRange(mg_level_fine,
- MGTools::max_level_for_coarse_mesh(
- dof_handler_fine.get_triangulation()) +
- 1);
-
- if (mg_level_coarse != numbers::invalid_unsigned_int)
- AssertIndexRange(mg_level_coarse,
- MGTools::max_level_for_coarse_mesh(
- dof_handler_coarse.get_triangulation()) +
- 1);
+ // if (mg_level_fine != numbers::invalid_unsigned_int)
+ // AssertIndexRange(mg_level_fine,
+ // MGTools::max_level_for_coarse_mesh(
+ // dof_handler_fine.get_triangulation()) +
+ // 1);
+ //
+ // if (mg_level_coarse != numbers::invalid_unsigned_int)
+ // AssertIndexRange(mg_level_coarse,
+ // MGTools::max_level_for_coarse_mesh(
+ // dof_handler_coarse.get_triangulation()) +
+ // 1);
const GlobalCoarseningFineDoFHandlerView<dim> view(dof_handler_fine,
dof_handler_coarse,
-template <int dim, typename VectorType>
-MGTransferBlockGlobalCoarsening<dim, VectorType>::
- MGTransferBlockGlobalCoarsening(
- const MGTransferGlobalCoarsening<dim, VectorType> &transfer_operator)
- : MGTransferBlockMatrixFreeBase<dim,
- typename VectorType::value_type,
- MGTransferGlobalCoarsening<dim, VectorType>>(
- true)
- , transfer_operator(transfer_operator)
-{}
+template <int dim, typename Number>
+MGTransferMF<dim, Number>::MGTransferMF(
+ const MGConstrainedDoFs &mg_constrained_dofs)
+{
+ this->initialize_constraints(mg_constrained_dofs);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::initialize_constraints(
+ const MGConstrainedDoFs &mg_constrained_dofs)
+{
+ this->mg_constrained_dofs = &mg_constrained_dofs;
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::intitialize_internal_transfer(
+ const DoFHandler<dim> & dof_handler,
+ const SmartPointer<const MGConstrainedDoFs> &mg_constrained_dofs)
+{
+ const unsigned int min_level = 0;
+ const unsigned int max_level =
+ dof_handler.get_triangulation().n_global_levels() - 1;
+
+ MGLevelObject<AffineConstraints<typename VectorType::value_type>> constraints(
+ min_level, max_level);
+
+ if (mg_constrained_dofs)
+ for (unsigned int l = min_level; l <= max_level; ++l)
+ mg_constrained_dofs->merge_constraints(
+ constraints[l],
+ l,
+ /*add_boundary_indices*/ true,
+ /*add_refinement_edge_indices*/ false,
+ /*add_level_constraints*/ true,
+ /*add_user_constraints*/ true);
+
+ this->internal_transfer.resize(min_level, max_level);
+
+ for (unsigned int l = min_level; l < max_level; ++l)
+ internal_transfer[l + 1].reinit_geometric_transfer(
+ dof_handler, dof_handler, constraints[l + 1], constraints[l], l + 1, l);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::build(
+ const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
+ &external_partitioners)
+{
+ this->external_partitioners = external_partitioners;
+
+ if (this->external_partitioners.size() > 0)
+ {
+ const unsigned int min_level = transfer.min_level();
+ const unsigned int max_level = transfer.max_level();
+
+ AssertDimension(this->external_partitioners.size(), transfer.n_levels());
+
+ for (unsigned int l = min_level + 1; l <= max_level; ++l)
+ transfer[l]->enable_inplace_operations_if_possible(
+ this->external_partitioners[l - 1 - min_level],
+ this->external_partitioners[l - min_level]);
+ }
+ else
+ {
+ const unsigned int min_level = transfer.min_level();
+ const unsigned int max_level = transfer.max_level();
+
+ for (unsigned int l = min_level + 1; l <= max_level; ++l)
+ {
+ if (l == min_level + 1)
+ this->external_partitioners.push_back(
+ transfer[l]->partitioner_coarse);
+
+ this->external_partitioners.push_back(transfer[l]->partitioner_fine);
+ }
+ }
+
+ this->perform_plain_copy = true;
+ this->perform_renumbered_plain_copy = false;
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::build(
+ const std::function<void(const unsigned int, VectorType &)>
+ &initialize_dof_vector)
+{
+ if (initialize_dof_vector)
+ {
+ const unsigned int min_level = transfer.min_level();
+ const unsigned int max_level = transfer.max_level();
+ const unsigned int n_levels = transfer.n_levels();
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
+ external_partitioners(n_levels);
+
+ for (unsigned int l = min_level; l <= max_level; ++l)
+ {
+ LinearAlgebra::distributed::Vector<typename VectorType::value_type>
+ vector;
+ initialize_dof_vector(l, vector);
+ external_partitioners[l - min_level] = vector.get_partitioner();
+ }
+
+ this->build(external_partitioners);
+ }
+ else
+ {
+ this->build();
+ }
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::build(
+ const DoFHandler<dim> &dof_handler,
+ const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
+ &external_partitioners)
+{
+ this->intitialize_internal_transfer(dof_handler, this->mg_constrained_dofs);
+ this->intitialize_transfer_references(internal_transfer);
+ this->build(external_partitioners);
+ this->fill_and_communicate_copy_indices(dof_handler);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::build(
+ const DoFHandler<dim> &dof_handler,
+ const std::function<void(const unsigned int, VectorType &)>
+ &initialize_dof_vector)
+{
+ this->intitialize_internal_transfer(dof_handler, this->mg_constrained_dofs);
+ this->intitialize_transfer_references(internal_transfer);
+ this->build(initialize_dof_vector);
+ this->fill_and_communicate_copy_indices(dof_handler);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::prolongate(const unsigned int to_level,
+ VectorType & dst,
+ const VectorType & src) const
+{
+ dst = 0;
+ prolongate_and_add(to_level, dst, src);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::prolongate_and_add(const unsigned int to_level,
+ VectorType & dst,
+ const VectorType & src) const
+{
+ this->transfer[to_level]->prolongate_and_add(dst, src);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferMF<dim, Number>::restrict_and_add(const unsigned int from_level,
+ VectorType & dst,
+ const VectorType & src) const
+{
+ this->transfer[from_level]->restrict_and_add(dst, src);
+}
+
+
+
+template <int dim, typename Number>
+std::size_t
+MGTransferMF<dim, Number>::memory_consumption() const
+{
+ std::size_t size = 0;
+
+ const unsigned int min_level = transfer.min_level();
+ const unsigned int max_level = transfer.max_level();
+
+ for (unsigned int l = min_level + 1; l <= max_level; ++l)
+ size += this->transfer[l]->memory_consumption();
+
+ return size;
+}
+
+
+
+template <int dim, typename Number>
+inline unsigned int
+MGTransferMF<dim, Number>::min_level() const
+{
+ return transfer.min_level();
+}
+
+
+
+template <int dim, typename Number>
+inline unsigned int
+MGTransferMF<dim, Number>::max_level() const
+{
+ return transfer.max_level();
+}
+
+
+template <int dim, typename Number>
+inline void
+MGTransferMF<dim, Number>::clear()
+{
+ MGLevelGlobalTransfer<VectorType>::clear();
+
+ internal_transfer.clear();
+ transfer.clear();
+ external_partitioners.clear();
+}
+
+
+
+template <int dim, typename Number>
+MGTransferBlockMF<dim, Number>::MGTransferBlockMF(
+ const MGTransferMF<dim, Number> &transfer_operator)
+ : MGTransferBlockMatrixFreeBase<dim, Number, MGTransferMF<dim, Number>>(true)
+{
+ this->transfer_operators = {&transfer_operator};
+}
+
+
+
+template <int dim, typename Number>
+MGTransferBlockMF<dim, Number>::MGTransferBlockMF(
+ const MGConstrainedDoFs &mg_constrained_dofs)
+ : MGTransferBlockMatrixFreeBase<dim, Number, MGTransferMF<dim, Number>>(true)
+{
+ initialize_constraints(mg_constrained_dofs);
+}
+
+
+
+template <int dim, typename Number>
+MGTransferBlockMF<dim, Number>::MGTransferBlockMF(
+ const std::vector<MGConstrainedDoFs> &mg_constrained_dofs)
+ : MGTransferBlockMatrixFreeBase<dim, Number, MGTransferMF<dim, Number>>(false)
+{
+ initialize_constraints(mg_constrained_dofs);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferBlockMF<dim, Number>::initialize_constraints(
+ const MGConstrainedDoFs &mg_constrained_dofs)
+{
+ this->transfer_operators_internal.clear();
+ this->transfer_operators.clear();
+
+ Assert(this->same_for_all,
+ ExcMessage("This object was initialized with support for usage with "
+ "one DoFHandler for each block, but this method assumes "
+ "that the same DoFHandler is used for all the blocks!"));
+
+ this->transfer_operators_internal.emplace_back(mg_constrained_dofs);
+ this->transfer_operators = {&transfer_operators_internal.back()};
+}
-template <int dim, typename VectorType>
-const MGTransferGlobalCoarsening<dim, VectorType> &
-MGTransferBlockGlobalCoarsening<dim, VectorType>::get_matrix_free_transfer(
+template <int dim, typename Number>
+void
+MGTransferBlockMF<dim, Number>::initialize_constraints(
+ const std::vector<MGConstrainedDoFs> &mg_constrained_dofs)
+{
+ this->transfer_operators_internal.clear();
+ this->transfer_operators.clear();
+
+ Assert(!this->same_for_all,
+ ExcMessage("This object was initialized with support for using "
+ "the same DoFHandler for all the blocks, but this "
+ "method assumes that there is a separate DoFHandler "
+ "for each block!"));
+
+ for (const auto &dofs : mg_constrained_dofs)
+ this->transfer_operators_internal.emplace_back(dofs);
+
+ for (const auto &transfer : this->transfer_operators_internal)
+ this->transfer_operators.emplace_back(&transfer);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferBlockMF<dim, Number>::build(const DoFHandler<dim> &dof_handler)
+{
+ AssertDimension(transfer_operators.size(), 1);
+ this->transfer_operators_internal[0].build(dof_handler);
+}
+
+
+
+template <int dim, typename Number>
+void
+MGTransferBlockMF<dim, Number>::build(
+ const std::vector<const DoFHandler<dim> *> &dof_handler)
+{
+ AssertDimension(transfer_operators.size(), dof_handler.size());
+ AssertDimension(transfer_operators_internal.size(), dof_handler.size());
+
+ for (unsigned int i = 0; i < dof_handler.size(); ++i)
+ this->transfer_operators_internal[i].build(*dof_handler[i]);
+}
+
+
+
+template <int dim, typename Number>
+const MGTransferMF<dim, Number> &
+MGTransferBlockMF<dim, Number>::get_matrix_free_transfer(
const unsigned int b) const
{
- (void)b;
- AssertDimension(b, 0);
- return transfer_operator;
+ AssertIndexRange(b, transfer_operators.size());
+ return *transfer_operators[b];
}
namespace internal
template <int dim, int spacedim, typename Number>
void
fill_internal(
- const DoFHandler<dim, spacedim> &mg_dof,
- SmartPointer<
- const MGConstrainedDoFs,
- MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number>>>
- mg_constrained_dofs,
+ const DoFHandler<dim, spacedim> & mg_dof,
+ SmartPointer<const MGConstrainedDoFs> mg_constrained_dofs,
const MPI_Comm mpi_communicator,
const bool transfer_solution_vectors,
std::vector<Table<2, unsigned int>> & copy_indices,
template class MGTransferBlockMatrixFreeBase<
deal_II_dimension,
S1,
- MGTransferGlobalCoarsening<deal_II_dimension,
- LinearAlgebra::distributed::Vector<S1>>>;
- template class MGTransferBlockGlobalCoarsening<
- deal_II_dimension,
- LinearAlgebra::distributed::Vector<S1>>;
+ MGTransferMF<deal_II_dimension, S1>>;
+ template class MGTransferMF<deal_II_dimension, S1>;
+ template class MGTransferBlockMF<deal_II_dimension, S1>;
}
for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// test MGTransferMatrixFree<dim,Number>::interpolate_to_mg()
+// for a scalar field
+
+#include <deal.II/base/function.h>
+#include <deal.II/base/multithread_info.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/thread_management.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/mapping_q1.h>
+#include <deal.II/fe/mapping_q_eulerian.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/identity_matrix.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/sparse_matrix.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/vector_memory.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <iostream>
+#include <vector>
+
+#include "../tests.h"
+
+
+
+template <int dim>
+class SimpleField : public Function<dim>
+{
+public:
+ SimpleField()
+ : Function<dim>(1)
+ {}
+
+ double
+ value(const Point<dim> &p, const unsigned int component = 0) const
+ {
+ (void)component;
+ return p[0] * 2. + p[1] - 10.;
+ }
+};
+
+
+template <int dim,
+ int fe_degree = 2,
+ int n_q_points = fe_degree + 1,
+ typename NumberType = double,
+ typename LevelNumberType = NumberType>
+void
+test(const unsigned int n_glob_ref = 2, const unsigned int n_ref = 0)
+{
+ SimpleField<dim> function;
+
+ deallog << "dim=" << dim << std::endl;
+ MPI_Comm mpi_communicator(MPI_COMM_WORLD);
+ unsigned int myid = Utilities::MPI::this_mpi_process(mpi_communicator);
+ unsigned int numproc = Utilities::MPI::n_mpi_processes(mpi_communicator);
+
+ deallog << "numproc=" << numproc << std::endl;
+
+ parallel::distributed::Triangulation<dim> triangulation(
+ mpi_communicator,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(triangulation, 5, -1, 1);
+ // now do some refinement
+ triangulation.refine_global(n_glob_ref);
+ for (unsigned int ref = 0; ref < n_ref; ++ref)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ triangulation.begin_active();
+ cell != triangulation.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ triangulation.execute_coarsening_and_refinement();
+ }
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof_handler(triangulation);
+
+ dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs();
+
+ IndexSet locally_owned_dofs, locally_relevant_dofs;
+ locally_owned_dofs = dof_handler.locally_owned_dofs();
+ DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
+
+ // constraints:
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ constraints.close();
+
+
+ // interpolate:
+ LinearAlgebra::distributed::Vector<LevelNumberType> fine_projection;
+ fine_projection.reinit(locally_owned_dofs,
+ locally_relevant_dofs,
+ mpi_communicator);
+ VectorTools::project(dof_handler,
+ constraints,
+ QGauss<dim>(n_q_points + 2),
+ function,
+ fine_projection);
+ fine_projection.update_ghost_values();
+
+ // output for debug purposes:
+ if (false)
+ {
+ DataOut<dim> data_out;
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(fine_projection, "projection");
+
+ Vector<float> subdomain(triangulation.n_active_cells());
+ for (unsigned int i = 0; i < subdomain.size(); ++i)
+ subdomain(i) = triangulation.locally_owned_subdomain();
+ data_out.add_data_vector(subdomain, "subdomain");
+ data_out.build_patches();
+ const std::string filename =
+ "output_" + Utilities::int_to_string(myid) + ".vtu";
+ std::ofstream output(filename);
+ data_out.write_vtu(output);
+
+ const std::string mg_mesh = "mg_mesh";
+ GridOut grid_out;
+ grid_out.write_mesh_per_processor_as_vtu(triangulation,
+ mg_mesh,
+ true,
+ true);
+ }
+
+ // MG hanging node constraints
+ // we do not add extra zero Dirichlet BC here
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof_handler);
+
+ // MG transfer:
+ MGTransferMF<dim, LevelNumberType> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof_handler);
+
+ // now the core of the test:
+ const unsigned int max_level =
+ dof_handler.get_triangulation().n_global_levels() - 1;
+ const unsigned int min_level = 0;
+ MGLevelObject<LinearAlgebra::distributed::Vector<LevelNumberType>>
+ level_projection(min_level, max_level);
+ for (unsigned int level = min_level; level <= max_level; ++level)
+ {
+ IndexSet set;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler, level, set);
+ level_projection[level].reinit(dof_handler.locally_owned_mg_dofs(level),
+ set,
+ mpi_communicator);
+ }
+ mg_transfer.interpolate_to_mg(dof_handler, level_projection, fine_projection);
+
+ // now go through all GMG levels and make sure FE field can represent
+ // analytic function exactly:
+ QGauss<dim> quadrature(n_q_points);
+ std::vector<LevelNumberType> q_values(quadrature.size());
+
+ FEValues<dim> fe_values(fe,
+ quadrature,
+ update_values | update_quadrature_points);
+ for (unsigned int level = max_level + 1; level != min_level;)
+ {
+ --level;
+
+ level_projection[level].update_ghost_values();
+
+ std::vector<types::global_dof_index> dof_indices(fe.dofs_per_cell);
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level);
+ typename DoFHandler<dim>::cell_iterator endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ if (cell->is_locally_owned_on_level())
+ {
+ fe_values.reinit(cell);
+ cell->get_mg_dof_indices(dof_indices);
+ fe_values.get_function_values(level_projection[level],
+ dof_indices,
+ q_values);
+
+ const std::vector<Point<dim>> &q_points =
+ fe_values.get_quadrature_points();
+
+ for (unsigned int q = 0; q < q_points.size(); ++q)
+ {
+ const double diff = q_values[q] - function.value(q_points[q]);
+ if (std::abs(diff) > 1e-10)
+ {
+ std::cout << "dofs: ";
+ for (const auto i : dof_indices)
+ std::cout << i << ' ';
+ std::cout << std::endl << "values: ";
+ std::vector<LevelNumberType> local_values(
+ dof_indices.size());
+ level_projection[level].extract_subvector_to(dof_indices,
+ local_values);
+ for (const auto v : local_values)
+ std::cout << v << ' ';
+ std::cout << std::endl
+ << "val(q)=" << q_values[q] << std::endl;
+ std::cout << "MGTransfer indices:" << std::endl;
+ mg_transfer.print_indices(std::cout);
+ AssertThrow(false,
+ ExcMessage("Level " + std::to_string(level) +
+ " Diff " + std::to_string(diff) +
+ " center_x " +
+ std::to_string(cell->center()[0]) +
+ " center_y " +
+ std::to_string(cell->center()[1])));
+ }
+ }
+ }
+ }
+
+ deallog << "Ok" << std::endl;
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+ MPILogInitAll log;
+
+ test<2>();
+ test<2, 1>(0, 1);
+}
--- /dev/null
+
+DEAL:0::dim=2
+DEAL:0::numproc=1
+DEAL:0::Ok
+DEAL:0::dim=2
+DEAL:0::numproc=1
+DEAL:0::Ok
--- /dev/null
+
+DEAL:0::dim=2
+DEAL:0::numproc=3
+DEAL:0::Ok
+DEAL:0::dim=2
+DEAL:0::numproc=3
+DEAL:0::Ok
+
+DEAL:1::dim=2
+DEAL:1::numproc=3
+DEAL:1::Ok
+DEAL:1::dim=2
+DEAL:1::numproc=3
+DEAL:1::Ok
+
+
+DEAL:2::dim=2
+DEAL:2::numproc=3
+DEAL:2::Ok
+DEAL:2::dim=2
+DEAL:2::numproc=3
+DEAL:2::Ok
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2021 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// test function MGTransferMatrixFree::interpolate_to_mg() for periodic
+// boundaries
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/mapping_q1.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+template <int dim>
+class RightHandSideFunction : public Function<dim>
+{
+public:
+ RightHandSideFunction(const unsigned int n_components)
+ : Function<dim>(n_components)
+ {}
+
+ virtual double
+ value(const Point<dim> &p, const unsigned int component = 0) const
+ {
+ return p[component % dim] * p[component % dim];
+ }
+};
+
+template <int dim>
+void
+test()
+{
+ const unsigned int fe_degree = 1;
+
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+
+ GridGenerator::hyper_cube(tria, -1., 1., true);
+
+ std::vector<GridTools::PeriodicFacePair<TriaIterator<CellAccessor<dim, dim>>>>
+ tria_matched_pairs;
+ GridTools::collect_periodic_faces(tria, 0, 1, 0, tria_matched_pairs);
+ tria.add_periodicity(tria_matched_pairs);
+ tria.refine_global(2);
+
+ const FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof_handler(tria);
+ dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs();
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
+
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+
+ std::vector<
+ GridTools::PeriodicFacePair<typename DoFHandler<dim>::cell_iterator>>
+ dof_matched_pairs;
+ GridTools::collect_periodic_faces(dof_handler, 0, 1, 0, dof_matched_pairs);
+ DoFTools::make_periodicity_constraints<dim, dim>(dof_matched_pairs,
+ constraints);
+ constraints.close();
+
+ LinearAlgebra::distributed::Vector<double> qsol(
+ dof_handler.locally_owned_dofs(), locally_relevant_dofs, MPI_COMM_WORLD);
+
+ VectorTools::interpolate(MappingQ1<dim>(),
+ dof_handler,
+ RightHandSideFunction<dim>(1),
+ qsol);
+
+ MGLevelObject<LinearAlgebra::distributed::Vector<double>> mg_qsol;
+ MGConstrainedDoFs mg_constrained_dofs;
+ MGTransferMF<dim, double> mg_transfer;
+
+ unsigned int n_tria_levels = tria.n_global_levels();
+ mg_qsol.resize(0, n_tria_levels - 1);
+
+ mg_constrained_dofs.initialize(dof_handler);
+ mg_transfer.initialize_constraints(mg_constrained_dofs);
+ mg_transfer.build(dof_handler);
+
+ mg_transfer.interpolate_to_mg(dof_handler, mg_qsol, qsol);
+
+ for (unsigned int i = mg_qsol.min_level(); i <= mg_qsol.max_level(); ++i)
+ deallog << mg_qsol[i].l2_norm() << std::endl;
+
+ deallog << "OK" << std::endl;
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+ Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+ MPILogInitAll all;
+
+ test<2>();
+}
--- /dev/null
+
+DEAL:0::2.00000
+DEAL:0::2.44949
+DEAL:0::3.25960
+DEAL:0::OK
+
+DEAL:1::2.00000
+DEAL:1::2.44949
+DEAL:1::3.25960
+DEAL:1::OK
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2006 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Test DataOut::add_mg_data_vector in parallel
+
+#include <deal.II/base/function_lib.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim>
+void
+do_test()
+{
+ parallel::distributed::Triangulation<dim> triangulation(
+ MPI_COMM_WORLD,
+ dealii::Triangulation<dim>::none,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+
+ GridGenerator::hyper_cube(triangulation);
+ triangulation.refine_global(1);
+ triangulation.begin_active()->set_refine_flag();
+ triangulation.execute_coarsening_and_refinement();
+
+ FE_Q<dim> fe(1);
+ DoFHandler<dim> dof_handler(triangulation);
+ dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs();
+
+ // Make FE vector
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
+
+ using VectorType = LinearAlgebra::distributed::Vector<double>;
+ VectorType global_dof_vector;
+ global_dof_vector.reinit(dof_handler.locally_owned_dofs(),
+ locally_relevant_dofs,
+ MPI_COMM_WORLD);
+
+ VectorTools::interpolate(dof_handler,
+ Functions::SquareFunction<dim>(),
+ global_dof_vector);
+ global_dof_vector.update_ghost_values();
+
+ {
+ DataOut<dim> data_out;
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(dof_handler,
+ global_dof_vector,
+ std::vector<std::string>(1, "data"));
+ data_out.build_patches(0);
+ data_out.write_gnuplot(deallog.get_file_stream());
+ data_out.write_vtu_in_parallel("base.vtu", MPI_COMM_WORLD);
+ }
+
+ {
+ MGLevelObject<VectorType> dof_vector(0,
+ triangulation.n_global_levels() - 1);
+ MGTransferMF<dim, typename VectorType::value_type> transfer;
+
+ transfer.build(dof_handler);
+ transfer.interpolate_to_mg(dof_handler, dof_vector, global_dof_vector);
+
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ {
+ deallog << "* level " << level << std::endl;
+ DataOut<dim> data_out;
+ data_out.set_cell_selection(
+ [level](const typename Triangulation<dim>::cell_iterator &cell) {
+ return (cell->level() == static_cast<int>(level) &&
+ cell->is_locally_owned_on_level());
+ });
+ data_out.attach_triangulation(triangulation);
+ dof_vector[level].update_ghost_values();
+ data_out.add_mg_data_vector(dof_handler, dof_vector, "data");
+ data_out.build_patches(0);
+ data_out.write_gnuplot(deallog.get_file_stream());
+ data_out.write_vtu_in_parallel(std::string("level") +
+ Utilities::to_string(level) + ".vtu",
+ MPI_COMM_WORLD);
+ }
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ MPILogInitAll log;
+
+ do_test<2>();
+ // do_test<3>();
+ return 0;
+}
--- /dev/null
+
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.00000 0.00000 0.00000
+0.250000 0.00000 0.0625000
+
+0.00000 0.250000 0.0625000
+0.250000 0.250000 0.125000
+
+
+0.250000 0.00000 0.0625000
+0.500000 0.00000 0.250000
+
+0.250000 0.250000 0.125000
+0.500000 0.250000 0.312500
+
+
+0.00000 0.250000 0.0625000
+0.250000 0.250000 0.125000
+
+0.00000 0.500000 0.250000
+0.250000 0.500000 0.312500
+
+
+0.250000 0.250000 0.125000
+0.500000 0.250000 0.312500
+
+0.250000 0.500000 0.312500
+0.500000 0.500000 0.500000
+
+
+DEAL:0::* level 0
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.00000 0.00000 0.00000
+1.00000 0.00000 1.00000
+
+0.00000 1.00000 1.00000
+1.00000 1.00000 2.00000
+
+
+DEAL:0::* level 1
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.00000 0.00000 0.00000
+0.500000 0.00000 0.250000
+
+0.00000 0.500000 0.250000
+0.500000 0.500000 0.500000
+
+
+DEAL:0::* level 2
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.00000 0.00000 0.00000
+0.250000 0.00000 0.0625000
+
+0.00000 0.250000 0.0625000
+0.250000 0.250000 0.125000
+
+
+0.250000 0.00000 0.0625000
+0.500000 0.00000 0.250000
+
+0.250000 0.250000 0.125000
+0.500000 0.250000 0.312500
+
+
+0.00000 0.250000 0.0625000
+0.250000 0.250000 0.125000
+
+0.00000 0.500000 0.250000
+0.250000 0.500000 0.312500
+
+
+0.250000 0.250000 0.125000
+0.500000 0.250000 0.312500
+
+0.250000 0.500000 0.312500
+0.500000 0.500000 0.500000
+
+
+
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.500000 0.00000 0.250000
+1.00000 0.00000 1.00000
+
+0.500000 0.500000 0.500000
+1.00000 0.500000 1.25000
+
+
+0.00000 0.500000 0.250000
+0.500000 0.500000 0.500000
+
+0.00000 1.00000 1.00000
+0.500000 1.00000 1.25000
+
+
+0.500000 0.500000 0.500000
+1.00000 0.500000 1.25000
+
+0.500000 1.00000 1.25000
+1.00000 1.00000 2.00000
+
+
+DEAL:1::* level 0
+DEAL:1::* level 1
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data>
+0.500000 0.00000 0.250000
+1.00000 0.00000 1.00000
+
+0.500000 0.500000 0.500000
+1.00000 0.500000 1.25000
+
+
+0.00000 0.500000 0.250000
+0.500000 0.500000 0.500000
+
+0.00000 1.00000 1.00000
+0.500000 1.00000 1.25000
+
+
+0.500000 0.500000 0.500000
+1.00000 0.500000 1.25000
+
+0.500000 1.00000 1.25000
+1.00000 1.00000 2.00000
+
+
+DEAL:1::* level 2
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2006 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+// Test DataOut::add_mg_data_vector in parallel for a vector valued dof function
+
+#include <deal.II/base/function_lib.h>
+#include <deal.II/base/function_parser.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim>
+void
+do_test()
+{
+ parallel::distributed::Triangulation<dim> triangulation(
+ MPI_COMM_WORLD,
+ dealii::Triangulation<dim>::none,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+
+ GridGenerator::hyper_cube(triangulation);
+ triangulation.refine_global(1);
+ triangulation.begin_active()->set_refine_flag();
+ triangulation.execute_coarsening_and_refinement();
+
+ FESystem<dim> fe(FE_DGQ<dim>(1), dim + 1);
+
+ DoFHandler<dim> dof_handler(triangulation);
+ dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs();
+
+ // Make FE vector
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
+
+ using VectorType = LinearAlgebra::distributed::Vector<double>;
+ VectorType global_dof_vector;
+ global_dof_vector.reinit(dof_handler.locally_owned_dofs(),
+ locally_relevant_dofs,
+ MPI_COMM_WORLD);
+
+ QGauss<dim> quadrature(3);
+
+ FunctionParser<dim> function(dim == 2 ? "y;-x;x*x+y*y" :
+ "y;-x;0;x*x+y*y+z*z");
+
+ AffineConstraints<double> constraints;
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ constraints.close();
+ VectorTools::project(
+ dof_handler, constraints, quadrature, function, global_dof_vector);
+ /* VectorTools::interpolate(dof_handler,
+ Functions::SquareFunction<dim>(),
+ global_dof_vector);
+ */
+
+ global_dof_vector.update_ghost_values();
+
+ std::vector<std::string> names(dim, "vec");
+ names.emplace_back("my_scalar");
+ std::vector<DataComponentInterpretation::DataComponentInterpretation>
+ interpretation(dim,
+ DataComponentInterpretation::component_is_part_of_vector);
+ interpretation.emplace_back(DataComponentInterpretation::component_is_scalar);
+
+ {
+ DataOut<dim> data_out;
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(dof_handler,
+ global_dof_vector,
+ names,
+ interpretation);
+ data_out.build_patches(0);
+ data_out.write_gnuplot(deallog.get_file_stream());
+ data_out.write_vtu_in_parallel("base.vtu", MPI_COMM_WORLD);
+ }
+
+ {
+ MGLevelObject<VectorType> dof_vector(0,
+ triangulation.n_global_levels() - 1);
+ MGTransferMF<dim, typename VectorType::value_type> transfer;
+
+ transfer.build(dof_handler);
+ transfer.interpolate_to_mg(dof_handler, dof_vector, global_dof_vector);
+
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ {
+ deallog << "* level " << level << std::endl;
+ DataOut<dim> data_out;
+ data_out.set_cell_selection(
+ [level](const typename Triangulation<dim>::cell_iterator &cell) {
+ return (cell->level() == static_cast<int>(level) &&
+ cell->is_locally_owned_on_level());
+ });
+ data_out.attach_triangulation(triangulation);
+ dof_vector[level].update_ghost_values();
+ data_out.add_mg_data_vector(dof_handler, dof_vector, "data");
+ data_out.add_mg_data_vector(dof_handler,
+ dof_vector,
+ names,
+ interpretation);
+ data_out.build_patches(0);
+ data_out.write_gnuplot(deallog.get_file_stream());
+ data_out.write_vtu_in_parallel(std::string("level") +
+ Utilities::to_string(level) + ".vtu",
+ MPI_COMM_WORLD);
+ }
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ MPILogInitAll log;
+
+ do_test<2>();
+ // do_test<3>();
+ return 0;
+}
--- /dev/null
+
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <vec> <vec> <my_scalar>
+0.00000 0.00000 -6.93889e-17 2.77556e-17 -0.0208333
+0.250000 0.00000 -5.55112e-17 -0.250000 0.0416667
+
+0.00000 0.250000 0.250000 2.77556e-17 0.0416667
+0.250000 0.250000 0.250000 -0.250000 0.104167
+
+
+0.250000 0.00000 -6.93889e-17 -0.250000 0.0416667
+0.500000 0.00000 -5.55112e-17 -0.500000 0.229167
+
+0.250000 0.250000 0.250000 -0.250000 0.104167
+0.500000 0.250000 0.250000 -0.500000 0.291667
+
+
+0.00000 0.250000 0.250000 2.77556e-17 0.0416667
+0.250000 0.250000 0.250000 -0.250000 0.104167
+
+0.00000 0.500000 0.500000 2.77556e-17 0.229167
+0.250000 0.500000 0.500000 -0.250000 0.291667
+
+
+0.250000 0.250000 0.250000 -0.250000 0.104167
+0.500000 0.250000 0.250000 -0.500000 0.291667
+
+0.250000 0.500000 0.500000 -0.250000 0.291667
+0.500000 0.500000 0.500000 -0.500000 0.479167
+
+
+DEAL:0::* level 0
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data_0> <data_1> <data_2> <vec> <vec> <my_scalar>
+0.00000 0.00000 -2.35922e-16 1.24900e-16 -0.333333 -2.35922e-16 1.24900e-16 -0.333333
+1.00000 0.00000 5.55112e-17 -1.00000 0.666667 5.55112e-17 -1.00000 0.666667
+
+0.00000 1.00000 1.00000 1.66533e-16 0.666667 1.00000 1.66533e-16 0.666667
+1.00000 1.00000 1.00000 -1.00000 1.66667 1.00000 -1.00000 1.66667
+
+
+DEAL:0::* level 1
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data_0> <data_1> <data_2> <vec> <vec> <my_scalar>
+0.00000 0.00000 -3.46945e-17 6.93889e-18 -0.0833333 -3.46945e-17 6.93889e-18 -0.0833333
+0.500000 0.00000 0.00000 -0.500000 0.166667 0.00000 -0.500000 0.166667
+
+0.00000 0.500000 0.500000 1.11022e-16 0.166667 0.500000 1.11022e-16 0.166667
+0.500000 0.500000 0.500000 -0.500000 0.416667 0.500000 -0.500000 0.416667
+
+
+DEAL:0::* level 2
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data_0> <data_1> <data_2> <vec> <vec> <my_scalar>
+0.00000 0.00000 -6.93889e-17 2.77556e-17 -0.0208333 -6.93889e-17 2.77556e-17 -0.0208333
+0.250000 0.00000 -5.55112e-17 -0.250000 0.0416667 -5.55112e-17 -0.250000 0.0416667
+
+0.00000 0.250000 0.250000 2.77556e-17 0.0416667 0.250000 2.77556e-17 0.0416667
+0.250000 0.250000 0.250000 -0.250000 0.104167 0.250000 -0.250000 0.104167
+
+
+0.250000 0.00000 -6.93889e-17 -0.250000 0.0416667 -6.93889e-17 -0.250000 0.0416667
+0.500000 0.00000 -5.55112e-17 -0.500000 0.229167 -5.55112e-17 -0.500000 0.229167
+
+0.250000 0.250000 0.250000 -0.250000 0.104167 0.250000 -0.250000 0.104167
+0.500000 0.250000 0.250000 -0.500000 0.291667 0.250000 -0.500000 0.291667
+
+
+0.00000 0.250000 0.250000 2.77556e-17 0.0416667 0.250000 2.77556e-17 0.0416667
+0.250000 0.250000 0.250000 -0.250000 0.104167 0.250000 -0.250000 0.104167
+
+0.00000 0.500000 0.500000 2.77556e-17 0.229167 0.500000 2.77556e-17 0.229167
+0.250000 0.500000 0.500000 -0.250000 0.291667 0.500000 -0.250000 0.291667
+
+
+0.250000 0.250000 0.250000 -0.250000 0.104167 0.250000 -0.250000 0.104167
+0.500000 0.250000 0.250000 -0.500000 0.291667 0.250000 -0.500000 0.291667
+
+0.250000 0.500000 0.500000 -0.250000 0.291667 0.500000 -0.250000 0.291667
+0.500000 0.500000 0.500000 -0.500000 0.479167 0.500000 -0.500000 0.479167
+
+
+
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <vec> <vec> <my_scalar>
+0.500000 0.00000 -1.38778e-16 -0.500000 0.166667
+1.00000 0.00000 -1.11022e-16 -1.00000 0.916667
+
+0.500000 0.500000 0.500000 -0.500000 0.416667
+1.00000 0.500000 0.500000 -1.00000 1.16667
+
+
+0.00000 0.500000 0.500000 5.55112e-17 0.166667
+0.500000 0.500000 0.500000 -0.500000 0.416667
+
+0.00000 1.00000 1.00000 5.55112e-17 0.916667
+0.500000 1.00000 1.00000 -0.500000 1.16667
+
+
+0.500000 0.500000 0.500000 -0.500000 0.416667
+1.00000 0.500000 0.500000 -1.00000 1.16667
+
+0.500000 1.00000 1.00000 -0.500000 1.16667
+1.00000 1.00000 1.00000 -1.00000 1.91667
+
+
+DEAL:1::* level 0
+DEAL:1::* level 1
+# This file was generated by the deal.II library.
+
+
+#
+# For a description of the GNUPLOT format see the GNUPLOT manual.
+#
+# <x> <y> <data_0> <data_1> <data_2> <vec> <vec> <my_scalar>
+0.500000 0.00000 -1.38778e-16 -0.500000 0.166667 -1.38778e-16 -0.500000 0.166667
+1.00000 0.00000 -1.11022e-16 -1.00000 0.916667 -1.11022e-16 -1.00000 0.916667
+
+0.500000 0.500000 0.500000 -0.500000 0.416667 0.500000 -0.500000 0.416667
+1.00000 0.500000 0.500000 -1.00000 1.16667 0.500000 -1.00000 1.16667
+
+
+0.00000 0.500000 0.500000 5.55112e-17 0.166667 0.500000 5.55112e-17 0.166667
+0.500000 0.500000 0.500000 -0.500000 0.416667 0.500000 -0.500000 0.416667
+
+0.00000 1.00000 1.00000 5.55112e-17 0.916667 1.00000 5.55112e-17 0.916667
+0.500000 1.00000 1.00000 -0.500000 1.16667 1.00000 -0.500000 1.16667
+
+
+0.500000 0.500000 0.500000 -0.500000 0.416667 0.500000 -0.500000 0.416667
+1.00000 0.500000 0.500000 -1.00000 1.16667 0.500000 -1.00000 1.16667
+
+0.500000 1.00000 1.00000 -0.500000 1.16667 1.00000 -0.500000 1.16667
+1.00000 1.00000 1.00000 -1.00000 1.91667 1.00000 -1.00000 1.91667
+
+
+DEAL:1::* level 2
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// same as multigrid_dg_sip but using periodic boundary conditions
+
+#include <deal.II/base/function.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <int dim, typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int n_q_points_1d,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ fe_degree = dof_handler.get_fe().degree;
+
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ addit_data.mapping_update_flags_inner_faces =
+ (update_gradients | update_JxW_values);
+ addit_data.mapping_update_flags_boundary_faces =
+ (update_gradients | update_JxW_values);
+ AffineConstraints<double> constraints;
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ data.loop(&LaplaceOperator::local_apply,
+ &LaplaceOperator::local_apply_face,
+ &LaplaceOperator::local_apply_boundary,
+ this,
+ dst,
+ src);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval_neighbor(data, false);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval_neighbor.reinit(face);
+
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval_neighbor.read_dof_values(src);
+ fe_eval_neighbor.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ (std::abs((fe_eval.normal_vector(0) *
+ fe_eval.inverse_jacobian(0))[dim - 1]) +
+ std::abs((fe_eval.normal_vector(0) *
+ fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
+ (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ fe_eval.get_normal_derivative(q) +
+ fe_eval_neighbor.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval_neighbor.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ fe_eval_neighbor.submit_value(-average_valgrad, q);
+ }
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ fe_eval_neighbor.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ fe_eval_neighbor.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ std::abs(
+ (fe_eval.normal_vector(0) * fe_eval.inverse_jacobian(0))[dim - 1]) *
+ (number)(std::max(1, fe_degree) * (fe_degree + 1.0)) * 2.;
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value = fe_eval.get_value(q);
+ VectorizedArray<number> average_valgrad =
+ -fe_eval.get_normal_derivative(q);
+ average_valgrad += average_value * sigmaF * 2.0;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ }
+
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.loop(&LaplaceOperator::local_diagonal_cell,
+ &LaplaceOperator::local_diagonal_face,
+ &LaplaceOperator::local_diagonal_boundary,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi(data, true);
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi_outer(data, false);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ phi.reinit(face);
+ phi_outer.reinit(face);
+
+ VectorizedArray<number> sigmaF =
+ (std::abs((phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
+ std::abs(
+ (phi.normal_vector(0) * phi_outer.inverse_jacobian(0))[dim - 1])) *
+ (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
+
+ // Compute phi part
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
+ phi_outer.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ phi.get_normal_derivative(q) +
+ phi_outer.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ phi.submit_normal_derivative(-average_value, q);
+ phi.submit_value(average_valgrad, q);
+ }
+ phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+
+ // Compute phi_outer part
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
+ phi_outer.begin_dof_values()[i] = 1.;
+ phi_outer.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ phi.get_normal_derivative(q) +
+ phi_outer.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ phi_outer.submit_normal_derivative(-average_value, q);
+ phi_outer.submit_value(-average_valgrad, q);
+ }
+ phi_outer.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi_outer.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi_outer.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi(data);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ phi.reinit(face);
+
+ VectorizedArray<number> sigmaF =
+ std::abs((phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) *
+ (number)(std::max(1, fe_degree) * (fe_degree + 1.0)) * 2.;
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value = phi.get_value(q);
+ VectorizedArray<number> average_valgrad =
+ -phi.get_normal_derivative(q);
+ average_valgrad += average_value * sigmaF * 2.0;
+ phi.submit_normal_derivative(-average_value, q);
+ phi.submit_value(average_valgrad, q);
+ }
+
+ phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ int fe_degree;
+};
+
+
+
+template <typename MATRIX, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MATRIX &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-7, false, false);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MATRIX *coarse_matrix;
+};
+
+
+
+template <int dim, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const unsigned int n_q_points_1d)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(n_q_points_1d);
+ LaplaceOperator<dim, number> fine_matrix;
+ fine_matrix.initialize(mapping, dof, n_q_points_1d);
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = LaplaceOperator<dim, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].initialize(mapping, dof, n_q_points_1d, level);
+
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 20.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer;
+ mg_transfer.build(dof, partitioners);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ ReductionControl control(30, 1e-20, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim>
+void
+test(const unsigned int fe_degree)
+{
+ for (unsigned int i = 5; i < 9 - fe_degree; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ dealii::Triangulation<dim>::none,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ // set boundary ids on boundaries to the number of the face
+ for (unsigned int face = 2; face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ tria.begin()->face(face)->set_all_boundary_ids(face);
+
+ std::vector<
+ GridTools::PeriodicFacePair<typename Triangulation<dim>::cell_iterator>>
+ periodic_faces;
+ for (unsigned int d = 1; d < dim; ++d)
+ GridTools::collect_periodic_faces(
+ tria, 2 * d, 2 * d + 1, d, periodic_faces);
+ tria.add_periodicity(periodic_faces);
+
+ tria.refine_global(i - dim);
+
+ FE_DGQ<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, double>(dof, fe_degree + 1);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+
+ {
+ deallog.push("2d");
+ test<2>(1);
+ test<2>(2);
+ deallog.pop();
+ deallog.push("3d");
+ test<3>(1);
+ test<3>(2);
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 7 value 1.80729e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 8 value 8.73511e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 8 value 4.57619e-10
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 7 value 1.07430e-09
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 8 value 1.87005e-10
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 4 value 7.99677e-17
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.27740e-11
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 7 value 2.41331e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 8 value 1.14978e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 9 value 1.16347e-09
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 7 value 1.80729e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 8 value 8.73511e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 8 value 4.57619e-10
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 7 value 1.07430e-09
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 8 value 1.87005e-10
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 4 value 9.91449e-17
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.27740e-11
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 7 value 2.41331e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 8 value 1.14978e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 9 value 1.16347e-09
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 7 value 1.80729e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 8 value 8.73511e-11
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 8 value 4.57619e-10
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 7 value 1.07430e-09
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 8 value 1.87005e-10
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 4 value 7.23452e-17
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.27740e-11
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 7 value 2.41331e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 8 value 1.14978e-09
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 9 value 1.16347e-09
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// test of a multigrid solver including face integration (DG case, symmetric
+// interior penalty + Nitsche).
+
+#include <deal.II/base/function.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <int dim, typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int n_q_points_1d,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ fe_degree = dof_handler.get_fe().degree;
+
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ addit_data.mapping_update_flags_inner_faces =
+ (update_gradients | update_JxW_values);
+ addit_data.mapping_update_flags_boundary_faces =
+ (update_gradients | update_JxW_values);
+ AffineConstraints<double> constraints;
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ if (!src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ {
+ LinearAlgebra::distributed::Vector<number> src_copy;
+ src_copy.reinit(data.get_dof_info().vector_partitioner);
+ src_copy = src;
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src).swap(
+ src_copy);
+ }
+ if (!dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ {
+ LinearAlgebra::distributed::Vector<number> dst_copy;
+ dst_copy.reinit(data.get_dof_info().vector_partitioner);
+ dst_copy = dst;
+ dst.swap(dst_copy);
+ }
+ dst.zero_out_ghost_values();
+ data.loop(&LaplaceOperator::local_apply,
+ &LaplaceOperator::local_apply_face,
+ &LaplaceOperator::local_apply_boundary,
+ this,
+ dst,
+ src);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ data.initialize_dof_vector(vector);
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ return inverse_diagonal_entries;
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval_neighbor(data, false);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval_neighbor.reinit(face);
+
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval_neighbor.read_dof_values(src);
+ fe_eval_neighbor.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ (std::abs((fe_eval.normal_vector(0) *
+ fe_eval.inverse_jacobian(0))[dim - 1]) +
+ std::abs((fe_eval.normal_vector(0) *
+ fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
+ (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ fe_eval.get_normal_derivative(q) +
+ fe_eval_neighbor.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval_neighbor.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ fe_eval_neighbor.submit_value(-average_valgrad, q);
+ }
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ fe_eval_neighbor.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ fe_eval_neighbor.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ std::abs(
+ (fe_eval.normal_vector(0) * fe_eval.inverse_jacobian(0))[dim - 1]) *
+ number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value = fe_eval.get_value(q);
+ VectorizedArray<number> average_valgrad =
+ -fe_eval.get_normal_derivative(q);
+ average_valgrad += average_value * sigmaF * 2.0;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ }
+
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.loop(&LaplaceOperator::local_diagonal_cell,
+ &LaplaceOperator::local_diagonal_face,
+ &LaplaceOperator::local_diagonal_boundary,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ }
+
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi(data, true);
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi_outer(data, false);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ phi.reinit(face);
+ phi_outer.reinit(face);
+
+ VectorizedArray<number> sigmaF =
+ (std::abs((phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) +
+ std::abs(
+ (phi.normal_vector(0) * phi_outer.inverse_jacobian(0))[dim - 1])) *
+ (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
+
+ // Compute phi part
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
+ phi_outer.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ phi.get_normal_derivative(q) +
+ phi_outer.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ phi.submit_normal_derivative(-average_value, q);
+ phi.submit_value(average_valgrad, q);
+ }
+ phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+
+ // Compute phi_outer part
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi_outer.begin_dof_values()[j] = VectorizedArray<number>();
+ phi_outer.begin_dof_values()[i] = 1.;
+ phi_outer.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (phi.get_value(q) - phi_outer.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ phi.get_normal_derivative(q) +
+ phi_outer.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ phi_outer.submit_normal_derivative(-average_value, q);
+ phi_outer.submit_value(-average_valgrad, q);
+ }
+ phi_outer.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi_outer.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi_outer.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi_outer.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> phi(data);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ phi.reinit(face);
+
+ VectorizedArray<number> sigmaF =
+ std::abs((phi.normal_vector(0) * phi.inverse_jacobian(0))[dim - 1]) *
+ number(std::max(fe_degree, 1) * (fe_degree + 1.0)) * 2.0;
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value = phi.get_value(q);
+ VectorizedArray<number> average_valgrad =
+ -phi.get_normal_derivative(q);
+ average_valgrad += average_value * sigmaF * 2.0;
+ phi.submit_normal_derivative(-average_value, q);
+ phi.submit_value(average_valgrad, q);
+ }
+
+ phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ int fe_degree;
+};
+
+
+
+template <typename MATRIX, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MATRIX &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10, false, false);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MATRIX *coarse_matrix;
+};
+
+
+
+template <int dim, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const unsigned n_q_points_1d)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(n_q_points_1d);
+ LaplaceOperator<dim, number> fine_matrix;
+ fine_matrix.initialize(mapping, dof, n_q_points_1d);
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = LaplaceOperator<dim, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, n_q_points_1d, level);
+ }
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 20.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+
+ mg_transfer.build(dof, [&](const unsigned int level, auto &vec) {
+ mg_matrices[level].initialize_dof_vector(vec);
+ });
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim>
+void
+test(const unsigned int fe_degree)
+{
+ for (unsigned int i = 5; i < 9 - fe_degree; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ dealii::Triangulation<dim>::none,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_DGQ<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, double>(dof, fe_degree + 1);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+
+ {
+ deallog.push("2d");
+ test<2>(1);
+ test<2>(2);
+ deallog.pop();
+ deallog.push("3d");
+ test<3>(1);
+ test<3>(2);
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 5 value 3.60502e-07
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 5 value 2.14074e-06
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 5 value 5.99637e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 5 value 1.81901e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 6 value 1.94976e-07
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 6 value 7.43327e-08
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.28298e-06
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 6 value 5.09300e-06
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 6 value 1.73456e-07
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 7 value 5.35539e-07
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 5 value 3.60502e-07
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 5 value 2.14074e-06
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 5 value 5.99637e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 5 value 1.81901e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 6 value 1.94976e-07
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 6 value 7.43327e-08
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.28298e-06
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 6 value 5.09300e-06
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 6 value 1.73456e-07
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 7 value 5.35539e-07
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// test of a multigrid solver including face integration (DG case, symmetric
+// interior penalty + Nitsche). As opposed to multigrid_dg_sip_01, this test
+// computes the diagonal using the alternative reinit(cell_index, face_number)
+
+#include <deal.II/base/function.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <int dim, typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int n_q_points_1d,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ fe_degree = dof_handler.get_fe().degree;
+
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ addit_data.mapping_update_flags_inner_faces =
+ update_JxW_values | update_normal_vectors | update_jacobians;
+ addit_data.mapping_update_flags_boundary_faces =
+ update_JxW_values | update_normal_vectors | update_jacobians;
+ addit_data.mapping_update_flags_faces_by_cells =
+ update_JxW_values | update_normal_vectors | update_jacobians;
+ AffineConstraints<double> constraints;
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ if (!src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ {
+ LinearAlgebra::distributed::Vector<number> src_copy;
+ src_copy.reinit(data.get_dof_info().vector_partitioner);
+ src_copy = src;
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src).swap(
+ src_copy);
+ }
+ if (!dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ {
+ LinearAlgebra::distributed::Vector<number> dst_copy;
+ dst_copy.reinit(data.get_dof_info().vector_partitioner);
+ dst_copy = dst;
+ dst.swap(dst_copy);
+ }
+ dst.zero_out_ghost_values();
+ data.loop(&LaplaceOperator::local_apply,
+ &LaplaceOperator::local_apply_face,
+ &LaplaceOperator::local_apply_boundary,
+ this,
+ dst,
+ src);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ data.initialize_dof_vector(vector);
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval_neighbor(data, false);
+
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval_neighbor.reinit(face);
+
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval_neighbor.read_dof_values(src);
+ fe_eval_neighbor.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ (std::abs((fe_eval.normal_vector(0) *
+ fe_eval.inverse_jacobian(0))[dim - 1]) +
+ std::abs((fe_eval.normal_vector(0) *
+ fe_eval_neighbor.inverse_jacobian(0))[dim - 1])) *
+ (number)(std::max(fe_degree, 1) * (fe_degree + 1.0));
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ (fe_eval.get_value(q) - fe_eval_neighbor.get_value(q)) * 0.5;
+ VectorizedArray<number> average_valgrad =
+ fe_eval.get_normal_derivative(q) +
+ fe_eval_neighbor.get_normal_derivative(q);
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad * 0.5;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval_neighbor.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ fe_eval_neighbor.submit_value(-average_valgrad, q);
+ }
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ fe_eval_neighbor.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ fe_eval_neighbor.distribute_local_to_global(dst);
+ }
+ }
+
+ 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
+ {
+ FEFaceEvaluation<dim, -1, 0, 1, number> fe_eval(data, true);
+ for (unsigned int face = face_range.first; face < face_range.second; ++face)
+ {
+ fe_eval.reinit(face);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
+ VectorizedArray<number> sigmaF =
+ std::abs(
+ (fe_eval.normal_vector(0) * fe_eval.inverse_jacobian(0))[dim - 1]) *
+ (number)(std::max(1, fe_degree) * (fe_degree + 1.0)) * 2.;
+
+ for (unsigned int q = 0; q < fe_eval.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value = fe_eval.get_value(q);
+ VectorizedArray<number> average_valgrad =
+ -fe_eval.get_normal_derivative(q);
+ average_valgrad += average_value * sigmaF * 2.0;
+ fe_eval.submit_normal_derivative(-average_value, q);
+ fe_eval.submit_value(average_valgrad, q);
+ }
+
+ fe_eval.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ fe_eval.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ }
+
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+ FEFaceEvaluation<dim, -1, 0, 1, number> phif(data);
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (const unsigned int face : GeometryInfo<dim>::face_indices())
+ {
+ phif.reinit(cell, face);
+ VectorizedArray<number> sigmaF =
+ std::abs(
+ (phif.normal_vector(0) * phif.inverse_jacobian(0))[dim - 1]) *
+ (number)(std::max(1, fe_degree) * (fe_degree + 1.0)) * 2.;
+ std::array<types::boundary_id, VectorizedArray<number>::size()>
+ boundary_ids = data.get_faces_by_cells_boundary_id(cell, face);
+ VectorizedArray<number> factor_boundary;
+ for (unsigned int v = 0; v < VectorizedArray<number>::size(); ++v)
+ // interior face
+ if (boundary_ids[v] == numbers::invalid_boundary_id)
+ factor_boundary[v] = 0.5;
+ // Dirichlet boundary
+ else
+ factor_boundary[v] = 1.0;
+ for (unsigned int i = 0; i < phif.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phif.dofs_per_cell; ++j)
+ phif.begin_dof_values()[j] = VectorizedArray<number>();
+ phif.begin_dof_values()[i] = 1.;
+ phif.evaluate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phif.n_q_points; ++q)
+ {
+ VectorizedArray<number> average_value =
+ phif.get_value(q) * factor_boundary;
+ VectorizedArray<number> average_valgrad =
+ phif.get_normal_derivative(q) * factor_boundary;
+ average_valgrad =
+ average_value * 2. * sigmaF - average_valgrad;
+ phif.submit_normal_derivative(-average_value, q);
+ phif.submit_value(average_valgrad, q);
+ }
+ phif.integrate(EvaluationFlags::values |
+ EvaluationFlags::gradients);
+ local_diagonal_vector[i] += phif.begin_dof_values()[i];
+ }
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ int fe_degree;
+};
+
+
+
+template <typename MATRIX, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MATRIX &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10, false, false);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MATRIX *coarse_matrix;
+};
+
+
+
+template <int dim, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const unsigned int n_q_points_1d)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(n_q_points_1d);
+ LaplaceOperator<dim, number> fine_matrix;
+ fine_matrix.initialize(mapping, dof, n_q_points_1d);
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = LaplaceOperator<dim, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, n_q_points_1d, level);
+ }
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 20.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim>
+void
+test(const unsigned int fe_degree)
+{
+ for (unsigned int i = 5; i < 9 - fe_degree; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ dealii::Triangulation<dim>::none,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_DGQ<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, double>(dof, fe_degree + 1);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ deallog.push("2d");
+ test<2>(1);
+ test<2>(2);
+ deallog.pop();
+ deallog.push("3d");
+ test<3>(1);
+ test<3>(2);
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 256
+DEAL:2d:cg::Starting value 16.0000
+DEAL:2d:cg::Convergence step 5 value 3.60502e-07
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 1024
+DEAL:2d:cg::Starting value 32.0000
+DEAL:2d:cg::Convergence step 5 value 2.14074e-06
+DEAL:2d::Testing FE_DGQ<2>(1)
+DEAL:2d::Number of degrees of freedom: 4096
+DEAL:2d:cg::Starting value 64.0000
+DEAL:2d:cg::Convergence step 5 value 5.99637e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 576
+DEAL:2d:cg::Starting value 24.0000
+DEAL:2d:cg::Convergence step 5 value 1.81901e-06
+DEAL:2d::Testing FE_DGQ<2>(2)
+DEAL:2d::Number of degrees of freedom: 2304
+DEAL:2d:cg::Starting value 48.0000
+DEAL:2d:cg::Convergence step 6 value 1.94976e-07
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 512
+DEAL:3d:cg::Starting value 22.6274
+DEAL:3d:cg::Convergence step 6 value 7.43327e-08
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 4096
+DEAL:3d:cg::Starting value 64.0000
+DEAL:3d:cg::Convergence step 6 value 2.28298e-06
+DEAL:3d::Testing FE_DGQ<3>(1)
+DEAL:3d::Number of degrees of freedom: 32768
+DEAL:3d:cg::Starting value 181.019
+DEAL:3d:cg::Convergence step 6 value 5.09300e-06
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 1728
+DEAL:3d:cg::Starting value 41.5692
+DEAL:3d:cg::Convergence step 6 value 1.73456e-07
+DEAL:3d::Testing FE_DGQ<3>(2)
+DEAL:3d::Number of degrees of freedom: 13824
+DEAL:3d:cg::Starting value 117.576
+DEAL:3d:cg::Convergence step 7 value 5.35539e-07
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// test running a multigrid solver on continuous FE_Q finite elements with
+// MatrixFree data structures (otherwise similar to step-37)
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const std::set<types::boundary_id> &dirichlet_boundaries,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.mg_level = level;
+
+ // extract the constraints due to Dirichlet boundary conditions
+ AffineConstraints<double> constraints;
+ Functions::ZeroFunction<dim> zero;
+ std::map<types::boundary_id, const Function<dim> *> functions;
+ for (std::set<types::boundary_id>::const_iterator it =
+ dirichlet_boundaries.begin();
+ it != dirichlet_boundaries.end();
+ ++it)
+ functions[*it] = &zero;
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number> fine_matrix;
+ const std::set<types::boundary_id> dirichlet_boundaries = {0};
+ fine_matrix.initialize(mapping, dof, dirichlet_boundaries);
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, dirichlet_boundaries, level);
+ }
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer;
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ smoother_data[level].preconditioner->get_vector() =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ for (unsigned int i = 5; i < 8; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ test<2, 2>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ test<3, 2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 81
+DEAL:2d:cg::Starting value 9.000
+DEAL:2d:cg:cg::Starting value 0.02203
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 0.0001585
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 8.884e-07
+DEAL:2d:cg:cg::Convergence step 1 value 9.863e-23
+DEAL:2d:cg:cg::Starting value 3.123e-09
+DEAL:2d:cg:cg::Convergence step 1 value 3.468e-25
+DEAL:2d:cg::Convergence step 4 value 2.071e-08
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 0.005310
+DEAL:2d:cg:cg::Convergence step 1 value 5.895e-19
+DEAL:2d:cg:cg::Starting value 5.163e-06
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 2.182e-08
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 9.610e-10
+DEAL:2d:cg:cg::Convergence step 1 value 2.134e-25
+DEAL:2d:cg::Convergence step 4 value 2.778e-08
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 0.008242
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 2.754e-06
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 9.820e-09
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 8.188e-12
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg::Convergence step 4 value 8.029e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 3.849
+DEAL:2d:cg:cg::Convergence step 2 value 1.388e-15
+DEAL:2d:cg:cg::Starting value 0.0007035
+DEAL:2d:cg:cg::Convergence step 2 value 7.914e-19
+DEAL:2d:cg:cg::Starting value 4.286e-06
+DEAL:2d:cg:cg::Convergence step 2 value 1.471e-21
+DEAL:2d:cg:cg::Starting value 2.909e-08
+DEAL:2d:cg:cg::Convergence step 2 value 1.896e-23
+DEAL:2d:cg::Convergence step 4 value 3.931e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 14.69
+DEAL:2d:cg:cg::Convergence step 2 value 4.242e-15
+DEAL:2d:cg:cg::Starting value 0.002915
+DEAL:2d:cg:cg::Convergence step 2 value 1.213e-18
+DEAL:2d:cg:cg::Starting value 3.439e-06
+DEAL:2d:cg:cg::Convergence step 2 value 1.583e-21
+DEAL:2d:cg:cg::Starting value 1.212e-08
+DEAL:2d:cg:cg::Convergence step 2 value 1.131e-24
+DEAL:2d:cg::Convergence step 4 value 8.121e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 4225
+DEAL:2d:cg::Starting value 65.00
+DEAL:2d:cg:cg::Starting value 58.09
+DEAL:2d:cg:cg::Convergence step 2 value 4.467e-14
+DEAL:2d:cg:cg::Starting value 0.01056
+DEAL:2d:cg:cg::Convergence step 2 value 9.358e-19
+DEAL:2d:cg:cg::Starting value 2.588e-05
+DEAL:2d:cg:cg::Convergence step 2 value 3.405e-20
+DEAL:2d:cg:cg::Starting value 6.672e-08
+DEAL:2d:cg:cg::Convergence step 2 value 5.007e-23
+DEAL:2d:cg::Convergence step 4 value 1.695e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 125
+DEAL:3d:cg::Starting value 11.18
+DEAL:3d:cg:cg::Starting value 0.5164
+DEAL:3d:cg:cg::Convergence step 1 value 1.147e-16
+DEAL:3d:cg:cg::Starting value 0.02357
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 5.322e-05
+DEAL:3d:cg:cg::Convergence step 1 value 1.182e-20
+DEAL:3d:cg:cg::Starting value 1.537e-07
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg::Convergence step 4 value 3.460e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 0.1824
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 0.004902
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 5.629e-06
+DEAL:3d:cg:cg::Convergence step 1 value 1.250e-21
+DEAL:3d:cg:cg::Starting value 3.386e-10
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg::Convergence step 4 value 1.074e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 0.1633
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 0.0001064
+DEAL:3d:cg:cg::Convergence step 1 value 1.181e-20
+DEAL:3d:cg:cg::Starting value 1.367e-06
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 1.607e-08
+DEAL:3d:cg:cg::Convergence step 1 value 3.568e-24
+DEAL:3d:cg::Convergence step 4 value 5.067e-08
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 1.696
+DEAL:3d:cg:cg::Convergence step 2 value 4.279e-16
+DEAL:3d:cg:cg::Starting value 0.1039
+DEAL:3d:cg:cg::Convergence step 2 value 1.250e-17
+DEAL:3d:cg:cg::Starting value 0.0001780
+DEAL:3d:cg:cg::Convergence step 2 value 1.054e-20
+DEAL:3d:cg:cg::Starting value 5.292e-06
+DEAL:3d:cg:cg::Convergence step 2 value 1.622e-22
+DEAL:3d:cg::Convergence step 4 value 2.351e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 2.288
+DEAL:3d:cg:cg::Convergence step 2 value 1.482e-15
+DEAL:3d:cg:cg::Starting value 0.04493
+DEAL:3d:cg:cg::Convergence step 2 value 2.411e-18
+DEAL:3d:cg:cg::Starting value 0.0007205
+DEAL:3d:cg:cg::Convergence step 2 value 9.281e-20
+DEAL:3d:cg:cg::Starting value 2.913e-06
+DEAL:3d:cg:cg::Convergence step 2 value 5.846e-23
+DEAL:3d:cg::Convergence step 4 value 4.578e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 35937
+DEAL:3d:cg::Starting value 189.6
+DEAL:3d:cg:cg::Starting value 17.19
+DEAL:3d:cg:cg::Convergence step 2 value 1.912e-14
+DEAL:3d:cg:cg::Starting value 0.01678
+DEAL:3d:cg:cg::Convergence step 2 value 4.151e-18
+DEAL:3d:cg:cg::Starting value 0.001099
+DEAL:3d:cg:cg::Convergence step 2 value 2.529e-19
+DEAL:3d:cg:cg::Starting value 9.998e-07
+DEAL:3d:cg:cg::Convergence step 2 value 5.098e-22
+DEAL:3d:cg::Convergence step 4 value 1.784e-05
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 81
+DEAL:2d:cg::Starting value 9.000
+DEAL:2d:cg:cg::Starting value 0.02203
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 0.0001585
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 8.884e-07
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 3.123e-09
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg::Convergence step 4 value 2.071e-08
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 0.005310
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 5.163e-06
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 2.182e-08
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 9.610e-10
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg::Convergence step 4 value 2.778e-08
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 0.008242
+DEAL:2d:cg:cg::Convergence step 1 value 1.830e-18
+DEAL:2d:cg:cg::Starting value 2.754e-06
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 9.820e-09
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg:cg::Starting value 8.188e-12
+DEAL:2d:cg:cg::Convergence step 1 value 0.000
+DEAL:2d:cg::Convergence step 4 value 8.029e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 3.849
+DEAL:2d:cg:cg::Convergence step 2 value 1.863e-15
+DEAL:2d:cg:cg::Starting value 0.0007035
+DEAL:2d:cg:cg::Convergence step 2 value 5.372e-19
+DEAL:2d:cg:cg::Starting value 4.286e-06
+DEAL:2d:cg:cg::Convergence step 2 value 4.258e-21
+DEAL:2d:cg:cg::Starting value 2.909e-08
+DEAL:2d:cg:cg::Convergence step 2 value 1.177e-24
+DEAL:2d:cg::Convergence step 4 value 3.931e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 14.69
+DEAL:2d:cg:cg::Convergence step 2 value 1.771e-14
+DEAL:2d:cg:cg::Starting value 0.002915
+DEAL:2d:cg:cg::Convergence step 2 value 2.794e-18
+DEAL:2d:cg:cg::Starting value 3.439e-06
+DEAL:2d:cg:cg::Convergence step 2 value 1.470e-21
+DEAL:2d:cg:cg::Starting value 1.212e-08
+DEAL:2d:cg:cg::Convergence step 2 value 4.310e-24
+DEAL:2d:cg::Convergence step 4 value 8.121e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 4225
+DEAL:2d:cg::Starting value 65.00
+DEAL:2d:cg:cg::Starting value 58.09
+DEAL:2d:cg:cg::Convergence step 2 value 7.517e-15
+DEAL:2d:cg:cg::Starting value 0.01056
+DEAL:2d:cg:cg::Convergence step 2 value 3.556e-18
+DEAL:2d:cg:cg::Starting value 2.588e-05
+DEAL:2d:cg:cg::Convergence step 2 value 1.590e-20
+DEAL:2d:cg:cg::Starting value 6.672e-08
+DEAL:2d:cg:cg::Convergence step 2 value 3.475e-23
+DEAL:2d:cg::Convergence step 4 value 1.695e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 125
+DEAL:3d:cg::Starting value 11.18
+DEAL:3d:cg:cg::Starting value 0.5164
+DEAL:3d:cg:cg::Convergence step 1 value 1.147e-16
+DEAL:3d:cg:cg::Starting value 0.02357
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 5.322e-05
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 1.537e-07
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg::Convergence step 4 value 3.460e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 0.1824
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 0.004902
+DEAL:3d:cg:cg::Convergence step 1 value 5.443e-19
+DEAL:3d:cg:cg::Starting value 5.629e-06
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 3.386e-10
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg::Convergence step 4 value 1.074e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 0.1633
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 0.0001064
+DEAL:3d:cg:cg::Convergence step 1 value 2.362e-20
+DEAL:3d:cg:cg::Starting value 1.367e-06
+DEAL:3d:cg:cg::Convergence step 1 value 0.000
+DEAL:3d:cg:cg::Starting value 1.607e-08
+DEAL:3d:cg:cg::Convergence step 1 value 3.568e-24
+DEAL:3d:cg::Convergence step 4 value 5.067e-08
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 1.696
+DEAL:3d:cg:cg::Convergence step 2 value 1.987e-16
+DEAL:3d:cg:cg::Starting value 0.1039
+DEAL:3d:cg:cg::Convergence step 2 value 3.578e-18
+DEAL:3d:cg:cg::Starting value 0.0001780
+DEAL:3d:cg:cg::Convergence step 2 value 1.311e-20
+DEAL:3d:cg:cg::Starting value 5.292e-06
+DEAL:3d:cg:cg::Convergence step 2 value 5.646e-22
+DEAL:3d:cg::Convergence step 4 value 2.351e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 2.288
+DEAL:3d:cg:cg::Convergence step 2 value 6.751e-17
+DEAL:3d:cg:cg::Starting value 0.04493
+DEAL:3d:cg:cg::Convergence step 2 value 1.105e-17
+DEAL:3d:cg:cg::Starting value 0.0007205
+DEAL:3d:cg:cg::Convergence step 2 value 1.525e-20
+DEAL:3d:cg:cg::Starting value 2.913e-06
+DEAL:3d:cg:cg::Convergence step 2 value 7.041e-22
+DEAL:3d:cg::Convergence step 4 value 4.578e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 35937
+DEAL:3d:cg::Starting value 189.6
+DEAL:3d:cg:cg::Starting value 17.19
+DEAL:3d:cg:cg::Convergence step 2 value 5.350e-15
+DEAL:3d:cg:cg::Starting value 0.01678
+DEAL:3d:cg:cg::Convergence step 2 value 3.272e-18
+DEAL:3d:cg:cg::Starting value 0.001099
+DEAL:3d:cg:cg::Convergence step 2 value 2.132e-20
+DEAL:3d:cg:cg::Starting value 9.998e-07
+DEAL:3d:cg:cg::Convergence step 2 value 3.927e-22
+DEAL:3d:cg::Convergence step 4 value 1.784e-05
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// similar to parallel_multigrid.cc but using
+// MatrixFreeOperators::LaplaceOperator class
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+using namespace dealii::MatrixFreeOperators;
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>
+ fine_matrix;
+ std::shared_ptr<MatrixFree<dim, number>> fine_level_data(
+ new MatrixFree<dim, number>());
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ for (unsigned int i = 5; i < 7; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ test<2, 2>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ test<3, 2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 81
+DEAL:2d:cg::Starting value 9.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg::Convergence step 3 value 6.753e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg::Convergence step 4 value 2.625e-09
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 3.765
+DEAL:2d:cg:cg::Convergence step 1 value 2.359e-16
+DEAL:2d:cg:cg::Starting value 0.0005314
+DEAL:2d:cg:cg::Convergence step 1 value 6.437e-20
+DEAL:2d:cg:cg::Starting value 3.806e-06
+DEAL:2d:cg:cg::Convergence step 1 value 9.264e-23
+DEAL:2d:cg:cg::Starting value 1.628e-08
+DEAL:2d:cg:cg::Convergence step 1 value 1.034e-24
+DEAL:2d:cg::Convergence step 4 value 1.712e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 14.37
+DEAL:2d:cg:cg::Convergence step 1 value 8.327e-16
+DEAL:2d:cg:cg::Starting value 0.002280
+DEAL:2d:cg:cg::Convergence step 1 value 2.711e-20
+DEAL:2d:cg:cg::Starting value 6.550e-06
+DEAL:2d:cg:cg::Convergence step 1 value 1.570e-22
+DEAL:2d:cg:cg::Starting value 5.084e-08
+DEAL:2d:cg:cg::Convergence step 1 value 6.035e-24
+DEAL:2d:cg::Convergence step 4 value 4.315e-08
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 125
+DEAL:3d:cg::Starting value 11.18
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg::Convergence step 3 value 4.383e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg::Convergence step 3 value 1.025e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 0.3870
+DEAL:3d:cg:cg::Convergence step 1 value 4.005e-17
+DEAL:3d:cg:cg::Starting value 0.0005996
+DEAL:3d:cg:cg::Convergence step 1 value 2.717e-20
+DEAL:3d:cg:cg::Starting value 3.381e-07
+DEAL:3d:cg:cg::Convergence step 1 value 1.182e-23
+DEAL:3d:cg:cg::Starting value 5.601e-10
+DEAL:3d:cg:cg::Convergence step 1 value 5.638e-26
+DEAL:3d:cg::Convergence step 4 value 5.998e-09
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 2.248
+DEAL:3d:cg:cg::Convergence step 1 value 8.552e-17
+DEAL:3d:cg:cg::Starting value 0.0007474
+DEAL:3d:cg:cg::Convergence step 1 value 1.057e-19
+DEAL:3d:cg:cg::Starting value 3.260e-06
+DEAL:3d:cg:cg::Convergence step 1 value 4.268e-23
+DEAL:3d:cg:cg::Starting value 1.168e-08
+DEAL:3d:cg:cg::Convergence step 1 value 4.233e-25
+DEAL:3d:cg::Convergence step 4 value 5.811e-08
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 81
+DEAL:2d:cg::Starting value 9.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg::Convergence step 3 value 6.753e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg:cg::Convergence step 0 value 0.000
+DEAL:2d:cg::Convergence step 4 value 2.625e-09
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 289
+DEAL:2d:cg::Starting value 17.00
+DEAL:2d:cg:cg::Starting value 3.765
+DEAL:2d:cg:cg::Convergence step 1 value 2.220e-16
+DEAL:2d:cg:cg::Starting value 0.0005314
+DEAL:2d:cg:cg::Convergence step 1 value 2.282e-20
+DEAL:2d:cg:cg::Starting value 3.806e-06
+DEAL:2d:cg:cg::Convergence step 1 value 2.569e-22
+DEAL:2d:cg:cg::Starting value 1.628e-08
+DEAL:2d:cg:cg::Convergence step 1 value 9.306e-25
+DEAL:2d:cg::Convergence step 4 value 1.712e-08
+DEAL:2d::Testing FE_Q<2>(2)
+DEAL:2d::Number of degrees of freedom: 1089
+DEAL:2d:cg::Starting value 33.00
+DEAL:2d:cg:cg::Starting value 14.37
+DEAL:2d:cg:cg::Convergence step 1 value 9.437e-16
+DEAL:2d:cg:cg::Starting value 0.002280
+DEAL:2d:cg:cg::Convergence step 1 value 2.168e-19
+DEAL:2d:cg:cg::Starting value 6.550e-06
+DEAL:2d:cg:cg::Convergence step 1 value 5.823e-22
+DEAL:2d:cg:cg::Starting value 5.084e-08
+DEAL:2d:cg:cg::Convergence step 1 value 4.136e-25
+DEAL:2d:cg::Convergence step 4 value 4.315e-08
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 125
+DEAL:3d:cg::Starting value 11.18
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg::Convergence step 3 value 4.383e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg:cg::Convergence step 0 value 0.000
+DEAL:3d:cg::Convergence step 3 value 1.025e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 729
+DEAL:3d:cg::Starting value 27.00
+DEAL:3d:cg:cg::Starting value 0.3870
+DEAL:3d:cg:cg::Convergence step 1 value 3.850e-18
+DEAL:3d:cg:cg::Starting value 0.0005996
+DEAL:3d:cg:cg::Convergence step 1 value 1.355e-20
+DEAL:3d:cg:cg::Starting value 3.381e-07
+DEAL:3d:cg:cg::Convergence step 1 value 8.779e-24
+DEAL:3d:cg:cg::Starting value 5.601e-10
+DEAL:3d:cg:cg::Convergence step 1 value 4.426e-26
+DEAL:3d:cg::Convergence step 4 value 5.998e-09
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 4913
+DEAL:3d:cg::Starting value 70.09
+DEAL:3d:cg:cg::Starting value 2.248
+DEAL:3d:cg:cg::Convergence step 1 value 2.463e-16
+DEAL:3d:cg:cg::Starting value 0.0007474
+DEAL:3d:cg:cg::Convergence step 1 value 1.924e-20
+DEAL:3d:cg:cg::Starting value 3.260e-06
+DEAL:3d:cg:cg::Convergence step 1 value 2.263e-22
+DEAL:3d:cg:cg::Starting value 1.168e-08
+DEAL:3d:cg:cg::Convergence step 1 value 1.617e-26
+DEAL:3d:cg::Convergence step 4 value 5.811e-08
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// similar as parallel_multigrid but using adaptive meshes with hanging nodes
+// (doing local smoothing)
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ LaplaceOperator(){};
+
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const MGConstrainedDoFs &mg_constrained_dofs,
+ const std::map<types::boundary_id, const Function<dim> *>
+ & dirichlet_boundary,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ AffineConstraints<double> constraints;
+ if (level == numbers::invalid_unsigned_int)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ VectorTools::interpolate_boundary_values(dof_handler,
+ dirichlet_boundary,
+ constraints);
+ }
+ else
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler,
+ level,
+ relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ constraints.add_lines(mg_constrained_dofs.get_boundary_indices(level));
+
+ const std::vector<types::global_dof_index> interface_indices =
+ mg_constrained_dofs.get_refinement_edge_indices(level)
+ .get_index_vector();
+ edge_constrained_indices.clear();
+ edge_constrained_indices.reserve(interface_indices.size());
+ edge_constrained_values.resize(interface_indices.size());
+ const IndexSet &locally_owned =
+ dof_handler.locally_owned_mg_dofs(level);
+ for (unsigned int i = 0; i < interface_indices.size(); ++i)
+ if (locally_owned.is_element(interface_indices[i]))
+ edge_constrained_indices.push_back(
+ locally_owned.index_within_set(interface_indices[i]));
+ have_interface_matrices =
+ Utilities::MPI::max((unsigned int)edge_constrained_indices.size(),
+ MPI_COMM_WORLD) > 0;
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ if (level != numbers::invalid_unsigned_int)
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ edge_constrained_values[i] = std::pair<number, number>(
+ src.local_element(edge_constrained_indices[i]),
+ dst.local_element(edge_constrained_indices[i]));
+ const_cast<LinearAlgebra::distributed::Vector<double> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+
+ // reset edge constrained values, multiply by unit matrix and add into
+ // destination
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const_cast<LinearAlgebra::distributed::Vector<double> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ dst.local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].second + edge_constrained_values[i].first;
+ }
+ }
+
+ void
+ vmult_interface_down(
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const double src_val = src.local_element(edge_constrained_indices[i]);
+ const_cast<LinearAlgebra::distributed::Vector<double> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ edge_constrained_values[i] = std::pair<number, number>(
+ src_val, dst.local_element(edge_constrained_indices[i]));
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ dst.local_element(c) = 0.;
+ ++c;
+
+ // reset the src values
+ const_cast<LinearAlgebra::distributed::Vector<double> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ }
+ for (; c < dst.locally_owned_size(); ++c)
+ dst.local_element(c) = 0.;
+ }
+
+ void
+ vmult_interface_up(
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ LinearAlgebra::distributed::Vector<double> src_cpy(src);
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ src_cpy.local_element(c) = 0.;
+ ++c;
+ }
+ for (; c < src_cpy.locally_owned_size(); ++c)
+ src_cpy.local_element(c) = 0.;
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src_cpy);
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ dst.local_element(edge_constrained_indices[i]) = 0.;
+ }
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ inverse_diagonal_entries.local_element(constrained_dofs[i]) = 1.;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ inverse_diagonal_entries.local_element(edge_constrained_indices[i]) =
+ 1.;
+ }
+
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ std::vector<unsigned int> edge_constrained_indices;
+ mutable std::vector<std::pair<number, number>> edge_constrained_values;
+ bool have_interface_matrices;
+};
+
+
+
+template <typename LAPLACEOPERATOR>
+class MGInterfaceMatrix : public Subscriptor
+{
+public:
+ void
+ initialize(const LAPLACEOPERATOR &laplace)
+ {
+ this->laplace = &laplace;
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ laplace->vmult_interface_down(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ laplace->vmult_interface_up(dst, src);
+ }
+
+private:
+ SmartPointer<const LAPLACEOPERATOR> laplace;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ AffineConstraints<double> hanging_node_constraints;
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number> fine_matrix;
+ fine_matrix.initialize(mapping,
+ dof,
+ mg_constrained_dofs,
+ dirichlet_boundary,
+ numbers::invalid_unsigned_int);
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(
+ mapping, dof, mg_constrained_dofs, dirichlet_boundary, level);
+ }
+ MGLevelObject<MGInterfaceMatrix<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ smoother_data[level].preconditioner->get_vector() =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 5 value 1.167e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 6 value 1.190e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 6 value 1.886e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 6 value 3.143e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 6 value 2.139e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 7 value 4.724e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 8 value 6.234e-06
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 5 value 1.145e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 6 value 1.176e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 6 value 1.884e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 6 value 3.090e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 6 value 2.139e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 7 value 4.739e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 8 value 6.236e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// same as parallel_multigrid_adaptive_01, but based on MGTransferMatrixFree
+// and using MatrixFreeOperators::LaplaceOperator class.
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>
+ fine_matrix;
+ std::shared_ptr<MatrixFree<dim, number>> fine_level_data(
+ new MatrixFree<dim, number>());
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_level_data[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ test<2, 3>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ test<3, 2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 5 value 1.167e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 6 value 1.190e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 6 value 1.886e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 6 value 3.143e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 64.26
+DEAL:2d:cg::Convergence step 5 value 2.131e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 83.11
+DEAL:2d:cg::Convergence step 6 value 5.783e-07
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 131.0
+DEAL:2d:cg::Convergence step 6 value 6.147e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 6 value 2.139e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 7 value 4.724e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 8 value 6.234e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 82.90
+DEAL:3d:cg::Convergence step 7 value 1.038e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 152.6
+DEAL:3d:cg::Convergence step 7 value 4.360e-06
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 5 value 1.145e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 6 value 1.176e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 6 value 1.884e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 6 value 3.090e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 64.26
+DEAL:2d:cg::Convergence step 5 value 2.131e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 83.11
+DEAL:2d:cg::Convergence step 6 value 5.788e-07
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 131.0
+DEAL:2d:cg::Convergence step 6 value 6.134e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 6 value 2.139e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 7 value 4.739e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 8 value 6.236e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 82.90
+DEAL:3d:cg::Convergence step 7 value 1.039e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 152.6
+DEAL:3d:cg::Convergence step 7 value 4.352e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// same test as parallel_multigrid_adaptive_01 but using
+// MGTransferMatrixFree rather the MGTransferPrebuilt (and manually
+// implementing the full LaplaceOperator class rather than using the
+// operator as in _02)
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const MGConstrainedDoFs &mg_constrained_dofs,
+ const std::map<types::boundary_id, const Function<dim> *>
+ & dirichlet_boundary,
+ const unsigned int level,
+ const bool threaded)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ if (threaded)
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::partition_partition;
+ else
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ AffineConstraints<double> constraints;
+ if (level == numbers::invalid_unsigned_int)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ VectorTools::interpolate_boundary_values(dof_handler,
+ dirichlet_boundary,
+ constraints);
+ }
+ else
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler,
+ level,
+ relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ constraints.add_lines(mg_constrained_dofs.get_boundary_indices(level));
+
+ const std::vector<types::global_dof_index> interface_indices =
+ mg_constrained_dofs.get_refinement_edge_indices(level)
+ .get_index_vector();
+ edge_constrained_indices.clear();
+ edge_constrained_indices.reserve(interface_indices.size());
+ edge_constrained_values.resize(interface_indices.size());
+ const IndexSet &locally_owned =
+ dof_handler.locally_owned_mg_dofs(level);
+ for (unsigned int i = 0; i < interface_indices.size(); ++i)
+ if (locally_owned.is_element(interface_indices[i]))
+ edge_constrained_indices.push_back(
+ locally_owned.index_within_set(interface_indices[i]));
+ have_interface_matrices =
+ Utilities::MPI::max((unsigned int)edge_constrained_indices.size(),
+ MPI_COMM_WORLD) > 0;
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ if (level != numbers::invalid_unsigned_int)
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ edge_constrained_values[i] = std::pair<number, number>(
+ src.local_element(edge_constrained_indices[i]),
+ dst.local_element(edge_constrained_indices[i]));
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+
+ // reset edge constrained values, multiply by unit matrix and add into
+ // destination
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ dst.local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].second + edge_constrained_values[i].first;
+ }
+ }
+
+ void
+ vmult_interface_down(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const double src_val = src.local_element(edge_constrained_indices[i]);
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ edge_constrained_values[i] = std::pair<number, number>(
+ src_val, dst.local_element(edge_constrained_indices[i]));
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ dst.local_element(c) = 0.;
+ ++c;
+
+ // reset the src values
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ }
+ for (; c < dst.locally_owned_size(); ++c)
+ dst.local_element(c) = 0.;
+ }
+
+ void
+ vmult_interface_up(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ LinearAlgebra::distributed::Vector<number> src_cpy(src);
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ src_cpy.local_element(c) = 0.;
+ ++c;
+ }
+ for (; c < src_cpy.locally_owned_size(); ++c)
+ src_cpy.local_element(c) = 0.;
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src_cpy);
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ dst.local_element(edge_constrained_indices[i]) = 0.;
+ }
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ inverse_diagonal_entries.local_element(constrained_dofs[i]) = 1.;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ inverse_diagonal_entries.local_element(edge_constrained_indices[i]) =
+ 1.;
+ }
+
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ std::vector<unsigned int> edge_constrained_indices;
+ mutable std::vector<std::pair<number, number>> edge_constrained_values;
+ bool have_interface_matrices;
+};
+
+
+
+template <typename LAPLACEOPERATOR>
+class MGInterfaceMatrix : public Subscriptor
+{
+public:
+ void
+ initialize(const LAPLACEOPERATOR &laplace)
+ {
+ this->laplace = &laplace;
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<typename LAPLACEOPERATOR::value_type>
+ &dst,
+ const LinearAlgebra::distributed::Vector<
+ typename LAPLACEOPERATOR::value_type> &src) const
+ {
+ laplace->vmult_interface_down(dst, src);
+ }
+
+ void
+ Tvmult(
+ LinearAlgebra::distributed::Vector<typename LAPLACEOPERATOR::value_type>
+ &dst,
+ const LinearAlgebra::distributed::Vector<
+ typename LAPLACEOPERATOR::value_type> &src) const
+ {
+ laplace->vmult_interface_up(dst, src);
+ }
+
+private:
+ SmartPointer<const LAPLACEOPERATOR> laplace;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const bool threaded)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ AffineConstraints<double> hanging_node_constraints;
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, double> fine_matrix;
+ fine_matrix.initialize(mapping,
+ dof,
+ mg_constrained_dofs,
+ dirichlet_boundary,
+ numbers::invalid_unsigned_int,
+ threaded);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(
+ mapping, dof, mg_constrained_dofs, dirichlet_boundary, level, threaded);
+ }
+ MGLevelObject<MGInterfaceMatrix<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ smoother_data[level].preconditioner->get_vector() =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename Number>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(8 - 2 * dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ deallog.push("nothread");
+ do_test<dim, fe_degree, fe_degree + 1, Number>(dof, false);
+ deallog.pop();
+ deallog.push("threaded");
+ do_test<dim, fe_degree, fe_degree + 1, Number>(dof, true);
+ deallog.pop();
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc,
+ argv,
+ testing_max_num_threads());
+
+ mpi_initlog();
+
+ test<2, 1, double>();
+ test<2, 2, float>();
+ test<3, 1, double>();
+}
--- /dev/null
+
+DEAL:nothread::Testing FE_Q<2>(1)
+DEAL:nothread::Number of degrees of freedom: 507
+DEAL:nothread:cg::Starting value 21.9317
+DEAL:nothread:cg::Convergence step 5 value 1.14537e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 507
+DEAL:threaded:cg::Starting value 21.9317
+DEAL:threaded:cg::Convergence step 5 value 1.14537e-06
+DEAL:nothread::Testing FE_Q<2>(1)
+DEAL:nothread::Number of degrees of freedom: 881
+DEAL:nothread:cg::Starting value 27.7669
+DEAL:nothread:cg::Convergence step 6 value 1.18996e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 881
+DEAL:threaded:cg::Starting value 27.7669
+DEAL:threaded:cg::Convergence step 6 value 1.18996e-06
+DEAL:nothread::Testing FE_Q<2>(1)
+DEAL:nothread::Number of degrees of freedom: 2147
+DEAL:nothread:cg::Starting value 43.2551
+DEAL:nothread:cg::Convergence step 6 value 1.86235e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 2147
+DEAL:threaded:cg::Starting value 43.2551
+DEAL:threaded:cg::Convergence step 6 value 1.86235e-06
+DEAL:nothread::Testing FE_Q<2>(1)
+DEAL:nothread::Number of degrees of freedom: 6517
+DEAL:nothread:cg::Starting value 76.9220
+DEAL:nothread:cg::Convergence step 6 value 3.14118e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 6517
+DEAL:threaded:cg::Starting value 76.9220
+DEAL:threaded:cg::Convergence step 6 value 3.14118e-06
+DEAL:nothread::Testing FE_Q<2>(2)
+DEAL:nothread::Number of degrees of freedom: 1935
+DEAL:nothread:cg::Starting value 43.0929
+DEAL:nothread:cg::Convergence step 5 value 3.22499e-06
+DEAL:threaded::Testing FE_Q<2>(2)
+DEAL:threaded::Number of degrees of freedom: 1935
+DEAL:threaded:cg::Starting value 43.0929
+DEAL:threaded:cg::Convergence step 5 value 3.22490e-06
+DEAL:nothread::Testing FE_Q<2>(2)
+DEAL:nothread::Number of degrees of freedom: 3403
+DEAL:nothread:cg::Starting value 55.4346
+DEAL:nothread:cg::Convergence step 6 value 8.67842e-07
+DEAL:threaded::Testing FE_Q<2>(2)
+DEAL:threaded::Number of degrees of freedom: 3403
+DEAL:threaded:cg::Starting value 55.4346
+DEAL:threaded:cg::Convergence step 6 value 8.67877e-07
+DEAL:nothread::Testing FE_Q<2>(2)
+DEAL:nothread::Number of degrees of freedom: 8417
+DEAL:nothread:cg::Starting value 87.1149
+DEAL:nothread:cg::Convergence step 6 value 5.47729e-07
+DEAL:threaded::Testing FE_Q<2>(2)
+DEAL:threaded::Number of degrees of freedom: 8417
+DEAL:threaded:cg::Starting value 87.1149
+DEAL:threaded:cg::Convergence step 6 value 5.47731e-07
+DEAL:nothread::Testing FE_Q<3>(1)
+DEAL:nothread::Number of degrees of freedom: 186
+DEAL:nothread:cg::Starting value 12.3693
+DEAL:nothread:cg::Convergence step 4 value 2.87808e-08
+DEAL:threaded::Testing FE_Q<3>(1)
+DEAL:threaded::Number of degrees of freedom: 186
+DEAL:threaded:cg::Starting value 12.3693
+DEAL:threaded:cg::Convergence step 4 value 2.87808e-08
+DEAL:nothread::Testing FE_Q<3>(1)
+DEAL:nothread::Number of degrees of freedom: 648
+DEAL:nothread:cg::Starting value 21.1424
+DEAL:nothread:cg::Convergence step 6 value 6.44935e-07
+DEAL:threaded::Testing FE_Q<3>(1)
+DEAL:threaded::Number of degrees of freedom: 648
+DEAL:threaded:cg::Starting value 21.1424
+DEAL:threaded:cg::Convergence step 6 value 6.44935e-07
+DEAL:nothread::Testing FE_Q<3>(1)
+DEAL:nothread::Number of degrees of freedom: 2930
+DEAL:nothread:cg::Starting value 47.1699
+DEAL:nothread:cg::Convergence step 7 value 2.56010e-06
+DEAL:threaded::Testing FE_Q<3>(1)
+DEAL:threaded::Number of degrees of freedom: 2930
+DEAL:threaded:cg::Starting value 47.1699
+DEAL:threaded:cg::Convergence step 7 value 2.56010e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// same as parallel_multigrid_adaptive_02, but using mg::SmootherRelaxation
+// rather than MGSmootherPrecondition
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>
+ fine_matrix;
+ std::shared_ptr<MatrixFree<dim, number>> fine_level_data(
+ new MatrixFree<dim, number>());
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_level_data[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ mg::SmootherRelaxation<SMOOTHER, LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(8 - 2 * dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 186
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 648
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 2930
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// same test as parallel_multigrid_adaptive_03 but using partition_color
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const MGConstrainedDoFs &mg_constrained_dofs,
+ const std::map<types::boundary_id, const Function<dim> *>
+ & dirichlet_boundary,
+ const unsigned int level,
+ const bool threaded)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ if (threaded)
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::partition_color;
+ else
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.tasks_block_size = 3;
+ addit_data.mg_level = level;
+ AffineConstraints<double> constraints;
+ if (level == numbers::invalid_unsigned_int)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ VectorTools::interpolate_boundary_values(dof_handler,
+ dirichlet_boundary,
+ constraints);
+ }
+ else
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler,
+ level,
+ relevant_dofs);
+ constraints.reinit(relevant_dofs);
+ constraints.add_lines(mg_constrained_dofs.get_boundary_indices(level));
+
+ const std::vector<types::global_dof_index> interface_indices =
+ mg_constrained_dofs.get_refinement_edge_indices(level)
+ .get_index_vector();
+ edge_constrained_indices.clear();
+ edge_constrained_indices.reserve(interface_indices.size());
+ edge_constrained_values.resize(interface_indices.size());
+ const IndexSet &locally_owned =
+ dof_handler.locally_owned_mg_dofs(level);
+ for (unsigned int i = 0; i < interface_indices.size(); ++i)
+ if (locally_owned.is_element(interface_indices[i]))
+ edge_constrained_indices.push_back(
+ locally_owned.index_within_set(interface_indices[i]));
+ have_interface_matrices =
+ Utilities::MPI::max((unsigned int)edge_constrained_indices.size(),
+ MPI_COMM_WORLD) > 0;
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ if (level != numbers::invalid_unsigned_int)
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ edge_constrained_values[i] = std::pair<number, number>(
+ src.local_element(edge_constrained_indices[i]),
+ dst.local_element(edge_constrained_indices[i]));
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+
+ // reset edge constrained values, multiply by unit matrix and add into
+ // destination
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ dst.local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].second + edge_constrained_values[i].first;
+ }
+ }
+
+ void
+ vmult_interface_down(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ // set zero Dirichlet values on the input vector (and remember the src and
+ // dst values because we need to reset them at the end)
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ const double src_val = src.local_element(edge_constrained_indices[i]);
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) = 0.;
+ edge_constrained_values[i] = std::pair<number, number>(
+ src_val, dst.local_element(edge_constrained_indices[i]));
+ }
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ dst.local_element(c) = 0.;
+ ++c;
+
+ // reset the src values
+ const_cast<LinearAlgebra::distributed::Vector<number> &>(src)
+ .local_element(edge_constrained_indices[i]) =
+ edge_constrained_values[i].first;
+ }
+ for (; c < dst.locally_owned_size(); ++c)
+ dst.local_element(c) = 0.;
+ }
+
+ void
+ vmult_interface_up(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ Assert(src.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ Assert(dst.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+
+ dst = 0;
+
+ if (!have_interface_matrices)
+ return;
+
+ LinearAlgebra::distributed::Vector<number> src_cpy(src);
+ unsigned int c = 0;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ for (; c < edge_constrained_indices[i]; ++c)
+ src_cpy.local_element(c) = 0.;
+ ++c;
+ }
+ for (; c < src_cpy.locally_owned_size(); ++c)
+ src_cpy.local_element(c) = 0.;
+
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src_cpy);
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ dst.local_element(edge_constrained_indices[i]) = 0.;
+ }
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ inverse_diagonal_entries.local_element(constrained_dofs[i]) = 1.;
+ for (unsigned int i = 0; i < edge_constrained_indices.size(); ++i)
+ {
+ inverse_diagonal_entries.local_element(edge_constrained_indices[i]) =
+ 1.;
+ }
+
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ std::vector<unsigned int> edge_constrained_indices;
+ mutable std::vector<std::pair<number, number>> edge_constrained_values;
+ bool have_interface_matrices;
+};
+
+
+
+template <typename LAPLACEOPERATOR>
+class MGInterfaceMatrix : public Subscriptor
+{
+public:
+ void
+ initialize(const LAPLACEOPERATOR &laplace)
+ {
+ this->laplace = &laplace;
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<typename LAPLACEOPERATOR::value_type>
+ &dst,
+ const LinearAlgebra::distributed::Vector<
+ typename LAPLACEOPERATOR::value_type> &src) const
+ {
+ laplace->vmult_interface_down(dst, src);
+ }
+
+ void
+ Tvmult(
+ LinearAlgebra::distributed::Vector<typename LAPLACEOPERATOR::value_type>
+ &dst,
+ const LinearAlgebra::distributed::Vector<
+ typename LAPLACEOPERATOR::value_type> &src) const
+ {
+ laplace->vmult_interface_up(dst, src);
+ }
+
+private:
+ SmartPointer<const LAPLACEOPERATOR> laplace;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const bool threaded)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ AffineConstraints<double> hanging_node_constraints;
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, double> fine_matrix;
+ fine_matrix.initialize(mapping,
+ dof,
+ mg_constrained_dofs,
+ dirichlet_boundary,
+ numbers::invalid_unsigned_int,
+ threaded);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(
+ mapping, dof, mg_constrained_dofs, dirichlet_boundary, level, threaded);
+ }
+ MGLevelObject<MGInterfaceMatrix<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, double> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ smoother_data[level].preconditioner->get_vector() =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, double>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename Number>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(8 - 2 * dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ deallog.push("threaded");
+ do_test<dim, fe_degree, fe_degree + 1, Number>(dof, true);
+ deallog.pop();
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ // The original issue with partition_color
+ // is hit with 2 threads and 4 cores.
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 2);
+
+ mpi_initlog();
+
+ test<2, 1, double>();
+}
--- /dev/null
+
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 507
+DEAL:threaded:cg::Starting value 21.9317
+DEAL:threaded:cg::Convergence step 5 value 1.14537e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 881
+DEAL:threaded:cg::Starting value 27.7669
+DEAL:threaded:cg::Convergence step 6 value 1.18996e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 2147
+DEAL:threaded:cg::Starting value 43.2551
+DEAL:threaded:cg::Convergence step 6 value 1.86235e-06
+DEAL:threaded::Testing FE_Q<2>(1)
+DEAL:threaded::Number of degrees of freedom: 6517
+DEAL:threaded:cg::Starting value 76.9220
+DEAL:threaded:cg::Convergence step 6 value 3.14118e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// similar to parallel_multigrid_adaptive_06ref but using
+// MGTransferBlockMatrixFree to solve block-diagonal matrix with Laplace
+// operator on diagonals. As expected, when we use a block vector with a single
+// block, we get the same results as the reference, non-block solution, i.e.
+//
+// DEAL:2d:cg::Starting value 21.93
+// DEAL:2d:cg::Convergence step 7 value 1.961e-07
+//
+//
+// What this test is really for is block operations. As expected we see
+// exactly the same number of iterations and the ratio of \sqrt(2) in values,
+// i.e.
+//
+// DEAL:2d:cg::Starting value 31.02
+// DEAL:2d:cg::Convergence step 7 value 2.774e-07
+
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+/**
+ * Block-Laplace operator with Block vector.
+ */
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename BlockVectorType =
+ LinearAlgebra::distributed::BlockVector<double>>
+class BlockLaplace : public Subscriptor
+{
+public:
+ using value_type = typename BlockVectorType::value_type;
+ using size_type = typename BlockVectorType::size_type;
+
+ BlockLaplace()
+ : Subscriptor()
+ {}
+
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, value_type>> data)
+ {
+ laplace.initialize(data);
+ }
+
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, value_type>> data,
+ const MGConstrainedDoFs &mg_constrained_dofs,
+ const unsigned int level)
+ {
+ laplace.initialize(data, mg_constrained_dofs, level);
+ }
+
+ void
+ vmult_interface_down(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.vmult_interface_down(dst.block(b), src.block(b));
+ }
+
+ void
+ vmult_interface_up(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.vmult_interface_up(dst.block(b), src.block(b));
+ }
+
+ void
+ vmult(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.vmult(dst.block(b), src.block(b));
+ }
+
+ void
+ Tvmult(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.Tvmult(dst.block(b), src.block(b));
+ }
+
+ void
+ vmult_add(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.vmult_add(dst.block(b), src.block(b));
+ }
+
+ void
+ Tvmult_add(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.Tvmult_add(dst.block(b), src.block(b));
+ }
+
+ void
+ precondition_Jacobi(BlockVectorType & dst,
+ const BlockVectorType &src,
+ const value_type omega) const
+ {
+ for (unsigned int b = 0; b < src.n_blocks(); ++b)
+ laplace.precondition_Jacobi(dst.block(b), src.block(b), omega);
+ }
+
+ void
+ compute_diagonal()
+ {
+ laplace.compute_diagonal();
+ }
+
+
+ virtual void
+ clear()
+ {
+ laplace.clear();
+ }
+
+private:
+ MatrixFreeOperators::LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ typename BlockVectorType::BlockType>
+ laplace;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::BlockVector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::BlockVector<Number> & dst,
+ const LinearAlgebra::distributed::BlockVector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::BlockVector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof, const unsigned int nb)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ BlockLaplace<dim,
+ fe_degree,
+ n_q_points_1d,
+ LinearAlgebra::distributed::BlockVector<number>>
+ fine_matrix;
+ std::shared_ptr<MatrixFree<dim, number>> fine_level_data(
+ new MatrixFree<dim, number>());
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+ LinearAlgebra::distributed::BlockVector<number> in(nb), sol(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ fine_level_data->initialize_dof_vector(in.block(b));
+ fine_level_data->initialize_dof_vector(sol.block(b));
+ }
+
+ in.collect_sizes();
+ sol.collect_sizes();
+
+ // set constant rhs vector
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.block(0).locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.block(0).get_partitioner()->local_to_global(i)))
+ in.block(0).local_element(i) = 1.;
+
+ for (unsigned int b = 1; b < nb; ++b)
+ in.block(b) = in.block(0);
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ BlockLaplace<dim,
+ fe_degree,
+ n_q_points_1d,
+ LinearAlgebra::distributed::BlockVector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ MGTransferBlockMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER = PreconditionJacobi<LevelMatrixType>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::BlockVector<number>>
+ mg_smoother;
+
+ mg_smoother.initialize(mg_matrices, typename SMOOTHER::AdditionalData(0.8));
+
+ mg::Matrix<LinearAlgebra::distributed::BlockVector<number>> mg_matrix(
+ mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::BlockVector<number>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::BlockVector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::BlockVector<number>,
+ MGTransferBlockMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::BlockVector<number>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test(const unsigned int nbands = 1)
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof, nbands);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ test<2, 3>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ test<3, 2>();
+ deallog.pop();
+ }
+
+ // 2 blocks
+ {
+ deallog.push("2d");
+ test<2, 1>(2);
+ test<2, 3>(2);
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>(2);
+ test<3, 2>(2);
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 7 value 1.961e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 8 value 2.956e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 7 value 2.063e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 7 value 7.253e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 64.26
+DEAL:2d:cg::Convergence step 9 value 1.536e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 83.11
+DEAL:2d:cg::Convergence step 9 value 8.264e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 131.0
+DEAL:2d:cg::Convergence step 9 value 1.071e-05
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 8 value 3.711e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 8 value 5.151e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 9 value 6.124e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 82.90
+DEAL:3d:cg::Convergence step 9 value 3.485e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 152.6
+DEAL:3d:cg::Convergence step 10 value 2.494e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 31.02
+DEAL:2d:cg::Convergence step 7 value 2.774e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 39.27
+DEAL:2d:cg::Convergence step 8 value 4.180e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 61.17
+DEAL:2d:cg::Convergence step 7 value 2.918e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 108.8
+DEAL:2d:cg::Convergence step 7 value 1.026e-05
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 90.87
+DEAL:2d:cg::Convergence step 9 value 2.172e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 117.5
+DEAL:2d:cg::Convergence step 9 value 1.169e-05
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 185.2
+DEAL:2d:cg::Convergence step 9 value 1.515e-05
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 44.14
+DEAL:3d:cg::Convergence step 8 value 5.248e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 77.78
+DEAL:3d:cg::Convergence step 8 value 7.285e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 107.7
+DEAL:3d:cg::Convergence step 9 value 8.661e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 117.2
+DEAL:3d:cg::Convergence step 9 value 4.929e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 215.8
+DEAL:3d:cg::Convergence step 10 value 3.527e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// same as parallel_multigrid_adaptive_02, but with Jacobi smoother.
+// The only reason for this test is to provide a reference for
+// parallel_multigrid_adaptive_06
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<double> & dst,
+ const LinearAlgebra::distributed::Vector<double> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>
+ fine_matrix;
+ std::shared_ptr<MatrixFree<dim, number>> fine_level_data(
+ new MatrixFree<dim, number>());
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+
+ LinearAlgebra::distributed::Vector<number> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_level_data[level].get_vector_partitioner());
+
+ MGTransferGlobalCoarsening<dim, LinearAlgebra::distributed::Vector<double>>
+ mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER = PreconditionJacobi<LevelMatrixType>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<double>>
+ mg_smoother;
+
+ mg_smoother.initialize(mg_matrices, typename SMOOTHER::AdditionalData(0.8));
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<double>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<
+ dim,
+ LinearAlgebra::distributed::Vector<double>,
+ MGTransferGlobalCoarsening<dim, LinearAlgebra::distributed::Vector<double>>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ {
+ deallog.push("2d");
+ test<2, 1>();
+ test<2, 3>();
+ deallog.pop();
+ deallog.push("3d");
+ test<3, 1>();
+ test<3, 2>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 21.93
+DEAL:2d:cg::Convergence step 7 value 1.961e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 27.77
+DEAL:2d:cg::Convergence step 8 value 2.956e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 43.26
+DEAL:2d:cg::Convergence step 7 value 2.063e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 76.92
+DEAL:2d:cg::Convergence step 7 value 7.253e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 64.26
+DEAL:2d:cg::Convergence step 9 value 1.536e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 83.11
+DEAL:2d:cg::Convergence step 9 value 8.264e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 131.0
+DEAL:2d:cg::Convergence step 9 value 1.071e-05
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 31.21
+DEAL:3d:cg::Convergence step 8 value 3.711e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 55.00
+DEAL:3d:cg::Convergence step 8 value 5.151e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 76.18
+DEAL:3d:cg::Convergence step 9 value 6.124e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 82.90
+DEAL:3d:cg::Convergence step 9 value 3.485e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 152.6
+DEAL:3d:cg::Convergence step 10 value 2.494e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// This test is similar to parallel_multigrid_adaptive_06 but we also test
+// for different polynomial degree in different blocks.
+// We expect to have the same iteration numbers as in
+// parallel_multigrid_adaptive_06 with repsect to the highest polynomial
+// degree used.
+
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include <algorithm>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+/**
+ * Block-Laplace operator with Block vector.
+ */
+template <int dim,
+ int fe_degree_1,
+ int fe_degree_2,
+ int n_q_points_1d,
+ typename BlockVectorType =
+ LinearAlgebra::distributed::BlockVector<double>>
+class BlockLaplace : public Subscriptor
+{
+public:
+ using value_type = typename BlockVectorType::value_type;
+ using size_type = typename BlockVectorType::size_type;
+
+ BlockLaplace()
+ : Subscriptor()
+ {}
+
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, value_type>> data)
+ {
+ laplace1.initialize(data, std::vector<unsigned int>(1, 0));
+ laplace2.initialize(data, std::vector<unsigned int>(1, 1));
+ }
+
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, value_type>> data,
+ const std::vector<MGConstrainedDoFs> &mg_constrained_dofs,
+ const unsigned int level)
+ {
+ laplace1.initialize(data,
+ mg_constrained_dofs[0],
+ level,
+ std::vector<unsigned int>(1, 0));
+ laplace2.initialize(data,
+ mg_constrained_dofs[1],
+ level,
+ std::vector<unsigned int>(1, 1));
+ }
+
+ void
+ vmult_interface_down(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.vmult_interface_down(dst.block(0), src.block(0));
+ laplace2.vmult_interface_down(dst.block(1), src.block(1));
+ }
+
+ void
+ vmult_interface_up(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.vmult_interface_up(dst.block(0), src.block(0));
+ laplace2.vmult_interface_up(dst.block(1), src.block(1));
+ }
+
+ void
+ vmult(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.vmult(dst.block(0), src.block(0));
+ laplace2.vmult(dst.block(1), src.block(1));
+ }
+
+ void
+ Tvmult(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.Tvmult(dst.block(0), src.block(0));
+ laplace2.Tvmult(dst.block(1), src.block(1));
+ }
+
+ void
+ vmult_add(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.vmult_add(dst.block(0), src.block(0));
+ laplace2.vmult_add(dst.block(1), src.block(1));
+ }
+
+ void
+ Tvmult_add(BlockVectorType &dst, const BlockVectorType &src) const
+ {
+ laplace1.Tvmult_add(dst.block(0), src.block(0));
+ laplace2.Tvmult_add(dst.block(1), src.block(1));
+ }
+
+ void
+ precondition_Jacobi(BlockVectorType & dst,
+ const BlockVectorType &src,
+ const value_type omega) const
+ {
+ laplace1.precondition_Jacobi(dst.block(0), src.block(0), omega);
+ laplace2.precondition_Jacobi(dst.block(1), src.block(1), omega);
+ }
+
+ void
+ compute_diagonal()
+ {
+ laplace1.compute_diagonal();
+ laplace2.compute_diagonal();
+ }
+
+
+ virtual void
+ clear()
+ {
+ laplace1.clear();
+ laplace2.clear();
+ }
+
+private:
+ MatrixFreeOperators::LaplaceOperator<dim,
+ fe_degree_1,
+ n_q_points_1d,
+ 1,
+ typename BlockVectorType::BlockType>
+ laplace1;
+ MatrixFreeOperators::LaplaceOperator<dim,
+ fe_degree_2,
+ n_q_points_1d,
+ 1,
+ typename BlockVectorType::BlockType>
+ laplace2;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::BlockVector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::BlockVector<Number> & dst,
+ const LinearAlgebra::distributed::BlockVector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::BlockVector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim,
+ int fe_degree_1,
+ int fe_degree_2,
+ int n_q_points_1d,
+ typename number>
+void
+do_test(const std::vector<const DoFHandler<dim> *> &dof)
+{
+ const unsigned int nb = 2;
+ if (std::is_same_v<number, float> == true)
+ {
+ deallog.push("float");
+ }
+ else
+ {}
+
+ for (unsigned int i = 0; i < dof.size(); ++i)
+ {
+ deallog << "Testing " << dof[i]->get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof[i]->n_dofs()
+ << std::endl;
+ }
+
+ std::vector<IndexSet> locally_relevant_dofs(dof.size());
+ for (unsigned int i = 0; i < dof.size(); ++i)
+ DoFTools::extract_locally_relevant_dofs(*dof[i], locally_relevant_dofs[i]);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ std::vector<AffineConstraints<double>> constraints(dof.size());
+ std::vector<const AffineConstraints<double> *> constraints_ptrs(dof.size());
+ for (unsigned int i = 0; i < dof.size(); ++i)
+ {
+ constraints[i].reinit(locally_relevant_dofs[i]);
+ DoFTools::make_hanging_node_constraints(*dof[i], constraints[i]);
+ VectorTools::interpolate_boundary_values(*dof[i],
+ dirichlet_boundary,
+ constraints[i]);
+ constraints[i].close();
+ constraints_ptrs[i] = &constraints[i];
+ }
+ QGauss<1> quad(n_q_points_1d);
+ constexpr int max_degree = std::max(fe_degree_1, fe_degree_2);
+ MappingQ<dim> mapping(max_degree);
+
+ typename MatrixFree<dim, number>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+
+ std::shared_ptr<MatrixFree<dim, double>> fine_level_data(
+ new MatrixFree<dim, double>());
+ fine_level_data->reinit(
+ mapping, dof, constraints_ptrs, quad, fine_level_additional_data);
+
+ BlockLaplace<dim,
+ fe_degree_1,
+ fe_degree_2,
+ n_q_points_1d,
+ LinearAlgebra::distributed::BlockVector<number>>
+ fine_matrix;
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+ LinearAlgebra::distributed::BlockVector<number> in(nb), sol(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ fine_level_data->initialize_dof_vector(in.block(b), b);
+ fine_level_data->initialize_dof_vector(sol.block(b), b);
+ }
+
+ in.collect_sizes();
+ sol.collect_sizes();
+
+ // set constant rhs vector
+ {
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+
+ hanging_node_constraints.reinit(locally_relevant_dofs[b]);
+ DoFTools::make_hanging_node_constraints(*dof[b],
+ hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.block(b).locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.block(b).get_partitioner()->local_to_global(i)))
+ in.block(b).local_element(i) = 1.;
+ }
+ }
+
+ // level constraints:
+ std::vector<MGConstrainedDoFs> mg_constrained_dofs(dof.size());
+ for (unsigned int i = 0; i < dof.size(); ++i)
+ {
+ mg_constrained_dofs[i].initialize(*dof[i]);
+ mg_constrained_dofs[i].make_zero_boundary_constraints(*dof[i], {0});
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ BlockLaplace<dim,
+ fe_degree_1,
+ fe_degree_2,
+ n_q_points_1d,
+ LinearAlgebra::distributed::BlockVector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof[0]->get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof[0]->get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof[0]->get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ std::vector<AffineConstraints<double>> level_constraints(dof.size());
+ std::vector<const AffineConstraints<double> *> level_constraints_ptrs(
+ dof.size());
+ for (unsigned int i = 0; i < dof.size(); ++i)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(*dof[i],
+ level,
+ relevant_dofs);
+ level_constraints[i].reinit(relevant_dofs);
+ level_constraints[i].add_lines(
+ mg_constrained_dofs[i].get_boundary_indices(level));
+ level_constraints[i].close();
+ level_constraints_ptrs[i] = &level_constraints[i];
+ }
+
+ mg_level_data[level].reinit(
+ mapping, dof, level_constraints_ptrs, quad, mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof[0]->get_triangulation().n_global_levels() -
+ 1);
+ for (unsigned int level = 0;
+ level < dof[0]->get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ MGTransferBlockMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER = PreconditionJacobi<LevelMatrixType>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::BlockVector<number>>
+ mg_smoother;
+
+ mg_smoother.initialize(mg_matrices, typename SMOOTHER::AdditionalData(0.8));
+
+ mg::Matrix<LinearAlgebra::distributed::BlockVector<number>> mg_matrix(
+ mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::BlockVector<number>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::BlockVector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::BlockVector<number>,
+ MGTransferBlockMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::BlockVector<number>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ if (std::is_same_v<number, float> == true)
+ deallog.pop();
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof[0]->get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree_1, int fe_degree_2>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ constexpr int max_degree = std::max(fe_degree_1, fe_degree_2);
+ const unsigned int n_runs = max_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ (((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2))))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe_1(fe_degree_1);
+ DoFHandler<dim> dof_1(tria);
+ dof_1.distribute_dofs(fe_1);
+ dof_1.distribute_mg_dofs();
+
+ FE_Q<dim> fe_2(fe_degree_2);
+ DoFHandler<dim> dof_2(tria);
+ dof_2.distribute_dofs(fe_2);
+ dof_2.distribute_mg_dofs();
+
+ std::vector<const DoFHandler<dim, dim> *> dh_ptrs{&dof_1, &dof_2};
+
+ constexpr int n_q_points_1d = std::max(fe_degree_1, fe_degree_2) + 1;
+ do_test<dim, fe_degree_1, fe_degree_2, n_q_points_1d, double>(dh_ptrs);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog();
+ deallog << std::setprecision(4);
+
+ // 2 blocks
+ {
+ deallog.push("2d");
+ test<2, 1, 1>();
+ deallog << std::endl;
+ test<2, 1, 3>();
+ deallog << std::endl;
+ test<2, 3, 1>();
+ deallog.pop();
+ deallog << std::endl;
+ deallog.push("3d");
+ test<3, 1, 1>();
+ deallog << std::endl;
+ test<3, 1, 2>();
+ deallog << std::endl;
+ test<3, 2, 1>();
+ deallog.pop();
+ }
+}
--- /dev/null
+
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 31.02
+DEAL:2d:cg::Convergence step 7 value 2.774e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 39.27
+DEAL:2d:cg::Convergence step 8 value 4.180e-07
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 61.17
+DEAL:2d:cg::Convergence step 7 value 2.918e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 6517
+DEAL:2d:cg::Starting value 108.8
+DEAL:2d:cg::Convergence step 7 value 1.026e-05
+DEAL:2d::
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d:cg::Starting value 67.90
+DEAL:2d:cg::Convergence step 9 value 1.556e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d:cg::Starting value 87.62
+DEAL:2d:cg::Convergence step 9 value 8.294e-06
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d:cg::Starting value 137.9
+DEAL:2d:cg::Convergence step 9 value 1.073e-05
+DEAL:2d::
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 4259
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 507
+DEAL:2d:cg::Starting value 67.90
+DEAL:2d:cg::Convergence step 9 value 1.556e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 7457
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 881
+DEAL:2d:cg::Starting value 87.62
+DEAL:2d:cg::Convergence step 9 value 8.294e-06
+DEAL:2d::Testing FE_Q<2>(3)
+DEAL:2d::Number of degrees of freedom: 18535
+DEAL:2d::Testing FE_Q<2>(1)
+DEAL:2d::Number of degrees of freedom: 2147
+DEAL:2d:cg::Starting value 137.9
+DEAL:2d:cg::Convergence step 9 value 1.073e-05
+DEAL::
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 44.14
+DEAL:3d:cg::Convergence step 8 value 5.248e-07
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 77.78
+DEAL:3d:cg::Convergence step 8 value 7.285e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 9566
+DEAL:3d:cg::Starting value 107.7
+DEAL:3d:cg::Convergence step 9 value 8.661e-06
+DEAL:3d::
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d:cg::Starting value 88.58
+DEAL:3d:cg::Convergence step 9 value 3.537e-06
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d:cg::Starting value 162.2
+DEAL:3d:cg::Convergence step 10 value 2.508e-06
+DEAL:3d::
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 7494
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 1103
+DEAL:3d:cg::Starting value 88.58
+DEAL:3d:cg::Convergence step 9 value 3.537e-06
+DEAL:3d::Testing FE_Q<3>(2)
+DEAL:3d::Number of degrees of freedom: 26548
+DEAL:3d::Testing FE_Q<3>(1)
+DEAL:3d::Number of degrees of freedom: 3694
+DEAL:3d:cg::Starting value 162.2
+DEAL:3d:cg::Convergence step 10 value 2.508e-06
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// similar to parallel_multigrid_adaptive_02 but without using a separate
+// transfer class that builds the appropriate vectors. Furthermore, we want to
+// avoid setting some vectors to zero in the cell loop. Rather,
+// MatrixFreeOperators::LaplaceOperator::adjust_ghost_range_if_necessary()
+// will do that - or rather a variant of that, given that we want to modify
+// the cell loop of the LaplaceOperator class and provide our own. This forces
+// us to reimplement a few things, but all ideas are the same as in the
+// matrix-free operators.
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+using namespace dealii::MatrixFreeOperators;
+
+
+template <int dim, int fe_degree, typename Number>
+class MyLaplaceOperator : public MatrixFreeOperators::LaplaceOperator<
+ dim,
+ fe_degree,
+ fe_degree + 1,
+ 1,
+ LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, Number>> data,
+ const MGConstrainedDoFs & mg_constrained_dofs,
+ const unsigned int level)
+ {
+ MatrixFreeOperators::Base<dim, LinearAlgebra::distributed::Vector<Number>>::
+ initialize(data,
+ mg_constrained_dofs,
+ level,
+ std::vector<unsigned int>({0}));
+
+ const std::vector<types::global_dof_index> interface_indices =
+ mg_constrained_dofs.get_refinement_edge_indices(level).get_index_vector();
+ vmult_edge_constrained_indices.clear();
+ vmult_edge_constrained_indices.reserve(interface_indices.size());
+ vmult_edge_constrained_values.resize(interface_indices.size());
+ const IndexSet &locally_owned =
+ this->data->get_dof_handler(0).locally_owned_mg_dofs(level);
+ for (unsigned int i = 0; i < interface_indices.size(); ++i)
+ if (locally_owned.is_element(interface_indices[i]))
+ vmult_edge_constrained_indices.push_back(
+ locally_owned.index_within_set(interface_indices[i]));
+ }
+
+ void
+ initialize(std::shared_ptr<const MatrixFree<dim, Number>> data,
+ const std::vector<unsigned int> & mask = {})
+ {
+ MatrixFreeOperators::Base<dim, LinearAlgebra::distributed::Vector<Number>>::
+ initialize(data, mask);
+ }
+
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ adjust_ghost_range_if_necessary(src);
+ adjust_ghost_range_if_necessary(dst);
+
+ for (unsigned int i = 0; i < vmult_edge_constrained_indices.size(); ++i)
+ {
+ vmult_edge_constrained_values[i] =
+ src.local_element(vmult_edge_constrained_indices[i]);
+ const_cast<LinearAlgebra::distributed::Vector<Number> &>(src)
+ .local_element(vmult_edge_constrained_indices[i]) = 0.;
+ }
+
+ // zero dst within the loop
+ this->data->cell_loop(
+ &MyLaplaceOperator::local_apply, this, dst, src, true);
+
+ for (auto i : this->data->get_constrained_dofs(0))
+ dst.local_element(i) = src.local_element(i);
+ for (unsigned int i = 0; i < vmult_edge_constrained_indices.size(); ++i)
+ {
+ dst.local_element(vmult_edge_constrained_indices[i]) =
+ vmult_edge_constrained_values[i];
+ const_cast<LinearAlgebra::distributed::Vector<Number> &>(src)
+ .local_element(vmult_edge_constrained_indices[i]) =
+ vmult_edge_constrained_values[i];
+ }
+ }
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.gather_evaluate(src, EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate_scatter(EvaluationFlags::gradients, dst);
+ }
+ }
+
+ void
+ adjust_ghost_range_if_necessary(
+ const LinearAlgebra::distributed::Vector<Number> &vec) const
+ {
+ if (vec.get_partitioner().get() ==
+ this->data->get_dof_info(0).vector_partitioner.get())
+ return;
+
+ Assert(
+ vec.get_partitioner()->locally_owned_size() ==
+ this->data->get_dof_info(0).vector_partitioner->locally_owned_size(),
+ ExcMessage("The vector passed to the vmult() function does not have "
+ "the correct size for compatibility with MatrixFree."));
+ LinearAlgebra::distributed::Vector<Number> copy_vec(vec);
+ this->data->initialize_dof_vector(
+ const_cast<LinearAlgebra::distributed::Vector<Number> &>(vec), 0);
+ const_cast<LinearAlgebra::distributed::Vector<Number> &>(vec)
+ .copy_locally_owned_data_from(copy_vec);
+ }
+
+ std::vector<unsigned int> vmult_edge_constrained_indices;
+
+ mutable std::vector<double> vmult_edge_constrained_values;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, constraints);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ // level constraints:
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ MappingQ<dim> mapping(fe_degree + 1);
+
+ MyLaplaceOperator<dim, fe_degree, double> fine_matrix;
+ std::shared_ptr<MatrixFree<dim, double>> fine_level_data(
+ new MatrixFree<dim, double>());
+
+ typename MatrixFree<dim, double>::AdditionalData fine_level_additional_data;
+ fine_level_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, double>::AdditionalData::none;
+ fine_level_additional_data.tasks_block_size = 3;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+ fine_matrix.compute_diagonal();
+
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ {
+ // this is to make it consistent with parallel_multigrid_adaptive.cc
+ AffineConstraints<double> hanging_node_constraints;
+ hanging_node_constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof, hanging_node_constraints);
+ hanging_node_constraints.close();
+
+ for (unsigned int i = 0; i < in.locally_owned_size(); ++i)
+ if (!hanging_node_constraints.is_constrained(
+ in.get_partitioner()->local_to_global(i)))
+ in.local_element(i) = 1.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = MyLaplaceOperator<dim, fe_degree, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<MatrixFree<dim, number>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(std::make_shared<MatrixFree<dim, number>>(
+ mg_level_data[level]),
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+ MGLevelObject<MGInterfaceOperator<LevelMatrixType>> mg_interface_matrices;
+ mg_interface_matrices.resize(0,
+ dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_level_data[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 6;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(3);
+
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ fine_matrix.clear();
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].clear();
+}
+
+
+
+template <int dim, int fe_degree>
+void
+test()
+{
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(6 - dim);
+ const unsigned int n_runs = fe_degree == 1 ? 6 - dim : 5 - dim;
+ for (unsigned int i = 0; i < n_runs; ++i)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tria.begin_active();
+ cell != tria.end();
+ ++cell)
+ if (cell->is_locally_owned() &&
+ ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2)))
+ cell->set_refine_flag();
+ tria.execute_coarsening_and_refinement();
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, double>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ mpi_initlog(true);
+
+ test<2, 2>();
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 1935
+DEAL:cg::Starting value 43.0929
+DEAL:cg:cg::Starting value 2.63785
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 0.000574845
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 4.62010e-05
+DEAL:cg:cg::Convergence step 1 value 6.77626e-21
+DEAL:cg:cg::Starting value 6.27180e-07
+DEAL:cg:cg::Convergence step 1 value 1.05879e-22
+DEAL:cg:cg::Starting value 3.19916e-08
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg::Convergence step 5 value 2.10775e-06
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 3403
+DEAL:cg::Starting value 55.4346
+DEAL:cg:cg::Starting value 3.96150
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 0.00121318
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 9.44668e-05
+DEAL:cg:cg::Convergence step 1 value 1.35525e-20
+DEAL:cg:cg::Starting value 1.80128e-06
+DEAL:cg:cg::Convergence step 1 value 2.11758e-22
+DEAL:cg:cg::Starting value 1.21766e-07
+DEAL:cg:cg::Convergence step 1 value 2.64698e-23
+DEAL:cg:cg::Starting value 5.04178e-09
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg::Convergence step 6 value 4.24128e-07
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 8417
+DEAL:cg::Starting value 87.1149
+DEAL:cg:cg::Starting value 9.09582
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 0.00294550
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 0.000242151
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 3.21426e-06
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 1.60211e-07
+DEAL:cg:cg::Convergence step 1 value 0.00000
+DEAL:cg:cg::Starting value 3.38024e-09
+DEAL:cg:cg::Convergence step 1 value 4.13590e-25
+DEAL:cg::Convergence step 6 value 2.56705e-07
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// test running a multigrid solver on continuous FE_Q finite elements with
+// MatrixFree data structures with parallel::fullydistributd::Triangulation
+// (otherwise similar to tests/matrix_free/parallel_multigrid_mf.cc)
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/fully_distributed_tria.h>
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const std::set<types::boundary_id> &dirichlet_boundaries,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.mg_level = level;
+
+ // extract the constraints due to Dirichlet boundary conditions
+ AffineConstraints<double> constraints;
+ Functions::ZeroFunction<dim> zero;
+ std::map<types::boundary_id, const Function<dim> *> functions;
+ for (std::set<types::boundary_id>::const_iterator it =
+ dirichlet_boundaries.begin();
+ it != dirichlet_boundaries.end();
+ ++it)
+ functions[*it] = &zero;
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, double> fine_matrix;
+ const std::set<types::boundary_id> dirichlet_boundaries = {0};
+ fine_matrix.initialize(mapping, dof, dirichlet_boundaries);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, dirichlet_boundaries, level);
+ }
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+
+ // temporarily disable deallog for the setup of the preconditioner that
+ // involves a CG solver for eigenvalue estimation
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename number>
+void
+test()
+{
+ for (unsigned int i = 5; i < 7; ++i)
+ {
+ dealii::Triangulation<dim> tria(
+ Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ GridTools::partition_triangulation_zorder(
+ Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD), tria);
+ GridTools::partition_multigrid_levels(tria);
+
+
+ parallel::fullydistributed::Triangulation<dim> tria_pft(MPI_COMM_WORLD);
+
+ // extract relevant information form pdt
+ auto construction_data = TriangulationDescription::Utilities::
+ create_description_from_triangulation(
+ tria,
+ MPI_COMM_WORLD,
+ TriangulationDescription::Settings::construct_multigrid_hierarchy);
+
+ // actually create triangulation
+ tria_pft.create_triangulation(construction_data);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria_pft);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, number>(dof);
+ }
+
+ if (false)
+ for (unsigned int i = 5; i < 7; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ parallel::fullydistributed::Triangulation<dim> tria_pft(MPI_COMM_WORLD);
+
+ // extract relevant information form pdt
+ auto construction_data = TriangulationDescription::Utilities::
+ create_description_from_triangulation(
+ tria,
+ MPI_COMM_WORLD,
+ TriangulationDescription::Settings::construct_multigrid_hierarchy);
+
+ // actually create triangulation
+ tria_pft.create_triangulation(construction_data);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria_pft);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, number>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ test<2, 1, double>();
+ test<2, 2, float>();
+
+ test<3, 1, double>();
+ test<3, 2, float>();
+ }
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 81
+DEAL:cg::Starting value 9.00000
+DEAL:cg::Convergence step 3 value 6.75256e-07
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 2.62465e-09
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 1.71224e-08
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 1089
+DEAL:cg::Starting value 33.0000
+DEAL:cg::Convergence step 4 value 4.31534e-08
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 125
+DEAL:cg::Starting value 11.1803
+DEAL:cg::Convergence step 3 value 4.38307e-07
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 3 value 1.02520e-06
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 4 value 5.99244e-09
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 70.0928
+DEAL:cg::Convergence step 4 value 5.81100e-08
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Similar test as parallel_multigrid_mf, but using the functionality of
+// PreconditionChebyshev to embed vector updates into the matrix-free loops of
+// a suitable operator class.
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator()
+ : n_calls_vmult(0)
+ {}
+
+ void
+ print_n_calls_special()
+ {
+ // round number of calls to make test more robust
+ if (n_calls_vmult > 0)
+ deallog
+ << "Approx. number of calls to special vmult for Operator of size "
+ << m() << ": " << (n_calls_vmult + 5) / 10 * 10 << std::endl;
+ }
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const std::set<types::boundary_id> &dirichlet_boundaries,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ n_calls_vmult = 0;
+ const QGauss<1> quad(dof_handler.get_fe().degree + 1);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.mg_level = level;
+
+ // extract the constraints due to Dirichlet boundary conditions
+ AffineConstraints<double> constraints;
+ Functions::ZeroFunction<dim> zero;
+ std::map<types::boundary_id, const Function<dim> *> functions;
+ for (std::set<types::boundary_id>::const_iterator it =
+ dirichlet_boundaries.begin();
+ it != dirichlet_boundaries.end();
+ ++it)
+ functions[*it] = &zero;
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src, true);
+ for (const unsigned int i : data.get_constrained_dofs())
+ dst.local_element(i) = src.local_element(i);
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src,
+ const std::function<void(const unsigned int, const unsigned int)>
+ &operation_before_loop,
+ const std::function<void(const unsigned int, const unsigned int)>
+ &operation_after_loop) const
+ {
+ ++n_calls_vmult;
+ data.cell_loop(&LaplaceOperator::local_apply,
+ this,
+ dst,
+ src,
+ operation_before_loop,
+ operation_after_loop);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+ for (const unsigned int i : data.get_constrained_dofs())
+ dst.local_element(i) += src.local_element(i);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ mutable unsigned int n_calls_vmult;
+};
+
+
+
+template <int dim, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ const unsigned int fe_degree = dof.get_fe().degree;
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, double> fine_matrix;
+ const std::set<types::boundary_id> dirichlet_boundaries = {0};
+ fine_matrix.initialize(mapping, dof, dirichlet_boundaries);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector, except boundary
+ in = 1.;
+ {
+ std::map<types::global_dof_index, double> boundary_values;
+ VectorTools::interpolate_boundary_values(dof,
+ 0,
+ Functions::ZeroFunction<dim>(),
+ boundary_values);
+ for (const auto it : boundary_values)
+ if (dof.locally_owned_dofs().is_element(it.first))
+ in(it.first) = 0.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = LaplaceOperator<dim, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, dirichlet_boundaries, level);
+ }
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ mg::SmootherRelaxation<SMOOTHER, LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 4;
+ smoother_data[level].eig_cg_n_iterations = 10;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+
+ mg_smoother.initialize(mg_matrices, smoother_data);
+ MGCoarseGridApplySmoother<LinearAlgebra::distributed::Vector<number>>
+ mg_coarse(mg_smoother);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+
+ // Require a fixed number of iterations rather than a tolerance, in order
+ // to make output more stable
+ IterationNumberControl control(6, 1e-15);
+
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ // Print statistics
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].print_n_calls_special();
+
+ fine_matrix.print_n_calls_special();
+}
+
+
+
+template <int dim, typename number>
+void
+test(const unsigned int fe_degree)
+{
+ for (unsigned int i = 6; i < 8; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, number>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ test<2, double>(1);
+ test<2, float>(3);
+
+ test<3, double>(1);
+ test<3, float>(2);
+ }
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 15.0000
+DEAL:cg::Convergence step 6 value 7.67890e-11
+DEAL::Approx. number of calls to special vmult for Operator of size 4: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 9: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 25: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 81: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 289: 50
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 1089
+DEAL:cg::Starting value 31.0000
+DEAL:cg::Convergence step 6 value 2.23750e-10
+DEAL::Approx. number of calls to special vmult for Operator of size 4: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 9: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 25: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 81: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 289: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 1089: 50
+DEAL::Testing FE_Q<2>(3)
+DEAL::Number of degrees of freedom: 2401
+DEAL:cg::Starting value 47.0000
+DEAL:cg::Convergence step 6 value 5.14228e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 16: 30
+DEAL::Approx. number of calls to special vmult for Operator of size 49: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 169: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 625: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 2401: 50
+DEAL::Testing FE_Q<2>(3)
+DEAL::Number of degrees of freedom: 9409
+DEAL:cg::Starting value 95.0000
+DEAL:cg::Convergence step 6 value 1.44454e-08
+DEAL::Approx. number of calls to special vmult for Operator of size 16: 30
+DEAL::Approx. number of calls to special vmult for Operator of size 49: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 169: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 625: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 2401: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 9409: 50
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 18.5203
+DEAL:cg::Convergence step 6 value 1.94706e-11
+DEAL::Approx. number of calls to special vmult for Operator of size 8: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 58.0948
+DEAL:cg::Convergence step 6 value 2.47598e-10
+DEAL::Approx. number of calls to special vmult for Operator of size 8: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 58.0948
+DEAL:cg::Convergence step 6 value 1.17825e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 35937
+DEAL:cg::Starting value 172.601
+DEAL:cg::Convergence step 6 value 4.79055e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 35937: 50
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Similar test as parallel_multigrid_mf, but using the functionality of
+// PreconditionChebyshev to embed vector updates into the matrix-free loops of
+// a suitable operator class and with additional renumbering of unknowns
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_renumbering.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator()
+ : n_calls_vmult(0)
+ {}
+
+ void
+ print_n_calls_special()
+ {
+ // round number of calls to make test more robust
+ if (n_calls_vmult > 0)
+ deallog
+ << "Approx. number of calls to special vmult for Operator of size "
+ << m() << ": " << (n_calls_vmult + 5) / 10 * 10 << std::endl;
+ }
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ DoFHandler<dim> & dof_handler,
+ const std::set<types::boundary_id> &dirichlet_boundaries,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ n_calls_vmult = 0;
+ const QGauss<1> quad(dof_handler.get_fe().degree + 1);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.mg_level = level;
+
+ // extract the constraints due to Dirichlet boundary conditions
+ AffineConstraints<double> constraints;
+ Functions::ZeroFunction<dim> zero;
+ std::map<types::boundary_id, const Function<dim> *> functions;
+ for (std::set<types::boundary_id>::const_iterator it =
+ dirichlet_boundaries.begin();
+ it != dirichlet_boundaries.end();
+ ++it)
+ functions[*it] = &zero;
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ DoFRenumbering::matrix_free_data_locality(dof_handler,
+ constraints,
+ addit_data);
+
+ constraints.clear();
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src, true);
+ for (const unsigned int i : data.get_constrained_dofs())
+ dst.local_element(i) = src.local_element(i);
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src,
+ const std::function<void(const unsigned int, const unsigned int)>
+ &operation_before_loop,
+ const std::function<void(const unsigned int, const unsigned int)>
+ &operation_after_loop) const
+ {
+ ++n_calls_vmult;
+ data.cell_loop(&LaplaceOperator::local_apply,
+ this,
+ dst,
+ src,
+ operation_before_loop,
+ operation_after_loop);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+ for (const unsigned int i : data.get_constrained_dofs())
+ dst.local_element(i) += src.local_element(i);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, -1, 0, 1, number> phi(data);
+
+ AlignedVector<VectorizedArray<number>> local_diagonal_vector(
+ phi.dofs_per_cell);
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+ mutable unsigned int n_calls_vmult;
+};
+
+
+
+template <int dim, typename number>
+void
+do_test(DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ const unsigned int fe_degree = dof.get_fe().degree;
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, double> fine_matrix;
+ const std::set<types::boundary_id> dirichlet_boundaries = {0};
+ fine_matrix.initialize(mapping, dof, dirichlet_boundaries);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector, except boundary
+ in = 1.;
+ {
+ std::map<types::global_dof_index, double> boundary_values;
+ VectorTools::interpolate_boundary_values(dof,
+ 0,
+ Functions::ZeroFunction<dim>(),
+ boundary_values);
+ for (const auto it : boundary_values)
+ if (dof.locally_owned_dofs().is_element(it.first))
+ in(it.first) = 0.;
+ }
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType = LaplaceOperator<dim, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, dirichlet_boundaries, level);
+ }
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ mg::SmootherRelaxation<SMOOTHER, LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 4;
+ smoother_data[level].eig_cg_n_iterations = 10;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+
+ mg_smoother.initialize(mg_matrices, smoother_data);
+ MGCoarseGridApplySmoother<LinearAlgebra::distributed::Vector<number>>
+ mg_coarse(mg_smoother);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+
+ // Require a fixed number of iterations rather than a tolerance, in order
+ // to make output more stable
+ IterationNumberControl control(6, 1e-15);
+
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+
+ // Print statistics
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ mg_matrices[level].print_n_calls_special();
+
+ fine_matrix.print_n_calls_special();
+}
+
+
+
+template <int dim, typename number>
+void
+test(const unsigned int fe_degree)
+{
+ for (unsigned int i = 6; i < 8; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, number>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ test<2, double>(1);
+ test<2, float>(3);
+
+ test<3, double>(1);
+ test<3, float>(2);
+ }
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 15.0000
+DEAL:cg::Convergence step 6 value 5.63311e-11
+DEAL::Approx. number of calls to special vmult for Operator of size 4: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 9: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 25: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 81: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 289: 50
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 1089
+DEAL:cg::Starting value 31.0000
+DEAL:cg::Convergence step 6 value 6.08657e-10
+DEAL::Approx. number of calls to special vmult for Operator of size 4: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 9: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 25: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 81: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 289: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 1089: 50
+DEAL::Testing FE_Q<2>(3)
+DEAL::Number of degrees of freedom: 2401
+DEAL:cg::Starting value 47.0000
+DEAL:cg::Convergence step 6 value 2.11509e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 16: 30
+DEAL::Approx. number of calls to special vmult for Operator of size 49: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 169: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 625: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 2401: 50
+DEAL::Testing FE_Q<2>(3)
+DEAL::Number of degrees of freedom: 9409
+DEAL:cg::Starting value 95.0000
+DEAL:cg::Convergence step 6 value 8.72760e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 16: 30
+DEAL::Approx. number of calls to special vmult for Operator of size 49: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 169: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 625: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 2401: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 9409: 50
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 18.5203
+DEAL:cg::Convergence step 6 value 2.77603e-11
+DEAL::Approx. number of calls to special vmult for Operator of size 8: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 58.0948
+DEAL:cg::Convergence step 6 value 3.05980e-10
+DEAL::Approx. number of calls to special vmult for Operator of size 8: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 40
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 58.0948
+DEAL:cg::Convergence step 6 value 1.26786e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 35937
+DEAL:cg::Starting value 172.601
+DEAL:cg::Convergence step 6 value 4.72892e-09
+DEAL::Approx. number of calls to special vmult for Operator of size 27: 20
+DEAL::Approx. number of calls to special vmult for Operator of size 125: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 729: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 4913: 50
+DEAL::Approx. number of calls to special vmult for Operator of size 35937: 50
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// same test as parallel_multigrid but using matrix-free transfer operations
+// (and including single-precision multigrid preconditioning)
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim,
+ int fe_degree,
+ int n_q_points_1d = fe_degree + 1,
+ typename number = double>
+class LaplaceOperator : public Subscriptor
+{
+public:
+ using value_type = number;
+
+ LaplaceOperator(){};
+
+ void
+ initialize(const Mapping<dim> & mapping,
+ const DoFHandler<dim> & dof_handler,
+ const std::set<types::boundary_id> &dirichlet_boundaries,
+ const unsigned int level = numbers::invalid_unsigned_int)
+ {
+ const QGauss<1> quad(n_q_points_1d);
+ typename MatrixFree<dim, number>::AdditionalData addit_data;
+ addit_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ addit_data.mg_level = level;
+
+ // extract the constraints due to Dirichlet boundary conditions
+ AffineConstraints<double> constraints;
+ Functions::ZeroFunction<dim> zero;
+ std::map<types::boundary_id, const Function<dim> *> functions;
+ for (std::set<types::boundary_id>::const_iterator it =
+ dirichlet_boundaries.begin();
+ it != dirichlet_boundaries.end();
+ ++it)
+ functions[*it] = &zero;
+ if (level == numbers::invalid_unsigned_int)
+ VectorTools::interpolate_boundary_values(dof_handler,
+ functions,
+ constraints);
+ else
+ {
+ std::vector<types::global_dof_index> local_dofs;
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(level),
+ endc = dof_handler.end(level);
+ for (; cell != endc; ++cell)
+ {
+ if (dof_handler.get_triangulation().locally_owned_subdomain() !=
+ numbers::invalid_subdomain_id &&
+ cell->level_subdomain_id() == numbers::artificial_subdomain_id)
+ continue;
+ const FiniteElement<dim> &fe = cell->get_fe();
+ local_dofs.resize(fe.dofs_per_face);
+
+ for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename DoFHandler<dim>::face_iterator face =
+ cell->face(face_no);
+ const types::boundary_id bi = face->boundary_id();
+ if (functions.find(bi) != functions.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ constraints.add_line(local_dofs[i]);
+ }
+ }
+ }
+ }
+ constraints.close();
+
+ data.reinit(mapping, dof_handler, constraints, quad, addit_data);
+
+ compute_inverse_diagonal();
+ }
+
+ void
+ vmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ dst = 0;
+ vmult_add(dst, src);
+ }
+
+ void
+ Tvmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ vmult_add(dst, src);
+ }
+
+ void
+ vmult_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ data.cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+
+ const std::vector<unsigned int> &constrained_dofs =
+ data.get_constrained_dofs();
+ for (unsigned int i = 0; i < constrained_dofs.size(); ++i)
+ dst.local_element(constrained_dofs[i]) +=
+ src.local_element(constrained_dofs[i]);
+ }
+
+ types::global_dof_index
+ m() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ types::global_dof_index
+ n() const
+ {
+ return data.get_vector_partitioner()->size();
+ }
+
+ number
+ el(const unsigned int row, const unsigned int col) const
+ {
+ AssertThrow(false,
+ ExcMessage("Matrix-free does not allow for entry access"));
+ return number();
+ }
+
+ void
+ initialize_dof_vector(
+ LinearAlgebra::distributed::Vector<number> &vector) const
+ {
+ if (!vector.partitioners_are_compatible(
+ *data.get_dof_info(0).vector_partitioner))
+ data.initialize_dof_vector(vector);
+ Assert(vector.partitioners_are_globally_compatible(
+ *data.get_dof_info(0).vector_partitioner),
+ ExcInternalError());
+ }
+
+ const LinearAlgebra::distributed::Vector<number> &
+ get_matrix_diagonal_inverse() const
+ {
+ Assert(inverse_diagonal_entries.size() > 0, ExcNotInitialized());
+ return inverse_diagonal_entries;
+ }
+
+ const std::shared_ptr<const Utilities::MPI::Partitioner> &
+ get_vector_partitioner() const
+ {
+ return data.get_vector_partitioner();
+ }
+
+
+private:
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ void
+ compute_inverse_diagonal()
+ {
+ data.initialize_dof_vector(inverse_diagonal_entries);
+ unsigned int dummy = 0;
+ data.cell_loop(&LaplaceOperator::local_diagonal_cell,
+ this,
+ inverse_diagonal_entries,
+ dummy);
+
+ for (unsigned int i = 0; i < inverse_diagonal_entries.locally_owned_size();
+ ++i)
+ if (std::abs(inverse_diagonal_entries.local_element(i)) > 1e-10)
+ inverse_diagonal_entries.local_element(i) =
+ 1. / inverse_diagonal_entries.local_element(i);
+ else
+ inverse_diagonal_entries.local_element(i) = 1.;
+ }
+
+ 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
+ {
+ FEEvaluation<dim, fe_degree, n_q_points_1d, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ phi.reinit(cell);
+
+ VectorizedArray<number> local_diagonal_vector[phi.tensor_dofs_per_cell];
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.begin_dof_values()[j] = VectorizedArray<number>();
+ phi.begin_dof_values()[i] = 1.;
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ local_diagonal_vector[i] = phi.begin_dof_values()[i];
+ }
+ for (unsigned int i = 0; i < phi.tensor_dofs_per_cell; ++i)
+ phi.begin_dof_values()[i] = local_diagonal_vector[i];
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+ MatrixFree<dim, number> data;
+ LinearAlgebra::distributed::Vector<number> inverse_diagonal_entries;
+};
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, double> fine_matrix;
+ const std::set<types::boundary_id> dirichlet_boundaries = {0};
+ fine_matrix.initialize(mapping, dof, dirichlet_boundaries);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ using LevelMatrixType =
+ LaplaceOperator<dim, fe_degree, n_q_points_1d, number>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ mg_matrices[level].initialize(mapping, dof, dirichlet_boundaries, level);
+ }
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners;
+ for (unsigned int level = mg_matrices.min_level();
+ level <= mg_matrices.max_level();
+ ++level)
+ partitioners.push_back(mg_matrices[level].get_vector_partitioner());
+
+ MGTransferMF<dim, number> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ auto preconditioner = std::make_shared<
+ DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>>();
+ preconditioner->reinit(mg_matrices[level].get_matrix_diagonal_inverse());
+ smoother_data[level].preconditioner = std::move(preconditioner);
+ }
+
+ // temporarily disable deallog for the setup of the preconditioner that
+ // involves a CG solver for eigenvalue estimation
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename number>
+void
+test()
+{
+ for (unsigned int i = 5; i < 7; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, number>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ test<2, 1, double>();
+ test<2, 2, float>();
+
+ test<3, 1, double>();
+ test<3, 2, float>();
+ }
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 81
+DEAL:cg::Starting value 9.00000
+DEAL:cg::Convergence step 3 value 6.75256e-07
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 2.62465e-09
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 1.71224e-08
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 1089
+DEAL:cg::Starting value 33.0000
+DEAL:cg::Convergence step 4 value 4.31534e-08
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 125
+DEAL:cg::Starting value 11.1803
+DEAL:cg::Convergence step 3 value 4.38307e-07
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 3 value 1.02520e-06
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 4 value 5.99244e-09
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 70.0928
+DEAL:cg::Convergence step 4 value 5.81100e-08
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2014 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// same test as parallel_multigrid_mf but using the Laplace operator from
+// MatrixFreeOperators::Laplace and handing the vector partitioning of those
+// operators to the MG transfer
+
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+
+template <typename MatrixType, typename Number>
+class MGCoarseIterative
+ : public MGCoarseGridBase<LinearAlgebra::distributed::Vector<Number>>
+{
+public:
+ MGCoarseIterative()
+ {}
+
+ void
+ initialize(const MatrixType &matrix)
+ {
+ coarse_matrix = &matrix;
+ }
+
+ virtual void
+ operator()(const unsigned int level,
+ LinearAlgebra::distributed::Vector<Number> & dst,
+ const LinearAlgebra::distributed::Vector<Number> &src) const
+ {
+ ReductionControl solver_control(1e4, 1e-50, 1e-10);
+ SolverCG<LinearAlgebra::distributed::Vector<Number>> solver_coarse(
+ solver_control);
+ solver_coarse.solve(*coarse_matrix, dst, src, PreconditionIdentity());
+ }
+
+ const MatrixType *coarse_matrix;
+};
+
+
+
+template <int dim, int fe_degree, int n_q_points_1d, typename number>
+void
+do_test(const DoFHandler<dim> &dof)
+{
+ deallog << "Testing " << dof.get_fe().get_name();
+ deallog << std::endl;
+ deallog << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
+
+ MappingQ<dim> mapping(fe_degree + 1);
+ MatrixFreeOperators::LaplaceOperator<
+ dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<double>>
+ fine_matrix;
+
+ // Dirichlet BC
+ Functions::ZeroFunction<dim> zero_function;
+ std::map<types::boundary_id, const Function<dim> *> dirichlet_boundary;
+ dirichlet_boundary[0] = &zero_function;
+
+ // fine-level constraints
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof, locally_relevant_dofs);
+ AffineConstraints<double> constraints;
+ constraints.reinit(locally_relevant_dofs);
+ VectorTools::interpolate_boundary_values(dof,
+ dirichlet_boundary,
+ constraints);
+ constraints.close();
+
+ std::shared_ptr<MatrixFree<dim, double>> fine_level_data(
+ new MatrixFree<dim, double>());
+
+ typename MatrixFree<dim, double>::AdditionalData fine_level_additional_data;
+ fine_level_data->reinit(mapping,
+ dof,
+ constraints,
+ QGauss<1>(n_q_points_1d),
+ fine_level_additional_data);
+
+ fine_matrix.initialize(fine_level_data);
+
+ LinearAlgebra::distributed::Vector<double> in, sol;
+ fine_matrix.initialize_dof_vector(in);
+ fine_matrix.initialize_dof_vector(sol);
+
+ // set constant rhs vector
+ in = 1.;
+
+ // set up multigrid in analogy to step-37
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(dof);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
+
+ using LevelMatrixType = MatrixFreeOperators::LaplaceOperator<
+ dim,
+ fe_degree,
+ n_q_points_1d,
+ 1,
+ LinearAlgebra::distributed::Vector<number>>;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGLevelObject<std::shared_ptr<MatrixFree<dim, number>>> mg_level_data;
+ mg_matrices.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ mg_level_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ typename MatrixFree<dim, number>::AdditionalData mg_additional_data;
+ mg_additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, number>::AdditionalData::none;
+ mg_additional_data.tasks_block_size = 3;
+ mg_additional_data.mg_level = level;
+
+ AffineConstraints<double> level_constraints;
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof, level, relevant_dofs);
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ mg_level_data[level].reset(new MatrixFree<dim, number>());
+ mg_level_data[level]->reinit(mapping,
+ dof,
+ level_constraints,
+ QGauss<1>(n_q_points_1d),
+ mg_additional_data);
+ mg_matrices[level].initialize(mg_level_data[level],
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].compute_diagonal();
+ }
+
+ MGTransferMF<dim, number> mg_transfer;
+ std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>> partitioners(
+ dof.get_triangulation().n_global_levels());
+ for (unsigned int level = 0; level < partitioners.size(); ++level)
+ partitioners[level] =
+ mg_level_data[level]->get_dof_info().vector_partitioner;
+ mg_transfer.build(dof, partitioners);
+
+ MGCoarseIterative<LevelMatrixType, number> mg_coarse;
+ mg_coarse.initialize(mg_matrices[0]);
+
+ using SMOOTHER =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<number>>;
+ MGSmootherPrecondition<LevelMatrixType,
+ SMOOTHER,
+ LinearAlgebra::distributed::Vector<number>>
+ mg_smoother;
+
+ MGLevelObject<typename SMOOTHER::AdditionalData> smoother_data;
+ smoother_data.resize(0, dof.get_triangulation().n_global_levels() - 1);
+ for (unsigned int level = 0;
+ level < dof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 5;
+ smoother_data[level].eig_cg_n_iterations = 15;
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+
+ // temporarily disable deallog for the setup of the preconditioner that
+ // involves a CG solver for eigenvalue estimation
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<number>> mg_matrix(mg_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<number>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<number>,
+ MGTransferMF<dim, number>>
+ preconditioner(dof, mg, mg_transfer);
+
+ {
+ // avoid output from inner (coarse-level) solver
+ deallog.depth_file(2);
+ ReductionControl control(30, 1e-20, 1e-7);
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(control);
+ solver.solve(fine_matrix, sol, in, preconditioner);
+ }
+}
+
+
+
+template <int dim, int fe_degree, typename number>
+void
+test()
+{
+ for (unsigned int i = 5; i < 7; ++i)
+ {
+ parallel::distributed::Triangulation<dim> tria(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tria);
+ tria.refine_global(i - dim);
+
+ FE_Q<dim> fe(fe_degree);
+ DoFHandler<dim> dof(tria);
+ dof.distribute_dofs(fe);
+ dof.distribute_mg_dofs();
+
+ do_test<dim, fe_degree, fe_degree + 1, number>(dof);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+ mpi_initlog();
+
+ {
+ test<2, 1, double>();
+ test<2, 2, float>();
+
+ test<3, 1, double>();
+ test<3, 2, float>();
+ }
+}
--- /dev/null
+
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 81
+DEAL:cg::Starting value 9.00000
+DEAL:cg::Convergence step 4 value 2.07070e-08
+DEAL::Testing FE_Q<2>(1)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 2.77789e-08
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 289
+DEAL:cg::Starting value 17.0000
+DEAL:cg::Convergence step 4 value 3.93059e-08
+DEAL::Testing FE_Q<2>(2)
+DEAL::Number of degrees of freedom: 1089
+DEAL:cg::Starting value 33.0000
+DEAL:cg::Convergence step 4 value 8.11904e-08
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 125
+DEAL:cg::Starting value 11.1803
+DEAL:cg::Convergence step 4 value 3.45976e-07
+DEAL::Testing FE_Q<3>(1)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 4 value 1.07425e-07
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 729
+DEAL:cg::Starting value 27.0000
+DEAL:cg::Convergence step 4 value 2.46943e-06
+DEAL::Testing FE_Q<3>(2)
+DEAL::Number of degrees of freedom: 4913
+DEAL:cg::Starting value 70.0928
+DEAL:cg::Convergence step 4 value 4.57526e-06
--- /dev/null
+/* ---------------------------------------------------------------------
+ *
+ * Copyright (C) 2009 - 2022 by the deal.II authors
+ *
+ * This file is part of the deal.II library.
+ *
+ * The deal.II library is free software; you can use it, redistribute
+ * it, and/or modify it under the terms of the GNU Lesser General
+ * Public License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * The full text of the license can be found in the file LICENSE.md at
+ * the top level directory of deal.II.
+ *
+ * ---------------------------------------------------------------------
+ *
+ * Authors: Katharina Kormann, Martin Kronbichler, Uppsala University,
+ * 2009-2012, updated to MPI version with parallel vectors in 2016
+ */
+
+// This test verifies that the first strategy for enforcing inhomogeneous
+// boundary conditions (i.e., using read_dof_values_plain to compute the
+// contribution of the constraints to the right hand side in assemble_rhs)
+// given in step-37 works.
+
+
+#include <deal.II/base/conditional_ostream.h>
+#include <deal.II/base/function.h>
+#include <deal.II/base/quadrature_lib.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <fstream>
+#include <iostream>
+
+#include "../tests.h"
+
+namespace Step37
+{
+ const unsigned int degree_finite_element = 2;
+
+ template <int dim>
+ class ManufacturedSolution : public Function<dim>
+ {
+ public:
+ virtual double
+ value(const Point<dim> &p,
+ const unsigned int /*component*/ = 0) const override
+ {
+ const double pi = numbers::PI;
+ return std::sin(pi * p[0]) + std::cos(pi * p[1]);
+ }
+ };
+
+
+
+ template <int dim>
+ class ManufacturedForcing : public Function<dim>
+ {
+ public:
+ virtual double
+ value(const Point<dim> &p,
+ const unsigned int /*compononent*/ = 0) const override
+ {
+ return value<double>(p);
+ }
+
+ template <typename number>
+ number
+ value(const Point<dim, number> &p) const
+ {
+ const double pi = numbers::PI;
+ const number d = 40.0 * p.square() + 1.0;
+ return 20 * pi * pi * std::cos(pi * p[1]) / d +
+ 20 * pi * pi * std::sin(pi * p[0]) / d +
+ 1600 * pi * p[0] * std::cos(pi * p[0]) / (d * d) -
+ 1600 * pi * p[1] * std::sin(pi * p[1]) / (d * d);
+ }
+ };
+
+
+ template <int dim>
+ class Coefficient : public Function<dim>
+ {
+ public:
+ Coefficient()
+ : Function<dim>()
+ {}
+
+ virtual double
+ value(const Point<dim> &p, const unsigned int component = 0) const override;
+
+ template <typename number>
+ number
+ value(const Point<dim, number> &p, const unsigned int component = 0) const;
+ };
+
+
+
+ template <int dim>
+ template <typename number>
+ number
+ Coefficient<dim>::value(const Point<dim, number> &p,
+ const unsigned int /*component*/) const
+ {
+ return 1. / (0.05 + 2. * p.square());
+ }
+
+
+
+ template <int dim>
+ double
+ Coefficient<dim>::value(const Point<dim> & p,
+ const unsigned int component) const
+ {
+ return value<double>(p, component);
+ }
+
+
+ template <int dim, int fe_degree, typename number>
+ class LaplaceOperator
+ : public MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::Vector<number>>
+ {
+ public:
+ using value_type = number;
+
+ LaplaceOperator();
+
+ void
+ clear() override;
+
+ void
+ evaluate_coefficient(const Coefficient<dim> &coefficient_function);
+
+ virtual void
+ compute_diagonal() override;
+
+ const Table<2, VectorizedArray<double>> &
+ get_coefficient() const
+ {
+ return coefficient;
+ }
+
+ private:
+ virtual void
+ apply_add(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const override;
+
+ 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;
+
+ void
+ local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const unsigned int & dummy,
+ const std::pair<unsigned int, unsigned int> &cell_range) const;
+
+ Table<2, VectorizedArray<number>> coefficient;
+ };
+
+
+
+ template <int dim, int fe_degree, typename number>
+ LaplaceOperator<dim, fe_degree, number>::LaplaceOperator()
+ : MatrixFreeOperators::Base<dim,
+ LinearAlgebra::distributed::Vector<number>>()
+ {}
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::clear()
+ {
+ coefficient.reinit(0, 0);
+ MatrixFreeOperators::Base<dim, LinearAlgebra::distributed::Vector<number>>::
+ clear();
+ }
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::evaluate_coefficient(
+ const Coefficient<dim> &coefficient_function)
+ {
+ const unsigned int n_cells = this->data->n_cell_batches();
+ FEEvaluation<dim, fe_degree, fe_degree + 1, 1, number> phi(*this->data);
+
+ coefficient.reinit(n_cells, phi.n_q_points);
+ for (unsigned int cell = 0; cell < n_cells; ++cell)
+ {
+ phi.reinit(cell);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ coefficient(cell, q) =
+ coefficient_function.value(phi.quadrature_point(q));
+ }
+ }
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::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
+ {
+ FEEvaluation<dim, fe_degree, fe_degree + 1, 1, number> phi(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ AssertDimension(coefficient.size(0), data.n_cell_batches());
+ AssertDimension(coefficient.size(1), phi.n_q_points);
+
+ phi.reinit(cell);
+ phi.read_dof_values(src);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(coefficient(cell, q) * phi.get_gradient(q), q);
+ phi.integrate(EvaluationFlags::gradients);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::apply_add(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ this->data->cell_loop(&LaplaceOperator::local_apply, this, dst, src);
+ }
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::compute_diagonal()
+ {
+ this->inverse_diagonal_entries.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ LinearAlgebra::distributed::Vector<number> &inverse_diagonal =
+ this->inverse_diagonal_entries->get_vector();
+ this->data->initialize_dof_vector(inverse_diagonal);
+ unsigned int dummy = 0;
+ this->data->cell_loop(&LaplaceOperator::local_compute_diagonal,
+ this,
+ inverse_diagonal,
+ dummy);
+
+ this->set_constrained_entries_to_one(inverse_diagonal);
+
+ for (unsigned int i = 0; i < inverse_diagonal.locally_owned_size(); ++i)
+ {
+ Assert(inverse_diagonal.local_element(i) > 0.,
+ ExcMessage("No diagonal entry in a positive definite operator "
+ "should be zero"));
+ inverse_diagonal.local_element(i) =
+ 1. / inverse_diagonal.local_element(i);
+ }
+ }
+
+
+
+ template <int dim, int fe_degree, typename number>
+ void
+ LaplaceOperator<dim, fe_degree, number>::local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> &dst,
+ const unsigned int &,
+ const std::pair<unsigned int, unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim, fe_degree, fe_degree + 1, 1, number> phi(data);
+
+ AlignedVector<VectorizedArray<number>> diagonal(phi.dofs_per_cell);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ AssertDimension(coefficient.size(0), data.n_cell_batches());
+ AssertDimension(coefficient.size(1), phi.n_q_points);
+
+ phi.reinit(cell);
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
+ phi.submit_dof_value(VectorizedArray<number>(), j);
+ phi.submit_dof_value(make_vectorized_array<number>(1.), i);
+
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ phi.submit_gradient(coefficient(cell, q) * phi.get_gradient(q),
+ q);
+ phi.integrate(EvaluationFlags::gradients);
+ diagonal[i] = phi.get_dof_value(i);
+ }
+ for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
+ phi.submit_dof_value(diagonal[i], i);
+ phi.distribute_local_to_global(dst);
+ }
+ }
+
+
+
+ template <int dim>
+ class LaplaceProblem
+ {
+ public:
+ LaplaceProblem();
+ void
+ run();
+
+ private:
+ void
+ setup_system();
+ void
+ assemble_rhs();
+ void
+ solve();
+ void
+ output_results(const unsigned int cycle) const;
+
+ parallel::distributed::Triangulation<dim> triangulation;
+
+ FE_Q<dim> fe;
+ DoFHandler<dim> dof_handler;
+
+ AffineConstraints<double> constraints;
+ using SystemMatrixType =
+ LaplaceOperator<dim, degree_finite_element, double>;
+ SystemMatrixType system_matrix;
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ using LevelMatrixType = LaplaceOperator<dim, degree_finite_element, float>;
+ MGLevelObject<LevelMatrixType> mg_matrices;
+
+ LinearAlgebra::distributed::Vector<double> solution;
+ LinearAlgebra::distributed::Vector<double> system_rhs;
+
+ ConditionalOStream pcout;
+ };
+
+
+
+ template <int dim>
+ LaplaceProblem<dim>::LaplaceProblem()
+ : triangulation(MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy)
+ , fe(degree_finite_element)
+ , dof_handler(triangulation)
+ , pcout(deallog.get_file_stream(),
+ Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0)
+ {}
+
+
+
+ template <int dim>
+ void
+ LaplaceProblem<dim>::setup_system()
+ {
+ system_matrix.clear();
+ mg_matrices.clear_elements();
+
+ dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs();
+
+ pcout << "Number of degrees of freedom: " << dof_handler.n_dofs()
+ << std::endl;
+
+ IndexSet locally_relevant_dofs;
+ DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
+
+ constraints.clear();
+ constraints.reinit(locally_relevant_dofs);
+ DoFTools::make_hanging_node_constraints(dof_handler, constraints);
+ VectorTools::interpolate_boundary_values(dof_handler,
+ 0,
+ ManufacturedSolution<dim>(),
+ constraints);
+ constraints.close();
+
+ {
+ typename MatrixFree<dim, double>::AdditionalData additional_data;
+ additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, double>::AdditionalData::none;
+ additional_data.mapping_update_flags =
+ (update_gradients | update_JxW_values | update_quadrature_points);
+ std::shared_ptr<MatrixFree<dim, double>> system_mf_storage(
+ new MatrixFree<dim, double>());
+ system_mf_storage->reinit(MappingQ1<dim>{},
+ dof_handler,
+ constraints,
+ QGauss<1>(fe.degree + 1),
+ additional_data);
+ system_matrix.initialize(system_mf_storage);
+ }
+
+ system_matrix.evaluate_coefficient(Coefficient<dim>());
+
+ system_matrix.initialize_dof_vector(solution);
+ system_matrix.initialize_dof_vector(system_rhs);
+
+ const unsigned int nlevels = triangulation.n_global_levels();
+ mg_matrices.resize(0, nlevels - 1);
+
+ const std::set<types::boundary_id> dirichlet_boundary = {0};
+ mg_constrained_dofs.initialize(dof_handler);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof_handler,
+ dirichlet_boundary);
+
+ for (unsigned int level = 0; level < nlevels; ++level)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler,
+ level,
+ relevant_dofs);
+ AffineConstraints<double> level_constraints;
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ typename MatrixFree<dim, float>::AdditionalData additional_data;
+ additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, float>::AdditionalData::none;
+ additional_data.mapping_update_flags =
+ (update_gradients | update_JxW_values | update_quadrature_points);
+ additional_data.mg_level = level;
+ std::shared_ptr<MatrixFree<dim, float>> mg_mf_storage_level(
+ new MatrixFree<dim, float>());
+ mg_mf_storage_level->reinit(MappingQ1<dim>{},
+ dof_handler,
+ level_constraints,
+ QGauss<1>(fe.degree + 1),
+ additional_data);
+
+ mg_matrices[level].initialize(mg_mf_storage_level,
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].evaluate_coefficient(Coefficient<dim>());
+ }
+ }
+
+
+
+ template <int dim>
+ void
+ LaplaceProblem<dim>::assemble_rhs()
+ {
+ solution = 0.0;
+ constraints.distribute(solution);
+ solution.update_ghost_values();
+ system_rhs = 0.0;
+
+ const Table<2, VectorizedArray<double>> &coefficient =
+ system_matrix.get_coefficient();
+ ManufacturedForcing<dim> forcing;
+
+ FEEvaluation<dim, degree_finite_element> phi(
+ *system_matrix.get_matrix_free());
+ for (unsigned int cell = 0;
+ cell < system_matrix.get_matrix_free()->n_cell_batches();
+ ++cell)
+ {
+ phi.reinit(cell);
+ phi.read_dof_values_plain(solution);
+ phi.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < phi.n_q_points; ++q)
+ {
+ phi.submit_gradient(-coefficient(cell, q) * phi.get_gradient(q), q);
+ phi.submit_value(forcing.value(phi.quadrature_point(q)), q);
+ }
+ phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
+ phi.distribute_local_to_global(system_rhs);
+ }
+ system_rhs.compress(VectorOperation::add);
+ }
+
+
+
+ template <int dim>
+ void
+ LaplaceProblem<dim>::solve()
+ {
+ MGTransferMF<dim, float> mg_transfer(mg_constrained_dofs);
+ mg_transfer.build(dof_handler);
+
+ using SmootherType =
+ PreconditionChebyshev<LevelMatrixType,
+ LinearAlgebra::distributed::Vector<float>>;
+ mg::SmootherRelaxation<SmootherType,
+ LinearAlgebra::distributed::Vector<float>>
+ mg_smoother;
+ MGLevelObject<typename SmootherType::AdditionalData> smoother_data;
+ smoother_data.resize(0, triangulation.n_global_levels() - 1);
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ {
+ if (level > 0)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 4;
+ smoother_data[level].eig_cg_n_iterations = 10;
+ }
+ else
+ {
+ smoother_data[0].smoothing_range = 1e-3;
+ smoother_data[0].degree = numbers::invalid_unsigned_int;
+ smoother_data[0].eig_cg_n_iterations = mg_matrices[0].m();
+ }
+ mg_matrices[level].compute_diagonal();
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ MGCoarseGridApplySmoother<LinearAlgebra::distributed::Vector<float>>
+ mg_coarse;
+ mg_coarse.initialize(mg_smoother);
+
+ mg::Matrix<LinearAlgebra::distributed::Vector<float>> mg_matrix(
+ mg_matrices);
+
+ MGLevelObject<MatrixFreeOperators::MGInterfaceOperator<LevelMatrixType>>
+ mg_interface_matrices;
+ mg_interface_matrices.resize(0, triangulation.n_global_levels() - 1);
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+ mg::Matrix<LinearAlgebra::distributed::Vector<float>> mg_interface(
+ mg_interface_matrices);
+
+ Multigrid<LinearAlgebra::distributed::Vector<float>> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+
+ PreconditionMG<dim,
+ LinearAlgebra::distributed::Vector<float>,
+ MGTransferMF<dim, float>>
+ preconditioner(dof_handler, mg, mg_transfer);
+
+ SolverControl solver_control(100, 1e-12 * system_rhs.l2_norm());
+ SolverCG<LinearAlgebra::distributed::Vector<double>> cg(solver_control);
+
+ constraints.set_zero(solution);
+ cg.solve(system_matrix, solution, system_rhs, preconditioner);
+
+ constraints.distribute(solution);
+ }
+
+
+
+ template <int dim>
+ void
+ LaplaceProblem<dim>::output_results(const unsigned int cycle) const
+ {
+ if (triangulation.n_global_active_cells() > 1000000)
+ return;
+
+ Vector<double> errors;
+ errors.reinit(triangulation.n_active_cells());
+ solution.update_ghost_values();
+ VectorTools::integrate_difference(dof_handler,
+ solution,
+ ManufacturedSolution<dim>(),
+ errors,
+ QIterated<dim>(QTrapezoid<1>(), 4),
+ VectorTools::NormType::Linfty_norm);
+ double max_cell_error = 1.0;
+ if (errors.begin() != errors.end())
+ max_cell_error = *std::max_element(errors.begin(), errors.end());
+ max_cell_error = Utilities::MPI::max(max_cell_error, MPI_COMM_WORLD);
+ Assert(max_cell_error != 0.0, ExcInternalError());
+ pcout << "max error: " << max_cell_error << '\n';
+ static double error = max_cell_error;
+ pcout << "error ratio: "
+ << Utilities::MPI::max(error, MPI_COMM_WORLD) / max_cell_error
+ << '\n';
+ error = max_cell_error;
+ }
+
+
+
+ template <int dim>
+ void
+ LaplaceProblem<dim>::run()
+ {
+ for (unsigned int cycle = 0; cycle < 8 - dim; ++cycle)
+ {
+ pcout << "Cycle " << cycle << std::endl;
+
+ if (cycle == 0)
+ {
+ GridGenerator::hyper_cube(triangulation, 0., 1.);
+ triangulation.refine_global(3 - dim);
+ }
+ triangulation.refine_global(1);
+ setup_system();
+ assemble_rhs();
+ solve();
+ output_results(cycle);
+ pcout << std::endl;
+ }
+ }
+} // namespace Step37
+
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+ MPILogInitAll mpi_log;
+
+ {
+ Step37::LaplaceProblem<2> laplace_problem;
+ laplace_problem.run();
+ }
+
+ {
+ Step37::LaplaceProblem<3> laplace_problem;
+ laplace_problem.run();
+ }
+}
--- /dev/null
+
+Cycle 0
+Number of degrees of freedom: 81
+DEAL:0:cg::Starting value 45.0807
+DEAL:0:cg::Convergence step 7 value 2.65304e-12
+max error: 0.00772526
+error ratio: 1.00000
+
+Cycle 1
+Number of degrees of freedom: 289
+DEAL:0:cg::Starting value 68.5863
+DEAL:0:cg::Convergence step 7 value 3.81082e-12
+max error: 0.000971239
+error ratio: 7.95402
+
+Cycle 2
+Number of degrees of freedom: 1089
+DEAL:0:cg::Starting value 95.4381
+DEAL:0:cg::Convergence step 7 value 7.14371e-12
+max error: 0.000120278
+error ratio: 8.07497
+
+Cycle 3
+Number of degrees of freedom: 4225
+DEAL:0:cg::Starting value 131.732
+DEAL:0:cg::Convergence step 7 value 1.44204e-11
+max error: 1.49228e-05
+error ratio: 8.05998
+
+Cycle 4
+Number of degrees of freedom: 16641
+DEAL:0:cg::Starting value 183.473
+DEAL:0:cg::Convergence step 7 value 2.54095e-11
+max error: 1.85713e-06
+error ratio: 8.03544
+
+Cycle 5
+Number of degrees of freedom: 66049
+DEAL:0:cg::Starting value 257.379
+DEAL:0:cg::Convergence step 7 value 3.94318e-11
+max error: 2.31590e-07
+error ratio: 8.01904
+
+Cycle 0
+Number of degrees of freedom: 125
+DEAL:0:cg::Starting value 6.44073
+DEAL:0:cg::Convergence step 7 value 4.64523e-13
+max error: 0.0499110
+error ratio: 1.00000
+
+Cycle 1
+Number of degrees of freedom: 729
+DEAL:0:cg::Starting value 8.68642
+DEAL:0:cg::Convergence step 7 value 5.79753e-13
+max error: 0.00756448
+error ratio: 6.59807
+
+Cycle 2
+Number of degrees of freedom: 4913
+DEAL:0:cg::Starting value 9.47362
+DEAL:0:cg::Convergence step 7 value 6.67651e-13
+max error: 0.000965192
+error ratio: 7.83728
+
+Cycle 3
+Number of degrees of freedom: 35937
+DEAL:0:cg::Starting value 9.30402
+DEAL:0:cg::Convergence step 7 value 9.36336e-13
+max error: 0.000120048
+error ratio: 8.04008
+
+Cycle 4
+Number of degrees of freedom: 274625
+DEAL:0:cg::Starting value 8.99023
+DEAL:0:cg::Convergence step 7 value 1.22268e-12
+max error: 1.49140e-05
+error ratio: 8.04933
+
+
+DEAL:1:cg::Starting value 45.0807
+DEAL:1:cg::Convergence step 7 value 2.65304e-12
+DEAL:1:cg::Starting value 68.5863
+DEAL:1:cg::Convergence step 7 value 3.81082e-12
+DEAL:1:cg::Starting value 95.4381
+DEAL:1:cg::Convergence step 7 value 7.14371e-12
+DEAL:1:cg::Starting value 131.732
+DEAL:1:cg::Convergence step 7 value 1.44204e-11
+DEAL:1:cg::Starting value 183.473
+DEAL:1:cg::Convergence step 7 value 2.54095e-11
+DEAL:1:cg::Starting value 257.379
+DEAL:1:cg::Convergence step 7 value 3.94318e-11
+DEAL:1:cg::Starting value 6.44073
+DEAL:1:cg::Convergence step 7 value 4.64523e-13
+DEAL:1:cg::Starting value 8.68642
+DEAL:1:cg::Convergence step 7 value 5.79753e-13
+DEAL:1:cg::Starting value 9.47362
+DEAL:1:cg::Convergence step 7 value 6.67651e-13
+DEAL:1:cg::Starting value 9.30402
+DEAL:1:cg::Convergence step 7 value 9.36336e-13
+DEAL:1:cg::Starting value 8.99023
+DEAL:1:cg::Convergence step 7 value 1.22268e-12
+
+
+DEAL:2:cg::Starting value 45.0807
+DEAL:2:cg::Convergence step 7 value 2.65304e-12
+DEAL:2:cg::Starting value 68.5863
+DEAL:2:cg::Convergence step 7 value 3.81082e-12
+DEAL:2:cg::Starting value 95.4381
+DEAL:2:cg::Convergence step 7 value 7.14371e-12
+DEAL:2:cg::Starting value 131.732
+DEAL:2:cg::Convergence step 7 value 1.44204e-11
+DEAL:2:cg::Starting value 183.473
+DEAL:2:cg::Convergence step 7 value 2.54095e-11
+DEAL:2:cg::Starting value 257.379
+DEAL:2:cg::Convergence step 7 value 3.94318e-11
+DEAL:2:cg::Starting value 6.44073
+DEAL:2:cg::Convergence step 7 value 4.64523e-13
+DEAL:2:cg::Starting value 8.68642
+DEAL:2:cg::Convergence step 7 value 5.79753e-13
+DEAL:2:cg::Starting value 9.47362
+DEAL:2:cg::Convergence step 7 value 6.67651e-13
+DEAL:2:cg::Starting value 9.30402
+DEAL:2:cg::Convergence step 7 value 9.36336e-13
+DEAL:2:cg::Starting value 8.99023
+DEAL:2:cg::Convergence step 7 value 1.22268e-12
+
+
+DEAL:3:cg::Starting value 45.0807
+DEAL:3:cg::Convergence step 7 value 2.65304e-12
+DEAL:3:cg::Starting value 68.5863
+DEAL:3:cg::Convergence step 7 value 3.81082e-12
+DEAL:3:cg::Starting value 95.4381
+DEAL:3:cg::Convergence step 7 value 7.14371e-12
+DEAL:3:cg::Starting value 131.732
+DEAL:3:cg::Convergence step 7 value 1.44204e-11
+DEAL:3:cg::Starting value 183.473
+DEAL:3:cg::Convergence step 7 value 2.54095e-11
+DEAL:3:cg::Starting value 257.379
+DEAL:3:cg::Convergence step 7 value 3.94318e-11
+DEAL:3:cg::Starting value 6.44073
+DEAL:3:cg::Convergence step 7 value 4.64523e-13
+DEAL:3:cg::Starting value 8.68642
+DEAL:3:cg::Convergence step 7 value 5.79753e-13
+DEAL:3:cg::Starting value 9.47362
+DEAL:3:cg::Convergence step 7 value 6.67651e-13
+DEAL:3:cg::Starting value 9.30402
+DEAL:3:cg::Convergence step 7 value 9.36336e-13
+DEAL:3:cg::Starting value 8.99023
+DEAL:3:cg::Convergence step 7 value 1.22268e-12
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2012 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// test for correctness of matrix free implementation for multigrid stokes
+
+
+#include <deal.II/base/function.h>
+#include <deal.II/base/index_set.h>
+#include <deal.II/base/logstream.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/symmetric_tensor.h>
+#include <deal.II/base/utilities.h>
+
+#include <deal.II/distributed/grid_refinement.h>
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_renumbering.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+#include <deal.II/fe/fe_values.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+
+#include <deal.II/lac/affine_constraints.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/generic_linear_algebra.h>
+#include <deal.II/lac/precondition.h>
+#include <deal.II/lac/solver_cg.h>
+#include <deal.II/lac/solver_gmres.h>
+#include <deal.II/lac/vector.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/operators.h>
+
+#include <deal.II/multigrid/mg_coarse.h>
+#include <deal.II/multigrid/mg_constrained_dofs.h>
+#include <deal.II/multigrid/mg_matrix.h>
+#include <deal.II/multigrid/mg_smoother.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+#include <deal.II/multigrid/multigrid.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include <cmath>
+#include <sstream>
+
+#include "../tests.h"
+
+
+unsigned int minlevel = 0;
+const unsigned int velocity_degree = 2;
+
+double pressure_scaling = 1.0;
+
+namespace StokesClass
+{
+ class QuietException
+ {};
+
+ namespace StokesSolver
+ {
+ /**
+ * Implement the block Schur preconditioner for the Stokes system.
+ */
+ template <class StokesMatrixType,
+ class MassMatrixType,
+ class PreconditionerA,
+ class PreconditionerMp>
+ class BlockSchurPreconditioner : public Subscriptor
+ {
+ public:
+ /**
+ * brief Constructor
+ *
+ * S The entire Stokes matrix
+ * Spre The matrix whose blocks are used in the definition of
+ * the preconditioning of the Stokes matrix, i.e. containing
+ *approximations of the A and S blocks. Mppreconditioner Preconditioner
+ *object for the Schur complement, typically chosen as the mass matrix.
+ * Apreconditioner Preconditioner object for the matrix A.
+ * do_solve_A A flag indicating whether we should actually solve with
+ * the matrix $A$, or only apply one preconditioner step with it.
+ * A_block_tolerance The tolerance for the CG solver which computes
+ * the inverse of the A block.
+ * S_block_tolerance The tolerance for the CG solver which computes
+ * the inverse of the S block (Schur complement matrix).
+ **/
+ BlockSchurPreconditioner(const StokesMatrixType &S,
+ const MassMatrixType & Mass,
+ const PreconditionerMp &Mppreconditioner,
+ const PreconditionerA & Apreconditioner,
+ const bool do_solve_A,
+ const double A_block_tolerance,
+ const double S_block_tolerance);
+
+ /**
+ * Matrix vector product with this preconditioner object.
+ */
+ void
+ vmult(LinearAlgebra::distributed::BlockVector<double> & dst,
+ const LinearAlgebra::distributed::BlockVector<double> &src) const;
+
+ unsigned int
+ n_iterations_A() const;
+ unsigned int
+ n_iterations_S() const;
+
+ private:
+ /**
+ * References to the various matrix object this preconditioner works on.
+ */
+ const StokesMatrixType &stokes_matrix;
+ const MassMatrixType & mass_matrix;
+ const PreconditionerMp &mp_preconditioner;
+ const PreconditionerA & a_preconditioner;
+
+ /**
+ * Whether to actually invert the $\tilde A$ part of the preconditioner
+ *matrix or to just apply a single preconditioner step with it.
+ **/
+ const bool do_solve_A;
+ mutable unsigned int n_iterations_A_;
+ mutable unsigned int n_iterations_S_;
+ const double A_block_tolerance;
+ const double S_block_tolerance;
+ };
+
+
+ template <class StokesMatrixType,
+ class MassMatrixType,
+ class PreconditionerA,
+ class PreconditionerMp>
+ BlockSchurPreconditioner<StokesMatrixType,
+ MassMatrixType,
+ PreconditionerA,
+ PreconditionerMp>::
+ BlockSchurPreconditioner(const StokesMatrixType &S,
+ const MassMatrixType & Mass,
+ const PreconditionerMp &Mppreconditioner,
+ const PreconditionerA & Apreconditioner,
+ const bool do_solve_A,
+ const double A_block_tolerance,
+ const double S_block_tolerance)
+ : stokes_matrix(S)
+ , mass_matrix(Mass)
+ , mp_preconditioner(Mppreconditioner)
+ , a_preconditioner(Apreconditioner)
+ , do_solve_A(do_solve_A)
+ , n_iterations_A_(0)
+ , n_iterations_S_(0)
+ , A_block_tolerance(A_block_tolerance)
+ , S_block_tolerance(S_block_tolerance)
+ {}
+
+ template <class StokesMatrixType,
+ class MassMatrixType,
+ class PreconditionerA,
+ class PreconditionerMp>
+ unsigned int
+ BlockSchurPreconditioner<StokesMatrixType,
+ MassMatrixType,
+ PreconditionerA,
+ PreconditionerMp>::n_iterations_A() const
+ {
+ return n_iterations_A_;
+ }
+
+ template <class StokesMatrixType,
+ class MassMatrixType,
+ class PreconditionerA,
+ class PreconditionerMp>
+ unsigned int
+ BlockSchurPreconditioner<StokesMatrixType,
+ MassMatrixType,
+ PreconditionerA,
+ PreconditionerMp>::n_iterations_S() const
+ {
+ return n_iterations_S_;
+ }
+
+ template <class StokesMatrixType,
+ class MassMatrixType,
+ class PreconditionerA,
+ class PreconditionerMp>
+ void
+ BlockSchurPreconditioner<StokesMatrixType,
+ MassMatrixType,
+ PreconditionerA,
+ PreconditionerMp>::
+ vmult(LinearAlgebra::distributed::BlockVector<double> & dst,
+ const LinearAlgebra::distributed::BlockVector<double> &src) const
+ {
+ LinearAlgebra::distributed::BlockVector<double> utmp(src);
+
+ // first solve with the bottom left block, which we have built
+ // as a mass matrix with the inverse of the viscosity
+ {
+ SolverControl solver_control(1000,
+ src.block(1).l2_norm() * S_block_tolerance,
+ false,
+ false);
+
+ SolverCG<LinearAlgebra::distributed::Vector<double>> solver(
+ solver_control);
+ try
+ {
+ dst.block(1) = 0.0;
+ solver.solve(mass_matrix,
+ dst.block(1),
+ src.block(1),
+ mp_preconditioner);
+ n_iterations_S_ += solver_control.last_step();
+ }
+ // if the solver fails, report the error from processor 0 with some
+ // additional information about its location, and throw a quiet
+ // exception on all other processors
+ catch (const std::exception &exc)
+ {
+ if (Utilities::MPI::this_mpi_process(
+ src.block(0).get_mpi_communicator()) == 0)
+ AssertThrow(
+ false,
+ ExcMessage(
+ std::string(
+ "The iterative (bottom right) solver in BlockSchurPreconditioner::vmult "
+ "did not converge to a tolerance of " +
+ Utilities::to_string(solver_control.tolerance()) +
+ ". It reported the following error:\n\n") +
+ exc.what())) else throw QuietException();
+ }
+ dst.block(1) *= -1.0;
+ }
+
+ // apply the top right block
+ {
+ LinearAlgebra::distributed::BlockVector<double> dst_tmp(dst);
+ dst_tmp.block(0) = 0.0;
+ stokes_matrix.vmult(utmp, dst_tmp); // B^T
+ utmp.block(0) *= -1.0;
+ utmp.block(0) += src.block(0);
+ }
+
+ // now either solve with the top left block (if do_solve_A==true)
+ // or just apply one preconditioner sweep (for the first few
+ // iterations of our two-stage outer GMRES iteration)
+ if (do_solve_A == true)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+ else
+ {
+ a_preconditioner.vmult(dst.block(0), utmp.block(0));
+ n_iterations_A_ += 1;
+ }
+ }
+ } // namespace StokesSolver
+
+
+ // Parameters for Sinker example
+ double beta = 10.0;
+ double delta = 200.0;
+ double omega = 0.1;
+
+ template <int dim>
+ struct Sinker
+ {
+ unsigned int problem_dim;
+ unsigned int n_sinkers;
+ std::vector<Point<dim>> centers;
+ double DR_mu;
+ double mu_min;
+ double mu_max;
+ };
+
+ template <int dim>
+ class Viscosity
+ {
+ public:
+ Viscosity(const Sinker<dim> &sink);
+ virtual double
+ value(const Point<dim> &p, const unsigned int component = 0) const;
+ virtual void
+ value_list(const std::vector<Point<dim>> &points,
+ std::vector<double> & values,
+ const unsigned int component = 0) const;
+
+ Sinker<dim> sinker;
+ };
+ template <int dim>
+ Viscosity<dim>::Viscosity(const Sinker<dim> &sink)
+ {
+ sinker = sink;
+ }
+ template <int dim>
+ double
+ Viscosity<dim>::value(const Point<dim> &p,
+ const unsigned int /*component*/) const
+ {
+ double Chi = 1.0;
+ for (unsigned int s = 0; s < sinker.n_sinkers; ++s)
+ {
+ double dist = p.distance(sinker.centers[s]);
+ double temp =
+ 1 - std::exp(-delta * std::pow(std::max(0.0, dist - omega / 2.0), 2));
+ Chi *= temp;
+ }
+ return (sinker.mu_max - sinker.mu_min) * (1 - Chi) + sinker.mu_min;
+ }
+ template <int dim>
+ void
+ Viscosity<dim>::value_list(const std::vector<Point<dim>> &points,
+ std::vector<double> & values,
+ const unsigned int component) const
+ {
+ Assert(values.size() == points.size(),
+ ExcDimensionMismatch(values.size(), points.size()));
+ Assert(component == 0, ExcIndexRange(component, 0, 1));
+ const unsigned int n_points = points.size();
+ for (unsigned int i = 0; i < n_points; ++i)
+ values[i] = value(points[i], component);
+ }
+
+ template <int dim>
+ class RightHandSide
+ {
+ public:
+ RightHandSide(const Sinker<dim> &sink);
+ Sinker<dim> sinker;
+ virtual void
+ vector_value(const Point<dim> &p, Vector<double> &value) const;
+ };
+ template <int dim>
+ RightHandSide<dim>::RightHandSide(const Sinker<dim> &sink)
+ {
+ sinker = sink;
+ }
+ template <int dim>
+ void
+ RightHandSide<dim>::vector_value(const Point<dim> &p,
+ Vector<double> & values) const
+ {
+ double Chi = 1.0;
+ for (unsigned int s = 0; s < sinker.n_sinkers; ++s)
+ {
+ double dist = p.distance(sinker.centers[s]);
+ double temp =
+ 1 - std::exp(-delta * std::pow(std::max(0.0, dist - omega / 2.0), 2));
+ Chi *= temp;
+ }
+
+ if (sinker.problem_dim == 2)
+ {
+ values[0] = 0;
+ values[1] = beta * (Chi - 1.0);
+ values[2] = 0;
+ }
+ else if (sinker.problem_dim == 3)
+ {
+ values[0] = 0;
+ values[1] = 0;
+ values[2] = beta * (Chi - 1.0);
+ values[3] = 0;
+ }
+ return;
+ }
+
+ template <int dim>
+ class ExactSolution_BoundaryValues : public Function<dim>
+ {
+ public:
+ ExactSolution_BoundaryValues()
+ : Function<dim>(dim + 1)
+ {}
+ virtual void
+ vector_value(const Point<dim> &p, Vector<double> &value) const;
+ };
+ template <int dim>
+ void
+ ExactSolution_BoundaryValues<dim>::vector_value(const Point<dim> &p,
+ Vector<double> &values) const
+ {
+ (void)p;
+ for (unsigned int i = 0; i < values.size(); ++i)
+ values(i) = 0.0;
+ return;
+ }
+
+ template <int dim>
+ class ExactSolution_BoundaryValues_u : public Function<dim>
+ {
+ public:
+ ExactSolution_BoundaryValues_u()
+ : Function<dim>(dim)
+ {}
+ virtual void
+ vector_value(const Point<dim> &p, Vector<double> &value) const;
+ };
+ template <int dim>
+ void
+ ExactSolution_BoundaryValues_u<dim>::vector_value(
+ const Point<dim> &p,
+ Vector<double> & values) const
+ {
+ (void)p;
+ for (unsigned int i = 0; i < values.size(); ++i)
+ values(i) = 0.0;
+ return;
+ }
+
+
+
+ template <int dim, int degree_v, typename number>
+ class StokesOperator
+ : public MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::BlockVector<number>>
+ {
+ public:
+ StokesOperator()
+ : MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::BlockVector<number>>()
+ {}
+ void
+ clear();
+ void
+ evaluate_2_x_viscosity(const Viscosity<dim> &viscosity_function);
+ virtual void
+ compute_diagonal();
+
+ private:
+ virtual void
+ apply_add(LinearAlgebra::distributed::BlockVector<number> & dst,
+ const LinearAlgebra::distributed::BlockVector<number> &src) const;
+
+ void
+ local_apply(const dealii::MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::BlockVector<number> & dst,
+ const LinearAlgebra::distributed::BlockVector<number> &src,
+ const std::pair<unsigned int, unsigned int> &cell_range) const;
+
+ Table<2, VectorizedArray<number>> viscosity_x_2;
+ };
+ template <int dim, int degree_v, typename number>
+ void
+ StokesOperator<dim, degree_v, number>::clear()
+ {
+ viscosity_x_2.reinit(0, 0);
+ MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::BlockVector<number>>::clear();
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ StokesOperator<dim, degree_v, number>::evaluate_2_x_viscosity(
+ const Viscosity<dim> &viscosity_function)
+ {
+ const unsigned int n_cells = this->data->n_cell_batches();
+ FEEvaluation<dim, degree_v, degree_v + 1, dim, number> velocity(*this->data,
+ 0);
+ viscosity_x_2.reinit(n_cells, velocity.n_q_points);
+ for (unsigned int cell = 0; cell < n_cells; ++cell)
+ {
+ velocity.reinit(cell);
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ VectorizedArray<number> return_value =
+ make_vectorized_array<number>(1.);
+ for (unsigned int i = 0; i < VectorizedArray<number>::size(); ++i)
+ {
+ Point<dim> p;
+ for (unsigned int d = 0; d < dim; ++d)
+ {
+ p(d) = velocity.quadrature_point(q)(d)[i];
+ }
+ return_value[i] = 2.0 * viscosity_function.value(p);
+ }
+ viscosity_x_2(cell, q) = return_value;
+ }
+ }
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ StokesOperator<dim, degree_v, number>::local_apply(
+ const dealii::MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::BlockVector<number> & dst,
+ const LinearAlgebra::distributed::BlockVector<number> &src,
+ const std::pair<unsigned int, unsigned int> & cell_range) const
+ {
+ using vector_t = VectorizedArray<number>;
+ FEEvaluation<dim, degree_v, degree_v + 1, dim, number> velocity(data, 0);
+ FEEvaluation<dim, degree_v - 1, degree_v + 1, 1, number> pressure(data, 1);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ velocity.reinit(cell);
+ velocity.read_dof_values(src.block(0));
+ velocity.evaluate(EvaluationFlags::gradients);
+ pressure.reinit(cell);
+ pressure.read_dof_values(src.block(1));
+ pressure.evaluate(EvaluationFlags::values);
+
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ SymmetricTensor<2, dim, vector_t> sym_grad_u =
+ velocity.get_symmetric_gradient(q);
+ vector_t pres = pressure.get_value(q);
+ vector_t div = -trace(sym_grad_u);
+ pressure.submit_value(div, q);
+
+ sym_grad_u *= viscosity_x_2(cell, q);
+ // subtract p * I
+ for (unsigned int d = 0; d < dim; ++d)
+ sym_grad_u[d][d] -= pres;
+
+ velocity.submit_symmetric_gradient(sym_grad_u, q);
+ }
+
+ velocity.integrate(EvaluationFlags::gradients);
+ velocity.distribute_local_to_global(dst.block(0));
+ pressure.integrate(EvaluationFlags::values);
+ pressure.distribute_local_to_global(dst.block(1));
+ }
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ StokesOperator<dim, degree_v, number>::apply_add(
+ LinearAlgebra::distributed::BlockVector<number> & dst,
+ const LinearAlgebra::distributed::BlockVector<number> &src) const
+ {
+ MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::BlockVector<number>>::data
+ ->cell_loop(&StokesOperator::local_apply, this, dst, src);
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ StokesOperator<dim, degree_v, number>::compute_diagonal()
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+ template <int dim, int degree_p, typename number>
+ class MassMatrixOperator
+ : public MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::Vector<number>>
+ {
+ public:
+ MassMatrixOperator()
+ : MatrixFreeOperators::Base<dim,
+ LinearAlgebra::distributed::Vector<number>>()
+ {}
+ void
+ clear();
+ void
+ evaluate_1_over_viscosity(const Viscosity<dim> &viscosity_function);
+ virtual void
+ compute_diagonal();
+
+ private:
+ virtual void
+ apply_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const;
+
+ void
+ local_apply(const dealii::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;
+
+ void
+ local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const unsigned int & dummy,
+ const std::pair<unsigned int, unsigned int> &cell_range) const;
+
+ Table<2, VectorizedArray<number>> one_over_viscosity;
+ };
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::clear()
+ {
+ one_over_viscosity.reinit(0, 0);
+ MatrixFreeOperators::Base<dim, LinearAlgebra::distributed::Vector<number>>::
+ clear();
+ }
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::evaluate_1_over_viscosity(
+ const Viscosity<dim> &viscosity_function)
+ {
+ const unsigned int n_cells = this->data->n_cell_batches();
+ FEEvaluation<dim, degree_p, degree_p + 2, 1, number> pressure(*this->data,
+ 0);
+ one_over_viscosity.reinit(n_cells, pressure.n_q_points);
+ for (unsigned int cell = 0; cell < n_cells; ++cell)
+ {
+ pressure.reinit(cell);
+ for (unsigned int q = 0; q < pressure.n_q_points; ++q)
+ {
+ VectorizedArray<number> return_value =
+ make_vectorized_array<number>(1.);
+ for (unsigned int i = 0; i < VectorizedArray<number>::size(); ++i)
+ {
+ Point<dim> p;
+ for (unsigned int d = 0; d < dim; ++d)
+ p(d) = pressure.quadrature_point(q)(d)[i];
+ return_value[i] = 1.0 / viscosity_function.value(p);
+ }
+ one_over_viscosity(cell, q) = return_value;
+ }
+ }
+ }
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::local_apply(
+ const dealii::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
+ {
+ FEEvaluation<dim, degree_p, degree_p + 2, 1, number> pressure(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ AssertDimension(one_over_viscosity.size(0), data.n_cell_batches());
+ AssertDimension(one_over_viscosity.size(1), pressure.n_q_points);
+
+ pressure.reinit(cell);
+ pressure.read_dof_values(src);
+ pressure.evaluate(EvaluationFlags::values);
+ for (unsigned int q = 0; q < pressure.n_q_points; ++q)
+ pressure.submit_value(one_over_viscosity(cell, q) *
+ pressure.get_value(q),
+ q);
+ pressure.integrate(EvaluationFlags::values);
+ pressure.distribute_local_to_global(dst);
+ }
+ }
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::apply_add(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ MatrixFreeOperators::Base<dim,
+ LinearAlgebra::distributed::Vector<number>>::data
+ ->cell_loop(&MassMatrixOperator::local_apply, this, dst, src);
+ }
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::compute_diagonal()
+ {
+ this->inverse_diagonal_entries.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ this->diagonal_entries.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+
+ LinearAlgebra::distributed::Vector<number> &inverse_diagonal =
+ this->inverse_diagonal_entries->get_vector();
+ LinearAlgebra::distributed::Vector<number> &diagonal =
+ this->diagonal_entries->get_vector();
+
+ unsigned int dummy = 0;
+ this->data->initialize_dof_vector(inverse_diagonal);
+ this->data->initialize_dof_vector(diagonal);
+
+ this->data->cell_loop(&MassMatrixOperator::local_compute_diagonal,
+ this,
+ diagonal,
+ dummy);
+
+ this->set_constrained_entries_to_one(diagonal);
+ inverse_diagonal = diagonal;
+ const unsigned int local_size = inverse_diagonal.locally_owned_size();
+ for (unsigned int i = 0; i < local_size; ++i)
+ {
+ Assert(inverse_diagonal.local_element(i) > 0.,
+ ExcMessage("No diagonal entry in a positive definite operator "
+ "should be zero"));
+ inverse_diagonal.local_element(i) =
+ 1. / inverse_diagonal.local_element(i);
+ }
+ }
+ template <int dim, int degree_p, typename number>
+ void
+ MassMatrixOperator<dim, degree_p, number>::local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> &dst,
+ const unsigned int &,
+ const std::pair<unsigned int, unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim, degree_p, degree_p + 2, 1, number> pressure(data, 0);
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ pressure.reinit(cell);
+ AlignedVector<VectorizedArray<number>> diagonal(pressure.dofs_per_cell);
+ for (unsigned int i = 0; i < pressure.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < pressure.dofs_per_cell; ++j)
+ pressure.begin_dof_values()[j] = VectorizedArray<number>();
+ pressure.begin_dof_values()[i] = make_vectorized_array<number>(1.);
+
+ pressure.evaluate(EvaluationFlags::values);
+ for (unsigned int q = 0; q < pressure.n_q_points; ++q)
+ pressure.submit_value(one_over_viscosity(cell, q) *
+ pressure.get_value(q),
+ q);
+ pressure.integrate(EvaluationFlags::values);
+
+ diagonal[i] = pressure.begin_dof_values()[i];
+ }
+
+ for (unsigned int i = 0; i < pressure.dofs_per_cell; ++i)
+ pressure.begin_dof_values()[i] = diagonal[i];
+ pressure.distribute_local_to_global(dst);
+ }
+ }
+
+
+ template <int dim, int degree_v, typename number>
+ class ABlockOperator : public MatrixFreeOperators::
+ Base<dim, LinearAlgebra::distributed::Vector<number>>
+ {
+ public:
+ ABlockOperator()
+ : MatrixFreeOperators::Base<dim,
+ LinearAlgebra::distributed::Vector<number>>()
+ {}
+ void
+ clear();
+ void
+ evaluate_2_x_viscosity(const Viscosity<dim> &viscosity_function);
+ virtual void
+ compute_diagonal();
+
+ private:
+ virtual void
+ apply_add(LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const;
+
+ void
+ local_apply(const dealii::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;
+
+ void
+ local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const unsigned int & dummy,
+ const std::pair<unsigned int, unsigned int> &cell_range) const;
+
+ Table<2, VectorizedArray<number>> viscosity_x_2;
+ };
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::clear()
+ {
+ viscosity_x_2.reinit(0, 0);
+ MatrixFreeOperators::Base<dim, LinearAlgebra::distributed::Vector<number>>::
+ clear();
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::evaluate_2_x_viscosity(
+ const Viscosity<dim> &viscosity_function)
+ {
+ const unsigned int n_cells = this->data->n_cell_batches();
+ FEEvaluation<dim, degree_v, degree_v + 1, dim, number> velocity(*this->data,
+ 0);
+ viscosity_x_2.reinit(n_cells, velocity.n_q_points);
+ for (unsigned int cell = 0; cell < n_cells; ++cell)
+ {
+ velocity.reinit(cell);
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ VectorizedArray<number> return_value =
+ make_vectorized_array<number>(1.);
+ for (unsigned int i = 0; i < VectorizedArray<number>::size(); ++i)
+ {
+ Point<dim> p;
+ for (unsigned int d = 0; d < dim; ++d)
+ {
+ p(d) = velocity.quadrature_point(q)(d)[i];
+ }
+ return_value[i] = 2.0 * viscosity_function.value(p);
+ }
+ viscosity_x_2(cell, q) = return_value;
+ }
+ }
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::local_apply(
+ const dealii::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
+ {
+ FEEvaluation<dim, degree_v, degree_v + 1, dim, number> velocity(data);
+
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ AssertDimension(viscosity_x_2.size(0), data.n_cell_batches());
+ AssertDimension(viscosity_x_2.size(1), velocity.n_q_points);
+
+ velocity.reinit(cell);
+ velocity.read_dof_values(src);
+ velocity.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ velocity.submit_symmetric_gradient(
+ viscosity_x_2(cell, q) * velocity.get_symmetric_gradient(q), q);
+ }
+ velocity.integrate(EvaluationFlags::gradients);
+ velocity.distribute_local_to_global(dst);
+ }
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::apply_add(
+ LinearAlgebra::distributed::Vector<number> & dst,
+ const LinearAlgebra::distributed::Vector<number> &src) const
+ {
+ MatrixFreeOperators::Base<dim,
+ LinearAlgebra::distributed::Vector<number>>::data
+ ->cell_loop(&ABlockOperator::local_apply, this, dst, src);
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::compute_diagonal()
+ {
+ this->inverse_diagonal_entries.reset(
+ new DiagonalMatrix<LinearAlgebra::distributed::Vector<number>>());
+ LinearAlgebra::distributed::Vector<number> &inverse_diagonal =
+ this->inverse_diagonal_entries->get_vector();
+ this->data->initialize_dof_vector(inverse_diagonal);
+ unsigned int dummy = 0;
+ this->data->cell_loop(&ABlockOperator::local_compute_diagonal,
+ this,
+ inverse_diagonal,
+ dummy);
+
+ this->set_constrained_entries_to_one(inverse_diagonal);
+
+ for (unsigned int i = 0; i < inverse_diagonal.locally_owned_size(); ++i)
+ {
+ Assert(inverse_diagonal.local_element(i) > 0.,
+ ExcMessage("No diagonal entry in a positive definite operator "
+ "should be zero"));
+ inverse_diagonal.local_element(i) =
+ 1. / inverse_diagonal.local_element(i);
+ }
+ }
+ template <int dim, int degree_v, typename number>
+ void
+ ABlockOperator<dim, degree_v, number>::local_compute_diagonal(
+ const MatrixFree<dim, number> & data,
+ LinearAlgebra::distributed::Vector<number> &dst,
+ const unsigned int &,
+ const std::pair<unsigned int, unsigned int> &cell_range) const
+ {
+ FEEvaluation<dim, degree_v, degree_v + 1, dim, number> velocity(data, 0);
+ for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
+ {
+ velocity.reinit(cell);
+ AlignedVector<VectorizedArray<number>> diagonal(velocity.dofs_per_cell);
+ for (unsigned int i = 0; i < velocity.dofs_per_cell; ++i)
+ {
+ for (unsigned int j = 0; j < velocity.dofs_per_cell; ++j)
+ velocity.begin_dof_values()[j] = VectorizedArray<number>();
+ velocity.begin_dof_values()[i] = make_vectorized_array<number>(1.);
+
+ velocity.evaluate(EvaluationFlags::gradients);
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ velocity.submit_symmetric_gradient(
+ viscosity_x_2(cell, q) * velocity.get_symmetric_gradient(q),
+ q);
+ }
+ velocity.integrate(EvaluationFlags::gradients);
+
+ diagonal[i] = velocity.begin_dof_values()[i];
+ }
+
+ for (unsigned int i = 0; i < velocity.dofs_per_cell; ++i)
+ velocity.begin_dof_values()[i] = diagonal[i];
+ velocity.distribute_local_to_global(dst);
+ }
+ }
+
+
+
+ template <int dim>
+ class StokesProblem
+ {
+ public:
+ StokesProblem();
+
+ void
+ run();
+
+ private:
+ void
+ make_grid(const unsigned int ref = 4);
+ void
+ create_sinker(const unsigned int n_sinkers, const double visc_jump);
+ void
+ setup_system();
+ void
+ assemble_rhs();
+ void
+ solve();
+
+ using vector_t = LinearAlgebra::distributed::Vector<double>;
+ using block_vector_t = LinearAlgebra::distributed::BlockVector<double>;
+
+ using StokesMatrixType = StokesOperator<dim, velocity_degree, double>;
+ using MassMatrixType = MassMatrixOperator<dim, velocity_degree - 1, double>;
+ using LevelMatrixType = ABlockOperator<dim, velocity_degree, double>;
+
+ unsigned int degree_u;
+
+ FESystem<dim> fe_u;
+ FE_Q<dim> fe_p;
+
+ parallel::distributed::Triangulation<dim> triangulation;
+ DoFHandler<dim> dof_handler_u;
+ DoFHandler<dim> dof_handler_p;
+
+ std::vector<IndexSet> owned_partitioning;
+ std::vector<IndexSet> relevant_partitioning;
+
+ AffineConstraints<double> constraints_u;
+ AffineConstraints<double> constraints_p;
+
+ block_vector_t solution;
+ block_vector_t system_rhs;
+
+ StokesMatrixType stokes_matrix;
+ MassMatrixType mass_matrix;
+
+ MGLevelObject<LevelMatrixType> mg_matrices;
+ MGConstrainedDoFs mg_constrained_dofs;
+
+ Sinker<dim> sinker;
+ };
+
+
+
+ template <int dim>
+ StokesProblem<dim>::StokesProblem()
+ : degree_u(velocity_degree)
+ , fe_u(FE_Q<dim>(degree_u), dim)
+ , fe_p(FE_Q<dim>(degree_u - 1))
+ , triangulation(MPI_COMM_WORLD,
+ typename Triangulation<dim>::MeshSmoothing(
+ Triangulation<dim>::limit_level_difference_at_vertices |
+ Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening),
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy)
+ , dof_handler_u(triangulation)
+ , dof_handler_p(triangulation)
+ {}
+
+ template <int dim>
+ void
+ StokesProblem<dim>::create_sinker(const unsigned int n_sinkers,
+ const double visc_jump)
+ {
+ sinker.problem_dim = dim;
+ sinker.n_sinkers = n_sinkers;
+ std::srand(171);
+ for (unsigned int s = 0; s < sinker.n_sinkers; ++s)
+ {
+ std::vector<double> coords(dim);
+ if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0)
+ for (unsigned int i = 0; i < dim; ++i)
+ coords[i] = std::rand() / (double)RAND_MAX;
+
+ MPI_Bcast(&(coords[0]), dim, MPI_DOUBLE, 0, MPI_COMM_WORLD);
+
+ Tensor<1, dim, double> coords_tens;
+ for (unsigned int i = 0; i < dim; ++i)
+ coords_tens[i] = coords[i];
+ sinker.centers.push_back(Point<dim>(coords_tens));
+ }
+
+ sinker.DR_mu = visc_jump;
+ sinker.mu_max = std::sqrt(sinker.DR_mu);
+ sinker.mu_min = 1.0 / std::sqrt(sinker.DR_mu);
+ }
+
+
+ template <int dim>
+ void
+ StokesProblem<dim>::make_grid(const unsigned int ref)
+ {
+ GridGenerator::hyper_cube(triangulation, 0, 1);
+ triangulation.refine_global(ref);
+ }
+
+
+ template <int dim>
+ void
+ StokesProblem<dim>::setup_system()
+ {
+ dof_handler_u.clear();
+ dof_handler_u.distribute_dofs(fe_u);
+ dof_handler_u.distribute_mg_dofs();
+
+ dof_handler_p.clear();
+ dof_handler_p.distribute_dofs(fe_p);
+
+ IndexSet locally_relevant_dofs_u;
+ DoFTools::extract_locally_relevant_dofs(dof_handler_u,
+ locally_relevant_dofs_u);
+ constraints_u.reinit(locally_relevant_dofs_u);
+ DoFTools::make_hanging_node_constraints(dof_handler_u, constraints_u);
+
+ VectorTools::interpolate_boundary_values(
+ dof_handler_u, 0, ExactSolution_BoundaryValues_u<dim>(), constraints_u);
+ constraints_u.close();
+
+ IndexSet locally_relevant_dofs_p;
+ DoFTools::extract_locally_relevant_dofs(dof_handler_p,
+ locally_relevant_dofs_p);
+ constraints_p.reinit(locally_relevant_dofs_p);
+ DoFTools::make_hanging_node_constraints(dof_handler_p, constraints_p);
+ constraints_p.close();
+
+
+ // Stokes matrix stuff...
+ typename MatrixFree<dim, double>::AdditionalData additional_data_stokes;
+ additional_data_stokes.tasks_parallel_scheme =
+ MatrixFree<dim, double>::AdditionalData::none;
+ additional_data_stokes.mapping_update_flags =
+ (update_values | update_gradients | update_JxW_values |
+ update_quadrature_points);
+
+ std::vector<const DoFHandler<dim> *> stokes_dofs;
+ stokes_dofs.push_back(&dof_handler_u);
+ stokes_dofs.push_back(&dof_handler_p);
+ std::vector<const AffineConstraints<double> *> stokes_constraints;
+ stokes_constraints.push_back(&constraints_u);
+ stokes_constraints.push_back(&constraints_p);
+
+ std::shared_ptr<MatrixFree<dim, double>> stokes_mf_storage(
+ new MatrixFree<dim, double>());
+ stokes_mf_storage->reinit(MappingQ1<dim>{},
+ stokes_dofs,
+ stokes_constraints,
+ QGauss<1>(degree_u + 1),
+ additional_data_stokes);
+
+ stokes_matrix.initialize(stokes_mf_storage);
+ stokes_matrix.evaluate_2_x_viscosity(Viscosity<dim>(sinker));
+
+ // Mass matrix stuff...
+ typename MatrixFree<dim, double>::AdditionalData additional_data_mass;
+ additional_data_mass.tasks_parallel_scheme =
+ MatrixFree<dim, double>::AdditionalData::none;
+ additional_data_mass.mapping_update_flags =
+ (update_values | update_JxW_values | update_quadrature_points);
+ std::shared_ptr<MatrixFree<dim, double>> mass_mf_storage(
+ new MatrixFree<dim, double>());
+ mass_mf_storage->reinit(MappingQ1<dim>{},
+ dof_handler_p,
+ constraints_p,
+ QGauss<1>(degree_u + 1),
+ additional_data_mass);
+
+ mass_matrix.initialize(mass_mf_storage);
+ mass_matrix.evaluate_1_over_viscosity(Viscosity<dim>(sinker));
+ mass_matrix.compute_diagonal();
+
+ // GMG stuff...
+ const unsigned int n_levels = triangulation.n_global_levels();
+ mg_matrices.clear_elements();
+
+ mg_matrices.resize(0, n_levels - 1);
+
+ mg_constrained_dofs.clear();
+ const std::set<types::boundary_id> dirichlet_boundary = {0};
+ mg_constrained_dofs.initialize(dof_handler_u);
+ mg_constrained_dofs.make_zero_boundary_constraints(dof_handler_u,
+ dirichlet_boundary);
+
+
+ for (unsigned int level = 0; level < n_levels; ++level)
+ {
+ IndexSet relevant_dofs;
+ DoFTools::extract_locally_relevant_level_dofs(dof_handler_u,
+ level,
+ relevant_dofs);
+ AffineConstraints<double> level_constraints;
+ level_constraints.reinit(relevant_dofs);
+ level_constraints.add_lines(
+ mg_constrained_dofs.get_boundary_indices(level));
+ level_constraints.close();
+
+ typename MatrixFree<dim, double>::AdditionalData additional_data;
+ additional_data.tasks_parallel_scheme =
+ MatrixFree<dim, double>::AdditionalData::none;
+ additional_data.mapping_update_flags =
+ (update_gradients | update_JxW_values | update_quadrature_points);
+ additional_data.mg_level = level;
+ std::shared_ptr<MatrixFree<dim, double>> mg_mf_storage_level(
+ new MatrixFree<dim, double>());
+ mg_mf_storage_level->reinit(MappingQ1<dim>{},
+ dof_handler_u,
+ level_constraints,
+ QGauss<1>(degree_u + 1),
+ additional_data);
+
+ mg_matrices[level].initialize(mg_mf_storage_level,
+ mg_constrained_dofs,
+ level);
+ mg_matrices[level].evaluate_2_x_viscosity(Viscosity<dim>(sinker));
+ mg_matrices[level].compute_diagonal();
+ }
+
+ solution.reinit(2);
+ system_rhs.reinit(2);
+
+ stokes_matrix.initialize_dof_vector(solution);
+ stokes_matrix.initialize_dof_vector(system_rhs);
+
+ solution.update_ghost_values();
+ solution.collect_sizes();
+
+ system_rhs.update_ghost_values();
+ system_rhs.collect_sizes();
+ }
+
+
+
+ template <int dim>
+ void
+ StokesProblem<dim>::assemble_rhs()
+ {
+ system_rhs = 0.0;
+
+ // Create operator with no Dirchlet info
+ StokesMatrixType operator_homogeneous;
+ typename MatrixFree<dim, double>::AdditionalData data;
+ data.tasks_parallel_scheme = MatrixFree<dim, double>::AdditionalData::none;
+ data.mapping_update_flags = (update_values | update_gradients |
+ update_JxW_values | update_quadrature_points);
+
+ // Create constraints with no Dirchlet info
+ AffineConstraints<double> constraints_u_no_dirchlet;
+ IndexSet locally_relevant_dofs_u;
+ DoFTools::extract_locally_relevant_dofs(dof_handler_u,
+ locally_relevant_dofs_u);
+ constraints_u_no_dirchlet.reinit(locally_relevant_dofs_u);
+ DoFTools::make_hanging_node_constraints(dof_handler_u,
+ constraints_u_no_dirchlet);
+ constraints_u_no_dirchlet.close();
+
+ std::vector<const AffineConstraints<double> *> constraints_no_dirchlet;
+ constraints_no_dirchlet.push_back(&constraints_u_no_dirchlet);
+ constraints_no_dirchlet.push_back(&constraints_p);
+ std::vector<const DoFHandler<dim> *> dofs;
+ dofs.push_back(&dof_handler_u);
+ dofs.push_back(&dof_handler_p);
+
+ std::shared_ptr<MatrixFree<dim, double>> matrix_free_homogeneous(
+ new MatrixFree<dim, double>());
+ matrix_free_homogeneous->reinit(MappingQ1<dim>{},
+ dofs,
+ constraints_no_dirchlet,
+ QGauss<1>(degree_u + 1),
+ data);
+
+ operator_homogeneous.initialize(matrix_free_homogeneous);
+ operator_homogeneous.evaluate_2_x_viscosity(Viscosity<dim>(sinker));
+ LinearAlgebra::distributed::BlockVector<double> inhomogeneity(2);
+ operator_homogeneous.initialize_dof_vector(inhomogeneity);
+ constraints_u.distribute(inhomogeneity.block(0));
+ operator_homogeneous.vmult(system_rhs, inhomogeneity);
+ system_rhs *= -1.;
+
+ // Normal apply boundary
+ RightHandSide<dim> right_hand_side(sinker);
+
+ FEEvaluation<dim, velocity_degree, velocity_degree + 1, dim, double>
+ velocity(*stokes_matrix.get_matrix_free(), 0);
+ FEEvaluation<dim, velocity_degree - 1, velocity_degree + 1, 1, double>
+ pressure(*stokes_matrix.get_matrix_free(), 1);
+
+ for (unsigned int cell = 0;
+ cell < stokes_matrix.get_matrix_free()->n_cell_batches();
+ ++cell)
+ {
+ velocity.reinit(cell);
+ pressure.reinit(cell);
+ for (unsigned int q = 0; q < velocity.n_q_points; ++q)
+ {
+ Tensor<1, dim, VectorizedArray<double>> rhs_u;
+ for (unsigned int d = 0; d < dim; ++d)
+ rhs_u[d] = make_vectorized_array<double>(1.0);
+ VectorizedArray<double> rhs_p = make_vectorized_array<double>(1.0);
+ for (unsigned int i = 0; i < VectorizedArray<double>::size(); ++i)
+ {
+ Point<dim> p;
+ for (unsigned int d = 0; d < dim; ++d)
+ p(d) = velocity.quadrature_point(q)(d)[i];
+
+ Vector<double> rhs_temp(dim + 1);
+ right_hand_side.vector_value(p, rhs_temp);
+
+ for (unsigned int d = 0; d < dim; ++d)
+ rhs_u[d][i] = rhs_temp(d);
+ rhs_p[i] = rhs_temp(dim);
+ }
+ velocity.submit_value(rhs_u, q);
+ pressure.submit_value(rhs_p, q);
+ }
+ velocity.integrate(EvaluationFlags::values);
+ velocity.distribute_local_to_global(system_rhs.block(0));
+ pressure.integrate(EvaluationFlags::values);
+ pressure.distribute_local_to_global(system_rhs.block(1));
+ }
+ system_rhs.compress(VectorOperation::add);
+ }
+
+ template <int dim>
+ void
+ StokesProblem<dim>::solve()
+ {
+ const double solver_tolerance = 1e-6 * system_rhs.l2_norm();
+ const unsigned int n_cheap_stokes_solver_steps = 1000;
+ const double linear_solver_A_block_tolerance = 1e-2;
+ const double linear_solver_S_block_tolerance = 1e-6;
+
+ // extract Stokes parts of solution vector, without any ghost elements
+ block_vector_t distributed_stokes_solution(solution);
+
+ const unsigned int block_vel = 0;
+ const unsigned int block_p = 1;
+
+ // extract Stokes parts of rhs vector
+ block_vector_t distributed_stokes_rhs(system_rhs);
+
+ PrimitiveVectorMemory<block_vector_t> mem;
+
+ SolverControl solver_control_cheap(n_cheap_stokes_solver_steps,
+ solver_tolerance,
+ false,
+ false);
+
+ using Transfer = MGTransferMF<dim, double>;
+
+ Transfer mg_transfer(mg_constrained_dofs);
+ mg_transfer.initialize_constraints(mg_constrained_dofs);
+ mg_transfer.build(dof_handler_u);
+
+ LevelMatrixType & coarse_matrix = mg_matrices[0];
+ SolverControl coarse_solver_control(1000, 1e-12, false, false);
+ SolverCG<vector_t> coarse_solver(coarse_solver_control);
+
+ PreconditionIdentity coarse_prec_identity;
+ MGCoarseGridIterativeSolver<vector_t,
+ SolverCG<vector_t>,
+ LevelMatrixType,
+ PreconditionIdentity>
+ mg_coarse;
+ mg_coarse.initialize(coarse_solver, coarse_matrix, coarse_prec_identity);
+
+ using SmootherType = PreconditionChebyshev<LevelMatrixType, vector_t>;
+ mg::SmootherRelaxation<SmootherType, vector_t> mg_smoother;
+ MGLevelObject<typename SmootherType::AdditionalData> smoother_data;
+ smoother_data.resize(0, triangulation.n_global_levels() - 1);
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ {
+ if (level > 0)
+ {
+ smoother_data[level].smoothing_range = 15.;
+ smoother_data[level].degree = 4;
+ smoother_data[level].eig_cg_n_iterations = 10;
+ }
+ else
+ {
+ smoother_data[0].smoothing_range = 1e-3;
+ smoother_data[0].degree = numbers::invalid_unsigned_int;
+ smoother_data[0].eig_cg_n_iterations = mg_matrices[0].m();
+ }
+ smoother_data[level].preconditioner =
+ mg_matrices[level].get_matrix_diagonal_inverse();
+ }
+ mg_smoother.initialize(mg_matrices, smoother_data);
+
+ mg::Matrix<vector_t> mg_matrix(mg_matrices);
+
+ MGLevelObject<MatrixFreeOperators::MGInterfaceOperator<LevelMatrixType>>
+ mg_interface_matrices;
+ mg_interface_matrices.resize(0, triangulation.n_global_levels() - 1);
+ for (unsigned int level = 0; level < triangulation.n_global_levels();
+ ++level)
+ mg_interface_matrices[level].initialize(mg_matrices[level]);
+ mg::Matrix<vector_t> mg_interface(mg_interface_matrices);
+
+ Multigrid<vector_t> mg(
+ mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother, 0);
+ mg.set_edge_matrices(mg_interface, mg_interface);
+
+
+ PreconditionMG<dim, vector_t, Transfer> prec_A(dof_handler_u,
+ mg,
+ mg_transfer);
+
+ using MassPrec = PreconditionChebyshev<MassMatrixType, vector_t>;
+ MassPrec prec_S;
+ typename MassPrec::AdditionalData prec_S_data;
+ prec_S_data.smoothing_range = 1e-3;
+ prec_S_data.degree = numbers::invalid_unsigned_int;
+ prec_S_data.eig_cg_n_iterations = mass_matrix.m();
+ prec_S_data.preconditioner = mass_matrix.get_matrix_diagonal_inverse();
+ prec_S.initialize(mass_matrix, prec_S_data);
+
+ using A_prec_type = PreconditionMG<dim, vector_t, Transfer>;
+
+ // create a cheap preconditioner that consists of only a single V-cycle
+ const StokesSolver::BlockSchurPreconditioner<StokesMatrixType,
+ MassMatrixType,
+ A_prec_type,
+ MassPrec>
+ preconditioner_cheap(stokes_matrix,
+ mass_matrix,
+ prec_S,
+ prec_A,
+ false,
+ linear_solver_A_block_tolerance,
+ linear_solver_S_block_tolerance);
+ try
+ {
+ SolverFGMRES<block_vector_t> solver(
+ solver_control_cheap,
+ mem,
+ SolverFGMRES<block_vector_t>::AdditionalData(50));
+
+ solver.solve(stokes_matrix,
+ distributed_stokes_solution,
+ distributed_stokes_rhs,
+ preconditioner_cheap);
+ }
+ catch (const SolverControl::NoConvergence &)
+ {
+ deallog
+ << "********************************************************************"
+ << std::endl
+ << "SOLVER DID NOT CONVERGE AFTER " << n_cheap_stokes_solver_steps
+ << " ITERATIONS. res=" << solver_control_cheap.last_value()
+ << std::endl
+ << "********************************************************************"
+ << std::endl;
+ }
+
+ constraints_u.distribute(distributed_stokes_solution.block(0));
+
+ distributed_stokes_solution.block(block_p) *= pressure_scaling;
+
+ solution.block(block_vel) = distributed_stokes_solution.block(block_vel);
+ solution.block(block_p) = distributed_stokes_solution.block(block_p);
+
+ deallog << "Solved-in "
+ << (solver_control_cheap.last_step() !=
+ numbers::invalid_unsigned_int ?
+ solver_control_cheap.last_step() :
+ 0)
+ << " iterations, final residual: "
+ << solver_control_cheap.last_value() << std::endl;
+ }
+
+
+ template <int dim>
+ void
+ StokesProblem<dim>::run()
+ {
+ deallog << "Sinker problem in " << dim << "D." << std::endl;
+
+ create_sinker(4, 1000);
+ deallog << "n_sinker: " << sinker.n_sinkers
+ << " max/min viscosity ratio: " << sinker.DR_mu << std::endl
+ << std::endl;
+
+ unsigned int initial_ref;
+ if (dim == 2)
+ {
+ initial_ref = 5;
+ }
+ else if (dim == 3)
+ {
+ initial_ref = 3;
+ }
+
+ unsigned int n_cycles = 1;
+ if (dim == 2)
+ n_cycles = 2;
+ for (unsigned int cycle = 0; cycle < n_cycles; ++cycle)
+ {
+ if (cycle == 0)
+ make_grid(initial_ref);
+ else
+ triangulation.refine_global();
+
+ setup_system();
+ deallog << "Number of active cells: "
+ << triangulation.n_global_active_cells() << " (on "
+ << triangulation.n_global_levels() << " levels)" << std::endl;
+ deallog << "Number of degrees of freedom: "
+ << dof_handler_u.n_dofs() + dof_handler_p.n_dofs() << " ("
+ << dof_handler_u.n_dofs() << '+' << dof_handler_p.n_dofs()
+ << ')' << std::endl;
+
+ assemble_rhs();
+ solve();
+
+ deallog << std::endl;
+ }
+ }
+} // namespace StokesClass
+
+
+int
+main(int argc, char *argv[])
+{
+ dealii::Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
+ mpi_initlog();
+ try
+ {
+ {
+ deallog.push("2d");
+ StokesClass::StokesProblem<2> problem;
+ problem.run();
+ deallog.pop();
+ }
+ {
+ deallog.push("3d");
+ StokesClass::StokesProblem<3> problem;
+ problem.run();
+ deallog.pop();
+ }
+ }
+ catch (const std::exception &exc)
+ {
+ std::cerr << std::endl
+ << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Exception on processing: " << std::endl
+ << exc.what() << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ throw;
+ }
+ catch (...)
+ {
+ std::cerr << std::endl
+ << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Unknown exception!" << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ throw;
+ }
+
+ return 0;
+}
--- /dev/null
+
+DEAL:2d::Sinker problem in 2D.
+DEAL:2d::n_sinker: 4 max/min viscosity ratio: 1000.00
+DEAL:2d::
+DEAL:2d::Number of active cells: 1024 (on 6 levels)
+DEAL:2d::Number of degrees of freedom: 9539 (8450+1089)
+DEAL:2d::Solved-in 69 iterations, final residual: 5.58979e-08
+DEAL:2d::
+DEAL:2d::Number of active cells: 4096 (on 7 levels)
+DEAL:2d::Number of degrees of freedom: 37507 (33282+4225)
+DEAL:2d::Solved-in 69 iterations, final residual: 2.58019e-08
+DEAL:2d::
+DEAL:3d::Sinker problem in 3D.
+DEAL:3d::n_sinker: 4 max/min viscosity ratio: 1000.00
+DEAL:3d::
+DEAL:3d::Number of active cells: 512 (on 4 levels)
+DEAL:3d::Number of degrees of freedom: 15468 (14739+729)
+DEAL:3d::Solved-in 62 iterations, final residual: 1.99453e-08
+DEAL:3d::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2006 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// check MGTransferBlockMatrixFree::copy_[from|to]_mg by comparison to non-block
+// MGTransferMatrixFree
+
+#include <deal.II/base/function.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/multigrid/mg_constrained_dofs.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <algorithm>
+
+#include "../tests.h"
+
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference non-block
+ MGTransferMF<dim, Number> transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free block transfer
+ MGTransferBlockMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ const unsigned int nb = 3;
+
+ MGLevelObject<LinearAlgebra::distributed::BlockVector<Number>> lbv(
+ 0, tr.n_global_levels() - 1);
+ LinearAlgebra::distributed::BlockVector<Number> bv(nb);
+
+ MGLevelObject<LinearAlgebra::distributed::Vector<Number>> lv(
+ 0, tr.n_global_levels() - 1);
+ LinearAlgebra::distributed::Vector<Number> v(nb);
+
+ // initialize
+ v.reinit(mgdof.locally_owned_dofs(), MPI_COMM_WORLD);
+ for (unsigned int b = 0; b < nb; ++b)
+ bv.block(b).reinit(mgdof.locally_owned_dofs(), MPI_COMM_WORLD);
+
+ for (unsigned int l = lbv.min_level(); l <= lbv.max_level(); ++l)
+ {
+ lv[l].reinit(mgdof.locally_owned_mg_dofs(l), MPI_COMM_WORLD);
+
+ lbv[l].reinit(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ lbv[l].block(b).reinit(mgdof.locally_owned_mg_dofs(l),
+ MPI_COMM_WORLD);
+
+ lbv[l].collect_sizes();
+
+ // set values:
+ for (unsigned int b = 0; b < nb; ++b)
+ for (unsigned int i = 0; i < lbv[l].block(b).locally_owned_size();
+ ++i)
+ lbv[l].block(b).local_element(i) = random_value<Number>();
+
+ lbv[l].compress(VectorOperation::insert);
+ }
+
+ // check copy_from_mg
+ transfer.copy_from_mg(mgdof, bv, lbv);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ lv[l] = lbv[l].block(b);
+
+ transfer_ref.copy_from_mg(mgdof, v, lv);
+ v -= bv.block(b);
+ deallog << "Diff copy_from_mg b" << b << ": " << v.l2_norm()
+ << std::endl;
+ }
+
+ // check copy_to_mg
+ // use un-initialized level-block vector to make sure that it will be
+ // set correctly in copy_to_mg().
+ MGLevelObject<LinearAlgebra::distributed::BlockVector<Number>> lbv2(
+ 0, tr.n_global_levels() - 1);
+ for (unsigned int b = 0; b < nb; ++b)
+ for (unsigned int i = 0; i < bv.block(b).locally_owned_size(); ++i)
+ bv.block(b).local_element(i) = random_value<Number>();
+
+ transfer.copy_to_mg(mgdof, lbv2, bv);
+ // Also check that the block vector has its (global) size set on each
+ // level:
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ {
+ unsigned int total_size = 0;
+ for (unsigned int b = 0; b < nb; ++b)
+ total_size += lbv2[l].block(b).size();
+
+ AssertThrow(total_size == lbv2[l].size(),
+ ExcDimensionMismatch(total_size, lbv2[l].size()));
+ }
+
+ // Finally check the difference:
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v = bv.block(b);
+ transfer_ref.copy_to_mg(mgdof, lv, v);
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ {
+ lv[l] -= lbv2[l].block(b);
+ deallog << "Diff copy_to_mg l" << l << ": " << lv[l].l2_norm()
+ << std::endl;
+ }
+ }
+
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_from_mg b2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2006 - 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// check MGTransferBlockMatrixFree::copy_[from|to]_mg by comparison to non-block
+// MGTransferMatrixFree. This is similar to transfer_05 but using
+// a separate DoFHandler for each block
+
+#include <deal.II/base/function.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+
+#include <deal.II/multigrid/mg_constrained_dofs.h>
+#include <deal.II/multigrid/mg_tools.h>
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <algorithm>
+
+#include "../tests.h"
+
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ const unsigned int nb = 2;
+
+ FE_Q<dim> fe_1(fe_degree + 1);
+ FE_Q<dim> fe_2(fe_degree);
+
+ deallog << "FE: " << fe_1.get_name() << std::endl;
+ deallog << "FE: " << fe_2.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof_1(tr);
+ mgdof_1.distribute_dofs(fe_1);
+ mgdof_1.distribute_mg_dofs();
+
+ DoFHandler<dim> mgdof_2(tr);
+ mgdof_2.distribute_dofs(fe_2);
+ mgdof_2.distribute_mg_dofs();
+
+ const std::vector<const DoFHandler<dim> *> mgdof_ptr{&mgdof_1, &mgdof_2};
+
+ std::vector<MGConstrainedDoFs> mg_constrained_dofs_vector(2);
+ for (unsigned int i = 0; i < mgdof_ptr.size(); ++i)
+ {
+ mg_constrained_dofs_vector[i].initialize(*mgdof_ptr[i]);
+ mg_constrained_dofs_vector[i].make_zero_boundary_constraints(
+ *mgdof_ptr[i], {0});
+ }
+
+ // build reference non-block
+ std::vector<MGTransferMF<dim, Number>> transfer_ref;
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ transfer_ref.emplace_back(mg_constrained_dofs_vector[b]);
+ transfer_ref[b].build(*mgdof_ptr[b]);
+ }
+
+ // build matrix-free block transfer
+ MGTransferBlockMF<dim, Number> transfer(mg_constrained_dofs_vector);
+ transfer.build(mgdof_ptr);
+
+ MGLevelObject<LinearAlgebra::distributed::BlockVector<Number>> lbv(
+ 0, tr.n_global_levels() - 1);
+ LinearAlgebra::distributed::BlockVector<Number> bv(nb);
+
+ MGLevelObject<LinearAlgebra::distributed::Vector<Number>> lv(
+ 0, tr.n_global_levels() - 1);
+ LinearAlgebra::distributed::Vector<Number> v(nb);
+
+ // initialize
+ for (unsigned int b = 0; b < nb; ++b)
+ bv.block(b).reinit(mgdof_ptr[b]->locally_owned_dofs(), MPI_COMM_WORLD);
+
+ for (unsigned int l = lbv.min_level(); l <= lbv.max_level(); ++l)
+ {
+ lbv[l].reinit(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ lbv[l].block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(l),
+ MPI_COMM_WORLD);
+
+ lbv[l].collect_sizes();
+
+ // set values:
+ for (unsigned int b = 0; b < nb; ++b)
+ for (unsigned int i = 0; i < lbv[l].block(b).locally_owned_size();
+ ++i)
+ lbv[l].block(b).local_element(i) = random_value<double>();
+
+ lbv[l].compress(VectorOperation::insert);
+ }
+
+ // check copy_from_mg
+ transfer.copy_from_mg(mgdof_ptr, bv, lbv);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v.reinit(mgdof_ptr[b]->locally_owned_dofs(), MPI_COMM_WORLD);
+
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ {
+ lv[l].reinit(mgdof_ptr[b]->locally_owned_mg_dofs(l),
+ MPI_COMM_WORLD);
+ lv[l] = lbv[l].block(b);
+ }
+
+ transfer_ref[b].copy_from_mg(*mgdof_ptr[b], v, lv);
+ v -= bv.block(b);
+ deallog << "Diff copy_from_mg b" << b << ": " << v.l2_norm()
+ << std::endl;
+ }
+
+ // check copy_to_mg
+ // use un-initialized level-block vector to make sure that it will be
+ // set correctly in copy_to_mg().
+ MGLevelObject<LinearAlgebra::distributed::BlockVector<Number>> lbv2(
+ 0, tr.n_global_levels() - 1);
+ for (unsigned int b = 0; b < nb; ++b)
+ for (unsigned int i = 0; i < bv.block(b).locally_owned_size(); ++i)
+ bv.block(b).local_element(i) = random_value<double>();
+
+ transfer.copy_to_mg(mgdof_ptr, lbv2, bv);
+ // Also check that the block vector has its (global) size set on each
+ // level:
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ {
+ unsigned int total_size = 0;
+ for (unsigned int b = 0; b < nb; ++b)
+ total_size += lbv2[l].block(b).size();
+
+ AssertThrow(total_size == lbv2[l].size(),
+ ExcDimensionMismatch(total_size, lbv2[l].size()));
+ }
+
+ // Finally check the difference:
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v.reinit(mgdof_ptr[b]->locally_owned_dofs(), MPI_COMM_WORLD);
+
+ v = bv.block(b);
+ transfer_ref[b].copy_to_mg(*mgdof_ptr[b], lv, v);
+ for (unsigned int l = lv.min_level(); l <= lv.max_level(); ++l)
+ {
+ lv[l] -= lbv2[l].block(b);
+ deallog << "Diff copy_to_mg l" << l << ": " << lv[l].l2_norm()
+ << std::endl;
+ }
+ }
+
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(2)
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(4)
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(4)
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff copy_from_mg b0: 0.00000
+DEAL::Diff copy_from_mg b1: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::Diff copy_to_mg l0: 0.00000
+DEAL::Diff copy_to_mg l1: 0.00000
+DEAL::Diff copy_to_mg l2: 0.00000
+DEAL::Diff copy_to_mg l3: 0.00000
+DEAL::Diff copy_to_mg l4: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with uniform meshes for FE_Q
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3, 4, 5, 6, 8};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 2.22045e-16
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.57009e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 5.43896e-16
+DEAL::Diff restrict add l3: 4.44089e-16
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 1.11022e-16
+DEAL::Diff prolongate l2: 1.66533e-16
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 9.93014e-16
+DEAL::Diff restrict add l2: 1.17495e-15
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.11022e-16
+DEAL::Diff prolongate l4: 2.77556e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 8.30815e-16
+DEAL::Diff restrict add l3: 7.69185e-16
+DEAL::Diff restrict l4: 2.09476e-15
+DEAL::Diff restrict add l4: 2.22045e-15
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 1.57009e-16
+DEAL::Diff prolongate l2: 3.05311e-16
+DEAL::Diff restrict l1: 1.29473e-15
+DEAL::Diff restrict add l1: 1.40433e-15
+DEAL::Diff restrict l2: 2.14132e-15
+DEAL::Diff restrict add l2: 2.43238e-15
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 1.11022e-16
+DEAL::Diff prolongate l2: 2.54384e-16
+DEAL::Diff prolongate l3: 4.75099e-16
+DEAL::Diff restrict l1: 4.96507e-16
+DEAL::Diff restrict add l1: 4.44089e-16
+DEAL::Diff restrict l2: 1.15378e-15
+DEAL::Diff restrict add l2: 1.25607e-15
+DEAL::Diff restrict l3: 3.16560e-15
+DEAL::Diff restrict add l3: 3.35280e-15
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.11022e-16
+DEAL::Diff prolongate l4: 1.57009e-16
+DEAL::Diff prolongate l5: 6.52699e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 9.67870e-16
+DEAL::Diff restrict add l3: 9.93014e-16
+DEAL::Diff restrict l4: 1.55431e-15
+DEAL::Diff restrict add l4: 1.67640e-15
+DEAL::Diff restrict l5: 4.09129e-15
+DEAL::Diff restrict add l5: 4.49606e-15
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 4.80741e-16
+DEAL::Diff restrict l1: 9.15513e-16
+DEAL::Diff restrict add l1: 9.93014e-16
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 1.86190e-16
+DEAL::Diff prolongate l2: 8.36002e-16
+DEAL::Diff restrict l1: 1.88411e-15
+DEAL::Diff restrict add l1: 1.77636e-15
+DEAL::Diff restrict l2: 1.75542e-15
+DEAL::Diff restrict add l2: 2.23152e-15
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 1.43538e-15
+DEAL::Diff restrict l1: 3.89726e-15
+DEAL::Diff restrict add l1: 4.47958e-15
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 2.92423e-16
+DEAL::Diff prolongate l2: 8.77050e-16
+DEAL::Diff prolongate l3: 1.86878e-15
+DEAL::Diff restrict l1: 7.69185e-16
+DEAL::Diff restrict add l1: 7.69185e-16
+DEAL::Diff restrict l2: 1.77982e-15
+DEAL::Diff restrict add l2: 1.71995e-15
+DEAL::Diff restrict l3: 5.40828e-15
+DEAL::Diff restrict add l3: 5.59094e-15
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 2.17853e-15
+DEAL::Diff restrict l1: 6.14936e-15
+DEAL::Diff restrict add l1: 6.60186e-15
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 1.47799e-15
+DEAL::Diff prolongate l2: 2.65352e-15
+DEAL::Diff restrict l1: 3.82826e-15
+DEAL::Diff restrict add l1: 3.82665e-15
+DEAL::Diff restrict l2: 7.88395e-15
+DEAL::Diff restrict add l2: 8.71649e-15
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 2.74525e-16
+DEAL::Diff prolongate l2: 7.76201e-16
+DEAL::Diff prolongate l3: 1.72781e-15
+DEAL::Diff prolongate l4: 3.59470e-15
+DEAL::Diff restrict l1: 3.14018e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 2.57035e-15
+DEAL::Diff restrict add l2: 2.62727e-15
+DEAL::Diff restrict l3: 5.33312e-15
+DEAL::Diff restrict add l3: 5.73030e-15
+DEAL::Diff restrict l4: 1.11508e-14
+DEAL::Diff restrict add l4: 1.20581e-14
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 8.88178e-16
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 2.83052e-16
+DEAL::Diff restrict l1: 2.51215e-15
+DEAL::Diff restrict add l1: 2.51215e-15
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.11022e-16
+DEAL::Diff prolongate l3: 4.87516e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 2.62727e-15
+DEAL::Diff restrict add l3: 3.07674e-15
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 7.53533e-16
+DEAL::Diff restrict l1: 5.10220e-15
+DEAL::Diff restrict add l1: 5.61733e-15
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 2.23773e-16
+DEAL::Diff prolongate l2: 1.17095e-15
+DEAL::Diff restrict l1: 1.40433e-15
+DEAL::Diff restrict add l1: 1.53837e-15
+DEAL::Diff restrict l2: 8.10387e-15
+DEAL::Diff restrict add l2: 8.54223e-15
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 3.76063e-16
+DEAL::Diff prolongate l4: 1.91920e-15
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 4.84444e-15
+DEAL::Diff restrict add l3: 4.94517e-15
+DEAL::Diff restrict l4: 1.43214e-14
+DEAL::Diff restrict add l4: 1.52161e-14
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 5.85228e-16
+DEAL::Diff restrict l1: 4.16593e-15
+DEAL::Diff restrict add l1: 4.78299e-15
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 1.18099e-15
+DEAL::Diff prolongate l2: 3.22757e-15
+DEAL::Diff restrict l1: 4.86475e-15
+DEAL::Diff restrict add l1: 5.10220e-15
+DEAL::Diff restrict l2: 2.45879e-14
+DEAL::Diff restrict add l2: 2.53986e-14
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 6.65254e-15
+DEAL::Diff restrict l1: 4.35629e-14
+DEAL::Diff restrict add l1: 4.43806e-14
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 5.45722e-16
+DEAL::Diff prolongate l2: 3.47491e-15
+DEAL::Diff prolongate l3: 1.08273e-14
+DEAL::Diff restrict l1: 9.18739e-15
+DEAL::Diff restrict add l1: 1.02044e-14
+DEAL::Diff restrict l2: 2.49877e-14
+DEAL::Diff restrict add l2: 2.48888e-14
+DEAL::Diff restrict l3: 7.50329e-14
+DEAL::Diff restrict add l3: 7.66746e-14
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 3.72529e-08
+DEAL::Diff prolongate l2: 1.31933e-07
+DEAL::Diff restrict l1: 1.67638e-08
+DEAL::Diff restrict add l1: 1.67638e-08
+DEAL::Diff restrict l2: 2.42676e-07
+DEAL::Diff restrict add l2: 4.47664e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 1.49012e-08
+DEAL::Diff prolongate l2: 1.44994e-07
+DEAL::Diff prolongate l3: 3.16323e-07
+DEAL::Diff restrict l1: 9.87202e-08
+DEAL::Diff restrict add l1: 9.87202e-08
+DEAL::Diff restrict l2: 2.15219e-07
+DEAL::Diff restrict add l2: 2.62683e-07
+DEAL::Diff restrict l3: 8.19761e-07
+DEAL::Diff restrict add l3: 8.79582e-07
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 2.98754e-07
+DEAL::Diff prolongate l2: 4.70776e-07
+DEAL::Diff restrict l1: 4.57351e-07
+DEAL::Diff restrict add l1: 8.03906e-07
+DEAL::Diff restrict l2: 1.05171e-06
+DEAL::Diff restrict add l2: 1.45557e-06
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 4.77070e-08
+DEAL::Diff prolongate l2: 8.87839e-08
+DEAL::Diff prolongate l3: 3.12393e-07
+DEAL::Diff prolongate l4: 6.85456e-07
+DEAL::Diff restrict l1: 2.84053e-08
+DEAL::Diff restrict add l1: 2.84053e-08
+DEAL::Diff restrict l2: 3.84794e-07
+DEAL::Diff restrict add l2: 4.83101e-07
+DEAL::Diff restrict l3: 7.28061e-07
+DEAL::Diff restrict add l3: 9.02211e-07
+DEAL::Diff restrict l4: 1.41847e-06
+DEAL::Diff restrict add l4: 1.74159e-06
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 4.30708e-07
+DEAL::Diff prolongate l2: 9.62514e-07
+DEAL::Diff restrict l1: 1.03503e-06
+DEAL::Diff restrict add l1: 1.12037e-06
+DEAL::Diff restrict l2: 1.90372e-06
+DEAL::Diff restrict add l2: 2.24836e-06
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 2.37561e-07
+DEAL::Diff prolongate l2: 4.85227e-07
+DEAL::Diff prolongate l3: 9.86324e-07
+DEAL::Diff restrict l1: 4.79749e-07
+DEAL::Diff restrict add l1: 7.42761e-07
+DEAL::Diff restrict l2: 1.10715e-06
+DEAL::Diff restrict add l2: 1.46215e-06
+DEAL::Diff restrict l3: 2.22257e-06
+DEAL::Diff restrict add l3: 2.53551e-06
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 1.49012e-08
+DEAL::Diff prolongate l2: 1.16789e-07
+DEAL::Diff prolongate l3: 3.15373e-07
+DEAL::Diff prolongate l4: 7.29600e-07
+DEAL::Diff prolongate l5: 1.41394e-06
+DEAL::Diff restrict l1: 2.45869e-07
+DEAL::Diff restrict add l1: 2.45869e-07
+DEAL::Diff restrict l2: 4.01137e-07
+DEAL::Diff restrict add l2: 4.01137e-07
+DEAL::Diff restrict l3: 6.86101e-07
+DEAL::Diff restrict add l3: 7.81855e-07
+DEAL::Diff restrict l4: 1.39585e-06
+DEAL::Diff restrict add l4: 1.79306e-06
+DEAL::Diff restrict l5: 3.06809e-06
+DEAL::Diff restrict add l5: 3.72838e-06
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 1.09627e-07
+DEAL::Diff restrict l1: 5.44882e-07
+DEAL::Diff restrict add l1: 5.44882e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 5.32529e-09
+DEAL::Diff prolongate l2: 3.39210e-07
+DEAL::Diff restrict l1: 3.74159e-07
+DEAL::Diff restrict add l1: 3.74159e-07
+DEAL::Diff restrict l2: 1.15370e-06
+DEAL::Diff restrict add l2: 1.22900e-06
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 8.62651e-07
+DEAL::Diff restrict l1: 2.89970e-06
+DEAL::Diff restrict add l1: 3.35540e-06
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 1.39089e-07
+DEAL::Diff prolongate l2: 3.04131e-07
+DEAL::Diff prolongate l3: 1.38532e-06
+DEAL::Diff restrict l1: 6.78934e-07
+DEAL::Diff restrict add l1: 6.78934e-07
+DEAL::Diff restrict l2: 1.38175e-06
+DEAL::Diff restrict add l2: 1.35441e-06
+DEAL::Diff restrict l3: 4.35419e-06
+DEAL::Diff restrict add l3: 4.60971e-06
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 2.07245e-06
+DEAL::Diff restrict l1: 5.91522e-06
+DEAL::Diff restrict add l1: 6.32888e-06
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 7.71899e-07
+DEAL::Diff prolongate l2: 2.83835e-06
+DEAL::Diff restrict l1: 2.59603e-06
+DEAL::Diff restrict add l1: 2.87564e-06
+DEAL::Diff restrict l2: 7.95574e-06
+DEAL::Diff restrict add l2: 8.72324e-06
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 5.82505e-08
+DEAL::Diff prolongate l2: 4.03345e-07
+DEAL::Diff prolongate l3: 1.32056e-06
+DEAL::Diff prolongate l4: 4.47191e-06
+DEAL::Diff restrict l1: 3.57279e-07
+DEAL::Diff restrict add l1: 3.57279e-07
+DEAL::Diff restrict l2: 1.26665e-06
+DEAL::Diff restrict add l2: 1.64848e-06
+DEAL::Diff restrict l3: 4.01036e-06
+DEAL::Diff restrict add l3: 4.09562e-06
+DEAL::Diff restrict l4: 1.25440e-05
+DEAL::Diff restrict add l4: 1.38985e-05
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.57009e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 2.22045e-16
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 6.66134e-16
+DEAL::Diff restrict add l3: 7.69185e-16
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 4.44089e-16
+DEAL::Diff restrict add l1: 4.44089e-16
+DEAL::Diff restrict l2: 1.29473e-15
+DEAL::Diff restrict add l2: 1.40433e-15
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 5.55112e-17
+DEAL::Diff prolongate l4: 2.43554e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 5.87475e-16
+DEAL::Diff restrict add l3: 4.44089e-16
+DEAL::Diff restrict l4: 1.33227e-15
+DEAL::Diff restrict add l4: 1.47288e-15
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 3.76495e-16
+DEAL::Diff restrict l1: 1.17495e-15
+DEAL::Diff restrict add l1: 1.17495e-15
+DEAL::Diff restrict l2: 2.14132e-15
+DEAL::Diff restrict add l2: 2.39149e-15
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 2.41967e-16
+DEAL::Diff prolongate l3: 4.51828e-16
+DEAL::Diff restrict l1: 2.22045e-16
+DEAL::Diff restrict add l1: 4.44089e-16
+DEAL::Diff restrict l2: 1.48952e-15
+DEAL::Diff restrict add l2: 1.53837e-15
+DEAL::Diff restrict l3: 2.44249e-15
+DEAL::Diff restrict add l3: 2.80867e-15
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.24127e-16
+DEAL::Diff prolongate l4: 2.67665e-16
+DEAL::Diff prolongate l5: 4.95730e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 7.02167e-16
+DEAL::Diff restrict add l3: 6.28037e-16
+DEAL::Diff restrict l4: 1.52226e-15
+DEAL::Diff restrict add l4: 1.88411e-15
+DEAL::Diff restrict l5: 3.75019e-15
+DEAL::Diff restrict add l5: 3.99680e-15
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 5.35510e-16
+DEAL::Diff restrict l1: 1.53837e-15
+DEAL::Diff restrict add l1: 1.53837e-15
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 2.77902e-16
+DEAL::Diff prolongate l2: 1.02023e-15
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 4.44089e-16
+DEAL::Diff restrict l2: 2.63897e-15
+DEAL::Diff restrict add l2: 2.80867e-15
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 1.47011e-15
+DEAL::Diff restrict l1: 3.83198e-15
+DEAL::Diff restrict add l1: 4.01526e-15
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 3.87586e-16
+DEAL::Diff prolongate l2: 8.10619e-16
+DEAL::Diff prolongate l3: 1.77724e-15
+DEAL::Diff restrict l1: 7.69185e-16
+DEAL::Diff restrict add l1: 1.08779e-15
+DEAL::Diff restrict l2: 1.76940e-15
+DEAL::Diff restrict add l2: 1.83103e-15
+DEAL::Diff restrict l3: 5.45198e-15
+DEAL::Diff restrict add l3: 5.51547e-15
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 2.43957e-15
+DEAL::Diff restrict l1: 6.58340e-15
+DEAL::Diff restrict add l1: 7.00409e-15
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 1.52511e-15
+DEAL::Diff prolongate l2: 2.75500e-15
+DEAL::Diff restrict l1: 2.71778e-15
+DEAL::Diff restrict add l1: 3.13232e-15
+DEAL::Diff restrict l2: 7.50219e-15
+DEAL::Diff restrict add l2: 8.11603e-15
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 5.32625e-16
+DEAL::Diff prolongate l2: 1.03306e-15
+DEAL::Diff prolongate l3: 1.87470e-15
+DEAL::Diff prolongate l4: 3.84816e-15
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 2.07704e-15
+DEAL::Diff restrict add l2: 2.66454e-15
+DEAL::Diff restrict l3: 4.96856e-15
+DEAL::Diff restrict add l3: 5.31517e-15
+DEAL::Diff restrict l4: 1.11741e-14
+DEAL::Diff restrict add l4: 1.19415e-14
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 1.66533e-16
+DEAL::Diff restrict l1: 1.60119e-15
+DEAL::Diff restrict add l1: 1.83103e-15
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 3.11884e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 3.46845e-15
+DEAL::Diff restrict add l3: 3.87148e-15
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 5.17215e-16
+DEAL::Diff restrict l1: 4.86475e-15
+DEAL::Diff restrict add l1: 5.29193e-15
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 2.14994e-16
+DEAL::Diff prolongate l2: 9.84663e-16
+DEAL::Diff restrict l1: 1.53837e-15
+DEAL::Diff restrict add l1: 1.53837e-15
+DEAL::Diff restrict l2: 6.76417e-15
+DEAL::Diff restrict add l2: 7.29713e-15
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 3.52521e-16
+DEAL::Diff prolongate l4: 1.77530e-15
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 3.74196e-15
+DEAL::Diff restrict add l3: 3.97205e-15
+DEAL::Diff restrict l4: 1.30912e-14
+DEAL::Diff restrict add l4: 1.43901e-14
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 7.61858e-16
+DEAL::Diff restrict l1: 1.06951e-14
+DEAL::Diff restrict add l1: 1.06951e-14
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 6.76681e-16
+DEAL::Diff prolongate l2: 3.94720e-15
+DEAL::Diff restrict l1: 3.66205e-15
+DEAL::Diff restrict add l1: 3.20237e-15
+DEAL::Diff restrict l2: 2.23362e-14
+DEAL::Diff restrict add l2: 2.30199e-14
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 8.06498e-15
+DEAL::Diff restrict l1: 4.17135e-14
+DEAL::Diff restrict add l1: 4.21809e-14
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 7.45673e-16
+DEAL::Diff prolongate l2: 4.05889e-15
+DEAL::Diff prolongate l3: 1.18902e-14
+DEAL::Diff restrict l1: 3.55271e-15
+DEAL::Diff restrict add l1: 3.43990e-15
+DEAL::Diff restrict l2: 2.10627e-14
+DEAL::Diff restrict add l2: 2.12329e-14
+DEAL::Diff restrict l3: 7.30222e-14
+DEAL::Diff restrict add l3: 7.41273e-14
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 2.98023e-08
+DEAL::Diff prolongate l2: 1.17073e-07
+DEAL::Diff restrict l1: 1.09896e-07
+DEAL::Diff restrict add l1: 1.09896e-07
+DEAL::Diff restrict l2: 2.72120e-07
+DEAL::Diff restrict add l2: 3.19417e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 1.86265e-08
+DEAL::Diff prolongate l2: 8.98385e-08
+DEAL::Diff prolongate l3: 2.91263e-07
+DEAL::Diff restrict l1: 2.09548e-08
+DEAL::Diff restrict add l1: 2.59373e-07
+DEAL::Diff restrict l2: 2.81788e-07
+DEAL::Diff restrict add l2: 2.43079e-07
+DEAL::Diff restrict l3: 6.86195e-07
+DEAL::Diff restrict add l3: 9.19423e-07
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 2.10869e-07
+DEAL::Diff prolongate l2: 5.18665e-07
+DEAL::Diff restrict l1: 5.39228e-07
+DEAL::Diff restrict add l1: 6.22714e-07
+DEAL::Diff restrict l2: 1.05092e-06
+DEAL::Diff restrict add l2: 1.28920e-06
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 2.32831e-09
+DEAL::Diff prolongate l2: 1.06222e-07
+DEAL::Diff prolongate l3: 3.08336e-07
+DEAL::Diff prolongate l4: 6.35164e-07
+DEAL::Diff restrict l1: 9.77889e-08
+DEAL::Diff restrict add l1: 9.77889e-08
+DEAL::Diff restrict l2: 3.48858e-07
+DEAL::Diff restrict add l2: 4.43091e-07
+DEAL::Diff restrict l3: 6.32397e-07
+DEAL::Diff restrict add l3: 6.36345e-07
+DEAL::Diff restrict l4: 1.34609e-06
+DEAL::Diff restrict add l4: 1.74577e-06
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 4.65403e-07
+DEAL::Diff prolongate l2: 8.14610e-07
+DEAL::Diff restrict l1: 8.38442e-07
+DEAL::Diff restrict add l1: 1.04497e-06
+DEAL::Diff restrict l2: 1.93553e-06
+DEAL::Diff restrict add l2: 2.22941e-06
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 1.92120e-07
+DEAL::Diff prolongate l2: 4.89637e-07
+DEAL::Diff prolongate l3: 1.00159e-06
+DEAL::Diff restrict l1: 4.66622e-07
+DEAL::Diff restrict add l1: 6.18348e-07
+DEAL::Diff restrict l2: 1.07663e-06
+DEAL::Diff restrict add l2: 1.25560e-06
+DEAL::Diff restrict l3: 2.27705e-06
+DEAL::Diff restrict add l3: 2.76853e-06
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 1.86265e-08
+DEAL::Diff prolongate l2: 1.34182e-07
+DEAL::Diff prolongate l3: 2.50837e-07
+DEAL::Diff prolongate l4: 6.39631e-07
+DEAL::Diff prolongate l5: 1.36606e-06
+DEAL::Diff restrict l1: 1.41561e-07
+DEAL::Diff restrict add l1: 1.41561e-07
+DEAL::Diff restrict l2: 2.95878e-07
+DEAL::Diff restrict add l2: 3.03793e-07
+DEAL::Diff restrict l3: 7.65107e-07
+DEAL::Diff restrict add l3: 8.77487e-07
+DEAL::Diff restrict l4: 1.37239e-06
+DEAL::Diff restrict add l4: 1.69515e-06
+DEAL::Diff restrict l5: 2.90070e-06
+DEAL::Diff restrict add l5: 3.56294e-06
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 3.16376e-08
+DEAL::Diff restrict l1: 1.28523e-07
+DEAL::Diff restrict add l1: 6.05360e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 1.12532e-08
+DEAL::Diff prolongate l2: 3.87787e-07
+DEAL::Diff restrict l1: 6.46105e-08
+DEAL::Diff restrict add l1: 6.46105e-08
+DEAL::Diff restrict l2: 1.24234e-06
+DEAL::Diff restrict add l2: 1.24808e-06
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 8.05794e-07
+DEAL::Diff restrict l1: 2.83397e-06
+DEAL::Diff restrict add l1: 3.05075e-06
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 2.11658e-08
+DEAL::Diff prolongate l2: 3.90292e-07
+DEAL::Diff prolongate l3: 1.51881e-06
+DEAL::Diff restrict l1: 4.28758e-07
+DEAL::Diff restrict add l1: 4.28758e-07
+DEAL::Diff restrict l2: 1.01649e-06
+DEAL::Diff restrict add l2: 1.14211e-06
+DEAL::Diff restrict l3: 3.94122e-06
+DEAL::Diff restrict add l3: 4.23609e-06
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 2.14713e-06
+DEAL::Diff restrict l1: 6.15121e-06
+DEAL::Diff restrict add l1: 6.59074e-06
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 9.90071e-07
+DEAL::Diff prolongate l2: 2.90218e-06
+DEAL::Diff restrict l1: 3.04764e-06
+DEAL::Diff restrict add l1: 3.40151e-06
+DEAL::Diff restrict l2: 7.91521e-06
+DEAL::Diff restrict add l2: 8.68910e-06
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 1.73861e-08
+DEAL::Diff prolongate l2: 4.86459e-07
+DEAL::Diff prolongate l3: 1.41420e-06
+DEAL::Diff prolongate l4: 4.47432e-06
+DEAL::Diff restrict l1: 4.23752e-08
+DEAL::Diff restrict add l1: 4.34462e-07
+DEAL::Diff restrict l2: 1.49430e-06
+DEAL::Diff restrict add l2: 1.49275e-06
+DEAL::Diff restrict l3: 4.52097e-06
+DEAL::Diff restrict add l3: 4.93599e-06
+DEAL::Diff restrict l4: 1.26332e-05
+DEAL::Diff restrict add l4: 1.38610e-05
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.11022e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 6.28037e-16
+DEAL::Diff restrict add l3: 7.69185e-16
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.57009e-16
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 9.42055e-16
+DEAL::Diff restrict add l2: 8.88178e-16
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 2.73361e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 7.77156e-16
+DEAL::Diff restrict add l3: 8.00593e-16
+DEAL::Diff restrict l4: 1.29473e-15
+DEAL::Diff restrict add l4: 1.66163e-15
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 1.11022e-16
+DEAL::Diff prolongate l2: 3.46945e-16
+DEAL::Diff restrict l1: 8.00593e-16
+DEAL::Diff restrict add l1: 9.93014e-16
+DEAL::Diff restrict l2: 2.36037e-15
+DEAL::Diff restrict add l2: 2.58946e-15
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 9.61481e-17
+DEAL::Diff prolongate l3: 4.83935e-16
+DEAL::Diff restrict l1: 6.66134e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 9.42055e-16
+DEAL::Diff restrict add l2: 1.17495e-15
+DEAL::Diff restrict l3: 2.48253e-15
+DEAL::Diff restrict add l3: 2.73755e-15
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 5.55112e-17
+DEAL::Diff prolongate l4: 1.57009e-16
+DEAL::Diff prolongate l5: 5.14040e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 4.96507e-16
+DEAL::Diff restrict add l3: 6.28037e-16
+DEAL::Diff restrict l4: 1.70917e-15
+DEAL::Diff restrict add l4: 1.89715e-15
+DEAL::Diff restrict l5: 3.90950e-15
+DEAL::Diff restrict add l5: 4.28264e-15
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 5.86162e-16
+DEAL::Diff restrict l1: 1.08779e-15
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 4.39840e-16
+DEAL::Diff prolongate l2: 1.33460e-15
+DEAL::Diff restrict l1: 4.44089e-16
+DEAL::Diff restrict add l1: 4.44089e-16
+DEAL::Diff restrict l2: 2.37079e-15
+DEAL::Diff restrict add l2: 2.47258e-15
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 1.30473e-15
+DEAL::Diff restrict l1: 3.36198e-15
+DEAL::Diff restrict add l1: 3.78128e-15
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 1.57927e-16
+DEAL::Diff prolongate l2: 8.20434e-16
+DEAL::Diff prolongate l3: 2.02790e-15
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 8.88178e-16
+DEAL::Diff restrict l2: 1.15911e-15
+DEAL::Diff restrict add l2: 1.08779e-15
+DEAL::Diff restrict l3: 4.45440e-15
+DEAL::Diff restrict add l3: 4.48508e-15
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 2.50604e-15
+DEAL::Diff restrict l1: 5.30560e-15
+DEAL::Diff restrict add l1: 6.22913e-15
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 1.35942e-15
+DEAL::Diff prolongate l2: 3.05918e-15
+DEAL::Diff restrict l1: 3.54664e-15
+DEAL::Diff restrict add l1: 4.52339e-15
+DEAL::Diff restrict l2: 7.68849e-15
+DEAL::Diff restrict add l2: 8.53356e-15
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 4.25711e-16
+DEAL::Diff prolongate l2: 7.75419e-16
+DEAL::Diff prolongate l3: 1.72716e-15
+DEAL::Diff prolongate l4: 3.94909e-15
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 9.93014e-16
+DEAL::Diff restrict l2: 1.25607e-15
+DEAL::Diff restrict add l2: 1.71995e-15
+DEAL::Diff restrict l3: 4.36857e-15
+DEAL::Diff restrict add l3: 4.64705e-15
+DEAL::Diff restrict l4: 1.06615e-14
+DEAL::Diff restrict add l4: 1.15035e-14
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 1.66678e-16
+DEAL::Diff restrict l1: 1.17495e-15
+DEAL::Diff restrict add l1: 8.88178e-16
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 5.55112e-17
+DEAL::Diff prolongate l3: 3.80818e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 3.01196e-15
+DEAL::Diff restrict add l3: 3.32326e-15
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 5.62008e-16
+DEAL::Diff restrict l1: 4.35117e-15
+DEAL::Diff restrict add l1: 4.44089e-15
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 9.71445e-17
+DEAL::Diff prolongate l2: 1.03975e-15
+DEAL::Diff restrict l1: 9.93014e-16
+DEAL::Diff restrict add l1: 1.25607e-15
+DEAL::Diff restrict l2: 6.21725e-15
+DEAL::Diff restrict add l2: 6.73495e-15
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 3.42475e-16
+DEAL::Diff prolongate l4: 1.72594e-15
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 2.43238e-15
+DEAL::Diff restrict add l3: 2.34990e-15
+DEAL::Diff restrict l4: 1.14348e-14
+DEAL::Diff restrict add l4: 1.23310e-14
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 6.50327e-16
+DEAL::Diff restrict l1: 6.08904e-15
+DEAL::Diff restrict add l1: 6.02392e-15
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 9.68541e-16
+DEAL::Diff prolongate l2: 4.87552e-15
+DEAL::Diff restrict l1: 4.44089e-15
+DEAL::Diff restrict add l1: 4.52884e-15
+DEAL::Diff restrict l2: 2.01905e-14
+DEAL::Diff restrict add l2: 2.02986e-14
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 8.78343e-15
+DEAL::Diff restrict l1: 3.92368e-14
+DEAL::Diff restrict add l1: 3.96547e-14
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 8.84649e-16
+DEAL::Diff prolongate l2: 3.96858e-15
+DEAL::Diff prolongate l3: 1.31313e-14
+DEAL::Diff restrict l1: 2.17558e-15
+DEAL::Diff restrict add l1: 2.17558e-15
+DEAL::Diff restrict l2: 1.66037e-14
+DEAL::Diff restrict add l2: 1.69294e-14
+DEAL::Diff restrict l3: 6.69581e-14
+DEAL::Diff restrict add l3: 6.79718e-14
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 3.72529e-08
+DEAL::Diff prolongate l2: 1.23918e-07
+DEAL::Diff restrict l1: 1.97440e-07
+DEAL::Diff restrict add l1: 1.97440e-07
+DEAL::Diff restrict l2: 3.51720e-07
+DEAL::Diff restrict add l2: 4.38541e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 3.72529e-09
+DEAL::Diff prolongate l2: 1.31323e-07
+DEAL::Diff prolongate l3: 2.69264e-07
+DEAL::Diff restrict l1: 3.37139e-07
+DEAL::Diff restrict add l1: 9.87202e-08
+DEAL::Diff restrict l2: 4.04329e-07
+DEAL::Diff restrict add l2: 3.87504e-07
+DEAL::Diff restrict l3: 6.87816e-07
+DEAL::Diff restrict add l3: 8.68312e-07
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 2.07089e-07
+DEAL::Diff prolongate l2: 5.55799e-07
+DEAL::Diff restrict l1: 5.67399e-07
+DEAL::Diff restrict add l1: 7.86516e-07
+DEAL::Diff restrict l2: 1.29939e-06
+DEAL::Diff restrict add l2: 1.57817e-06
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 1.19267e-08
+DEAL::Diff prolongate l2: 1.39742e-07
+DEAL::Diff prolongate l3: 3.09723e-07
+DEAL::Diff prolongate l4: 6.63463e-07
+DEAL::Diff restrict l1: 3.07336e-08
+DEAL::Diff restrict add l1: 3.07336e-08
+DEAL::Diff restrict l2: 1.83328e-07
+DEAL::Diff restrict add l2: 2.05324e-07
+DEAL::Diff restrict l3: 6.59020e-07
+DEAL::Diff restrict add l3: 8.18489e-07
+DEAL::Diff restrict l4: 1.44435e-06
+DEAL::Diff restrict add l4: 1.85608e-06
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 4.05180e-07
+DEAL::Diff prolongate l2: 8.54370e-07
+DEAL::Diff restrict l1: 9.93212e-07
+DEAL::Diff restrict add l1: 1.14004e-06
+DEAL::Diff restrict l2: 1.74876e-06
+DEAL::Diff restrict add l2: 2.16962e-06
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 1.74155e-07
+DEAL::Diff prolongate l2: 5.19866e-07
+DEAL::Diff prolongate l3: 9.61759e-07
+DEAL::Diff restrict l1: 3.23313e-07
+DEAL::Diff restrict add l1: 4.09015e-07
+DEAL::Diff restrict l2: 1.06199e-06
+DEAL::Diff restrict add l2: 1.32974e-06
+DEAL::Diff restrict l3: 2.21171e-06
+DEAL::Diff restrict add l3: 2.64991e-06
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.24189e-07
+DEAL::Diff prolongate l3: 2.63914e-07
+DEAL::Diff prolongate l4: 6.15720e-07
+DEAL::Diff prolongate l5: 1.36740e-06
+DEAL::Diff restrict l1: 1.08965e-07
+DEAL::Diff restrict add l1: 1.08965e-07
+DEAL::Diff restrict l2: 2.46043e-07
+DEAL::Diff restrict add l2: 3.26259e-07
+DEAL::Diff restrict l3: 7.10773e-07
+DEAL::Diff restrict add l3: 7.74864e-07
+DEAL::Diff restrict l4: 1.38466e-06
+DEAL::Diff restrict add l4: 1.63680e-06
+DEAL::Diff restrict l5: 2.98024e-06
+DEAL::Diff restrict add l5: 3.66432e-06
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 1.39089e-07
+DEAL::Diff restrict l1: 3.51210e-07
+DEAL::Diff restrict add l1: 3.51210e-07
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 5.32730e-08
+DEAL::Diff prolongate l2: 3.47201e-07
+DEAL::Diff restrict l1: 2.75424e-07
+DEAL::Diff restrict add l1: 2.75424e-07
+DEAL::Diff restrict l2: 1.37599e-06
+DEAL::Diff restrict add l2: 1.65391e-06
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 8.13494e-07
+DEAL::Diff restrict l1: 2.76829e-06
+DEAL::Diff restrict add l1: 3.07971e-06
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 5.82505e-08
+DEAL::Diff prolongate l2: 5.17285e-07
+DEAL::Diff prolongate l3: 1.42520e-06
+DEAL::Diff restrict l1: 1.60479e-07
+DEAL::Diff restrict add l1: 1.60479e-07
+DEAL::Diff restrict l2: 1.21423e-06
+DEAL::Diff restrict add l2: 1.45209e-06
+DEAL::Diff restrict l3: 4.13711e-06
+DEAL::Diff restrict add l3: 4.50632e-06
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 2.05461e-06
+DEAL::Diff restrict l1: 6.41987e-06
+DEAL::Diff restrict add l1: 7.01234e-06
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 7.72673e-07
+DEAL::Diff prolongate l2: 2.80277e-06
+DEAL::Diff restrict l1: 2.64256e-06
+DEAL::Diff restrict add l1: 3.00814e-06
+DEAL::Diff restrict l2: 8.18270e-06
+DEAL::Diff restrict add l2: 8.99079e-06
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 1.40781e-08
+DEAL::Diff prolongate l2: 3.60453e-07
+DEAL::Diff prolongate l3: 1.41714e-06
+DEAL::Diff prolongate l4: 4.48438e-06
+DEAL::Diff restrict l1: 2.01369e-07
+DEAL::Diff restrict add l1: 2.01369e-07
+DEAL::Diff restrict l2: 1.42552e-06
+DEAL::Diff restrict add l2: 1.66821e-06
+DEAL::Diff restrict l3: 4.00370e-06
+DEAL::Diff restrict add l3: 4.28661e-06
+DEAL::Diff restrict l4: 1.28845e-05
+DEAL::Diff restrict add l4: 1.39500e-05
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with adaptive meshes for FE_Q
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 5.55112e-17
+DEAL::Diff prolongate l4: 1.46869e-16
+DEAL::Diff prolongate l5: 1.57009e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 1.06489e-15
+DEAL::Diff restrict add l3: 1.08779e-15
+DEAL::Diff restrict l4: 6.28037e-16
+DEAL::Diff restrict add l4: 6.28037e-16
+DEAL::Diff restrict l5: 5.43896e-16
+DEAL::Diff restrict add l5: 7.69185e-16
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 7.85046e-17
+DEAL::Diff prolongate l4: 1.66533e-16
+DEAL::Diff prolongate l5: 2.41967e-16
+DEAL::Diff prolongate l6: 3.92523e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 9.42055e-16
+DEAL::Diff restrict add l3: 9.93014e-16
+DEAL::Diff restrict l4: 4.00297e-16
+DEAL::Diff restrict add l4: 4.44089e-16
+DEAL::Diff restrict l5: 1.13764e-15
+DEAL::Diff restrict add l5: 1.08779e-15
+DEAL::Diff restrict l6: 1.11576e-15
+DEAL::Diff restrict add l6: 1.60119e-15
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 2.22045e-16
+DEAL::Diff prolongate l3: 1.92296e-16
+DEAL::Diff prolongate l4: 4.00297e-16
+DEAL::Diff prolongate l5: 3.26349e-16
+DEAL::Diff restrict l1: 4.96507e-16
+DEAL::Diff restrict add l1: 8.88178e-16
+DEAL::Diff restrict l2: 8.88178e-16
+DEAL::Diff restrict add l2: 9.93014e-16
+DEAL::Diff restrict l3: 9.28879e-16
+DEAL::Diff restrict add l3: 1.08779e-15
+DEAL::Diff restrict l4: 1.58960e-15
+DEAL::Diff restrict add l4: 1.73422e-15
+DEAL::Diff restrict l5: 2.10942e-15
+DEAL::Diff restrict add l5: 2.53170e-15
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 3.87150e-16
+DEAL::Diff prolongate l2: 8.39463e-16
+DEAL::Diff prolongate l3: 1.04489e-15
+DEAL::Diff prolongate l4: 6.84528e-16
+DEAL::Diff restrict l1: 6.28037e-16
+DEAL::Diff restrict add l1: 8.88178e-16
+DEAL::Diff restrict l2: 2.67435e-15
+DEAL::Diff restrict add l2: 2.87803e-15
+DEAL::Diff restrict l3: 3.27845e-15
+DEAL::Diff restrict add l3: 4.18364e-15
+DEAL::Diff restrict l4: 1.71928e-15
+DEAL::Diff restrict add l4: 1.91010e-15
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 2.36534e-16
+DEAL::Diff prolongate l2: 8.41983e-16
+DEAL::Diff prolongate l3: 1.26888e-15
+DEAL::Diff prolongate l4: 1.72555e-15
+DEAL::Diff prolongate l5: 1.18848e-15
+DEAL::Diff restrict l1: 1.25607e-15
+DEAL::Diff restrict add l1: 1.25607e-15
+DEAL::Diff restrict l2: 2.58708e-15
+DEAL::Diff restrict add l2: 2.68298e-15
+DEAL::Diff restrict l3: 3.75399e-15
+DEAL::Diff restrict add l3: 4.21300e-15
+DEAL::Diff restrict l4: 4.85334e-15
+DEAL::Diff restrict add l4: 5.51100e-15
+DEAL::Diff restrict l5: 3.22837e-15
+DEAL::Diff restrict add l5: 3.83951e-15
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 1.38498e-15
+DEAL::Diff prolongate l2: 1.34926e-15
+DEAL::Diff prolongate l3: 1.69608e-15
+DEAL::Diff prolongate l4: 1.56273e-15
+DEAL::Diff restrict l1: 3.77517e-15
+DEAL::Diff restrict add l1: 4.00297e-15
+DEAL::Diff restrict l2: 4.20833e-15
+DEAL::Diff restrict add l2: 4.82404e-15
+DEAL::Diff restrict l3: 5.06973e-15
+DEAL::Diff restrict add l3: 5.63486e-15
+DEAL::Diff restrict l4: 5.06820e-15
+DEAL::Diff restrict add l4: 5.54223e-15
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 2.02658e-16
+DEAL::Diff prolongate l4: 5.37540e-16
+DEAL::Diff prolongate l5: 4.59437e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 8.88178e-16
+DEAL::Diff restrict add l2: 8.88178e-16
+DEAL::Diff restrict l3: 1.96104e-15
+DEAL::Diff restrict add l3: 2.12978e-15
+DEAL::Diff restrict l4: 3.17919e-15
+DEAL::Diff restrict add l4: 3.97205e-15
+DEAL::Diff restrict l5: 3.37661e-15
+DEAL::Diff restrict add l5: 3.97826e-15
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 2.29404e-16
+DEAL::Diff prolongate l2: 3.60822e-16
+DEAL::Diff prolongate l3: 7.51197e-16
+DEAL::Diff prolongate l4: 1.02364e-15
+DEAL::Diff restrict l1: 1.25607e-15
+DEAL::Diff restrict add l1: 1.83103e-15
+DEAL::Diff restrict l2: 2.95411e-15
+DEAL::Diff restrict add l2: 3.14018e-15
+DEAL::Diff restrict l3: 5.89569e-15
+DEAL::Diff restrict add l3: 6.37388e-15
+DEAL::Diff restrict l4: 6.45936e-15
+DEAL::Diff restrict add l4: 7.08110e-15
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 1.07692e-15
+DEAL::Diff prolongate l2: 1.20589e-15
+DEAL::Diff restrict l1: 5.02430e-15
+DEAL::Diff restrict add l1: 4.61511e-15
+DEAL::Diff restrict l2: 6.91131e-15
+DEAL::Diff restrict add l2: 6.76052e-15
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 3.78442e-15
+DEAL::Diff prolongate l2: 5.40000e-15
+DEAL::Diff prolongate l3: 3.66590e-15
+DEAL::Diff restrict l1: 2.62434e-14
+DEAL::Diff restrict add l1: 2.64653e-14
+DEAL::Diff restrict l2: 3.55385e-14
+DEAL::Diff restrict add l2: 3.60157e-14
+DEAL::Diff restrict l3: 2.16938e-14
+DEAL::Diff restrict add l3: 2.19353e-14
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.82947e-07
+DEAL::Diff prolongate l3: 2.73352e-07
+DEAL::Diff prolongate l4: 2.90000e-07
+DEAL::Diff prolongate l5: 2.38384e-07
+DEAL::Diff restrict l1: 1.25729e-07
+DEAL::Diff restrict add l1: 1.25729e-07
+DEAL::Diff restrict l2: 4.51923e-07
+DEAL::Diff restrict add l2: 4.64551e-07
+DEAL::Diff restrict l3: 5.80701e-07
+DEAL::Diff restrict add l3: 7.99297e-07
+DEAL::Diff restrict l4: 6.55915e-07
+DEAL::Diff restrict add l4: 9.76871e-07
+DEAL::Diff restrict l5: 4.91499e-07
+DEAL::Diff restrict add l5: 6.27939e-07
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 3.00343e-08
+DEAL::Diff prolongate l2: 1.06605e-07
+DEAL::Diff prolongate l3: 3.42290e-07
+DEAL::Diff prolongate l4: 3.27767e-07
+DEAL::Diff prolongate l5: 4.72479e-07
+DEAL::Diff prolongate l6: 4.70342e-07
+DEAL::Diff restrict l1: 1.13621e-07
+DEAL::Diff restrict add l1: 1.13621e-07
+DEAL::Diff restrict l2: 3.72885e-07
+DEAL::Diff restrict add l2: 3.82058e-07
+DEAL::Diff restrict l3: 6.77499e-07
+DEAL::Diff restrict add l3: 8.80222e-07
+DEAL::Diff restrict l4: 7.41751e-07
+DEAL::Diff restrict add l4: 1.01957e-06
+DEAL::Diff restrict l5: 8.74257e-07
+DEAL::Diff restrict add l5: 1.11659e-06
+DEAL::Diff restrict l6: 9.89949e-07
+DEAL::Diff restrict add l6: 1.16693e-06
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 2.03307e-07
+DEAL::Diff prolongate l2: 4.70858e-07
+DEAL::Diff prolongate l3: 4.27724e-07
+DEAL::Diff prolongate l4: 5.97569e-07
+DEAL::Diff prolongate l5: 6.83253e-07
+DEAL::Diff restrict l1: 4.87117e-07
+DEAL::Diff restrict add l1: 7.26694e-07
+DEAL::Diff restrict l2: 1.09591e-06
+DEAL::Diff restrict add l2: 1.38195e-06
+DEAL::Diff restrict l3: 9.63365e-07
+DEAL::Diff restrict add l3: 1.11536e-06
+DEAL::Diff restrict l4: 1.13478e-06
+DEAL::Diff restrict add l4: 1.32608e-06
+DEAL::Diff restrict l5: 1.39715e-06
+DEAL::Diff restrict add l5: 1.70729e-06
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 3.02644e-08
+DEAL::Diff prolongate l2: 5.10510e-08
+DEAL::Diff restrict l1: 3.77651e-07
+DEAL::Diff restrict add l1: 3.77651e-07
+DEAL::Diff restrict l2: 4.99556e-07
+DEAL::Diff restrict add l2: 4.99556e-07
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 6.05288e-08
+DEAL::Diff prolongate l2: 2.69857e-07
+DEAL::Diff prolongate l3: 8.37737e-07
+DEAL::Diff prolongate l4: 1.27552e-06
+DEAL::Diff prolongate l5: 1.40443e-06
+DEAL::Diff restrict l1: 6.15662e-07
+DEAL::Diff restrict add l1: 6.15662e-07
+DEAL::Diff restrict l2: 1.21900e-06
+DEAL::Diff restrict add l2: 1.34318e-06
+DEAL::Diff restrict l3: 2.64206e-06
+DEAL::Diff restrict add l3: 2.85523e-06
+DEAL::Diff restrict l4: 3.79070e-06
+DEAL::Diff restrict add l4: 4.12862e-06
+DEAL::Diff restrict l5: 3.57424e-06
+DEAL::Diff restrict add l5: 3.89088e-06
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 8.63082e-07
+DEAL::Diff prolongate l2: 1.02885e-06
+DEAL::Diff prolongate l3: 1.86363e-06
+DEAL::Diff prolongate l4: 2.64187e-06
+DEAL::Diff restrict l1: 2.70130e-06
+DEAL::Diff restrict add l1: 2.81647e-06
+DEAL::Diff restrict l2: 3.09755e-06
+DEAL::Diff restrict add l2: 3.25362e-06
+DEAL::Diff restrict l3: 4.73380e-06
+DEAL::Diff restrict add l3: 5.08899e-06
+DEAL::Diff restrict l4: 6.73984e-06
+DEAL::Diff restrict add l4: 7.45000e-06
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.11022e-16
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 5.55112e-17
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 4.44089e-16
+DEAL::Diff restrict add l3: 4.44089e-16
+DEAL::Diff restrict l4: 6.75322e-16
+DEAL::Diff restrict add l4: 6.66134e-16
+DEAL::Diff restrict l5: 4.00297e-16
+DEAL::Diff restrict add l5: 4.44089e-16
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 5.55112e-17
+DEAL::Diff prolongate l4: 9.61481e-17
+DEAL::Diff prolongate l5: 1.92296e-16
+DEAL::Diff prolongate l6: 2.09665e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 5.87475e-16
+DEAL::Diff restrict add l3: 6.28037e-16
+DEAL::Diff restrict l4: 3.33067e-16
+DEAL::Diff restrict add l4: 4.96507e-16
+DEAL::Diff restrict l5: 8.75951e-16
+DEAL::Diff restrict add l5: 1.13221e-15
+DEAL::Diff restrict l6: 1.49365e-15
+DEAL::Diff restrict add l6: 1.53837e-15
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.92296e-16
+DEAL::Diff prolongate l3: 2.09550e-16
+DEAL::Diff prolongate l4: 3.18887e-16
+DEAL::Diff prolongate l5: 3.14325e-16
+DEAL::Diff restrict l1: 4.96507e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 1.17495e-15
+DEAL::Diff restrict add l2: 1.17495e-15
+DEAL::Diff restrict l3: 1.15911e-15
+DEAL::Diff restrict add l3: 1.35064e-15
+DEAL::Diff restrict l4: 1.20089e-15
+DEAL::Diff restrict add l4: 1.61651e-15
+DEAL::Diff restrict l5: 1.72353e-15
+DEAL::Diff restrict add l5: 1.94843e-15
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 2.93415e-16
+DEAL::Diff prolongate l2: 1.12179e-15
+DEAL::Diff prolongate l3: 8.90270e-16
+DEAL::Diff prolongate l4: 9.68765e-16
+DEAL::Diff restrict l1: 7.69185e-16
+DEAL::Diff restrict add l1: 8.88178e-16
+DEAL::Diff restrict l2: 2.12398e-15
+DEAL::Diff restrict add l2: 1.67640e-15
+DEAL::Diff restrict l3: 1.93335e-15
+DEAL::Diff restrict add l3: 1.99840e-15
+DEAL::Diff restrict l4: 1.65070e-15
+DEAL::Diff restrict add l4: 1.79018e-15
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 4.19100e-16
+DEAL::Diff prolongate l2: 7.23163e-16
+DEAL::Diff prolongate l3: 1.49879e-15
+DEAL::Diff prolongate l4: 1.67926e-15
+DEAL::Diff prolongate l5: 1.34221e-15
+DEAL::Diff restrict l1: 3.84593e-16
+DEAL::Diff restrict add l1: 6.28037e-16
+DEAL::Diff restrict l2: 1.88738e-15
+DEAL::Diff restrict add l2: 1.99840e-15
+DEAL::Diff restrict l3: 3.40071e-15
+DEAL::Diff restrict add l3: 3.43990e-15
+DEAL::Diff restrict l4: 3.82627e-15
+DEAL::Diff restrict add l4: 3.64180e-15
+DEAL::Diff restrict l5: 3.84392e-15
+DEAL::Diff restrict add l5: 4.40746e-15
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 1.54021e-15
+DEAL::Diff prolongate l2: 1.55808e-15
+DEAL::Diff prolongate l3: 2.01813e-15
+DEAL::Diff prolongate l4: 1.80659e-15
+DEAL::Diff restrict l1: 3.42779e-15
+DEAL::Diff restrict add l1: 3.95962e-15
+DEAL::Diff restrict l2: 3.98735e-15
+DEAL::Diff restrict add l2: 4.56138e-15
+DEAL::Diff restrict l3: 4.36875e-15
+DEAL::Diff restrict add l3: 5.08283e-15
+DEAL::Diff restrict l4: 4.48817e-15
+DEAL::Diff restrict add l4: 5.31053e-15
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 2.18548e-16
+DEAL::Diff prolongate l4: 4.49062e-16
+DEAL::Diff prolongate l5: 5.55805e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 2.03507e-15
+DEAL::Diff restrict add l3: 2.03507e-15
+DEAL::Diff restrict l4: 3.29345e-15
+DEAL::Diff restrict add l4: 3.46845e-15
+DEAL::Diff restrict l5: 2.99760e-15
+DEAL::Diff restrict add l5: 3.68888e-15
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 2.60370e-16
+DEAL::Diff prolongate l2: 4.20018e-16
+DEAL::Diff prolongate l3: 6.98592e-16
+DEAL::Diff prolongate l4: 1.25803e-15
+DEAL::Diff restrict l1: 1.25607e-15
+DEAL::Diff restrict add l1: 9.93014e-16
+DEAL::Diff restrict l2: 2.22045e-15
+DEAL::Diff restrict add l2: 2.39149e-15
+DEAL::Diff restrict l3: 3.57347e-15
+DEAL::Diff restrict add l3: 3.60780e-15
+DEAL::Diff restrict l4: 5.93424e-15
+DEAL::Diff restrict add l4: 7.19164e-15
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 6.25665e-16
+DEAL::Diff prolongate l2: 1.12982e-15
+DEAL::Diff restrict l1: 3.07674e-15
+DEAL::Diff restrict add l1: 2.80867e-15
+DEAL::Diff restrict l2: 7.89196e-15
+DEAL::Diff restrict add l2: 8.16448e-15
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 4.47538e-15
+DEAL::Diff prolongate l2: 6.65118e-15
+DEAL::Diff prolongate l3: 4.28755e-15
+DEAL::Diff restrict l1: 2.07451e-14
+DEAL::Diff restrict add l1: 2.17150e-14
+DEAL::Diff restrict l2: 2.76721e-14
+DEAL::Diff restrict add l2: 2.85472e-14
+DEAL::Diff restrict l3: 2.07301e-14
+DEAL::Diff restrict add l3: 2.14859e-14
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 1.53598e-08
+DEAL::Diff prolongate l2: 1.32451e-07
+DEAL::Diff prolongate l3: 2.77478e-07
+DEAL::Diff prolongate l4: 2.43327e-07
+DEAL::Diff prolongate l5: 1.99307e-07
+DEAL::Diff restrict l1: 1.55531e-07
+DEAL::Diff restrict add l1: 1.55531e-07
+DEAL::Diff restrict l2: 1.80699e-07
+DEAL::Diff restrict add l2: 2.68656e-07
+DEAL::Diff restrict l3: 5.31998e-07
+DEAL::Diff restrict add l3: 6.10878e-07
+DEAL::Diff restrict l4: 6.72091e-07
+DEAL::Diff restrict add l4: 7.96976e-07
+DEAL::Diff restrict l5: 4.78152e-07
+DEAL::Diff restrict add l5: 6.10737e-07
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 9.31323e-09
+DEAL::Diff prolongate l2: 1.14023e-07
+DEAL::Diff prolongate l3: 3.02950e-07
+DEAL::Diff prolongate l4: 3.31972e-07
+DEAL::Diff prolongate l5: 4.83178e-07
+DEAL::Diff prolongate l6: 4.49200e-07
+DEAL::Diff restrict l1: 1.00117e-08
+DEAL::Diff restrict add l1: 1.00117e-08
+DEAL::Diff restrict l2: 3.03629e-07
+DEAL::Diff restrict add l2: 3.35049e-07
+DEAL::Diff restrict l3: 6.96781e-07
+DEAL::Diff restrict add l3: 9.83613e-07
+DEAL::Diff restrict l4: 6.53890e-07
+DEAL::Diff restrict add l4: 7.96383e-07
+DEAL::Diff restrict l5: 1.05105e-06
+DEAL::Diff restrict add l5: 1.35094e-06
+DEAL::Diff restrict l6: 9.63780e-07
+DEAL::Diff restrict add l6: 1.22002e-06
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 1.96297e-07
+DEAL::Diff prolongate l2: 4.29379e-07
+DEAL::Diff prolongate l3: 3.78592e-07
+DEAL::Diff prolongate l4: 5.48624e-07
+DEAL::Diff prolongate l5: 7.03000e-07
+DEAL::Diff restrict l1: 3.35044e-07
+DEAL::Diff restrict add l1: 3.89982e-07
+DEAL::Diff restrict l2: 1.15122e-06
+DEAL::Diff restrict add l2: 1.32525e-06
+DEAL::Diff restrict l3: 1.00435e-06
+DEAL::Diff restrict add l3: 1.22192e-06
+DEAL::Diff restrict l4: 1.23935e-06
+DEAL::Diff restrict add l4: 1.47309e-06
+DEAL::Diff restrict l5: 1.32602e-06
+DEAL::Diff restrict add l5: 1.91723e-06
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 1.05367e-08
+DEAL::Diff prolongate l2: 1.17397e-07
+DEAL::Diff restrict l1: 2.84635e-07
+DEAL::Diff restrict add l1: 2.84635e-07
+DEAL::Diff restrict l2: 5.41568e-07
+DEAL::Diff restrict add l2: 8.78831e-07
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 1.39089e-07
+DEAL::Diff prolongate l2: 3.79811e-07
+DEAL::Diff prolongate l3: 1.01625e-06
+DEAL::Diff prolongate l4: 1.27553e-06
+DEAL::Diff prolongate l5: 1.29250e-06
+DEAL::Diff restrict l1: 1.37952e-07
+DEAL::Diff restrict add l1: 1.37952e-07
+DEAL::Diff restrict l2: 1.18038e-06
+DEAL::Diff restrict add l2: 1.25114e-06
+DEAL::Diff restrict l3: 2.41311e-06
+DEAL::Diff restrict add l3: 2.66759e-06
+DEAL::Diff restrict l4: 3.55824e-06
+DEAL::Diff restrict add l4: 3.81845e-06
+DEAL::Diff restrict l5: 3.73363e-06
+DEAL::Diff restrict add l5: 4.00464e-06
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 9.71673e-07
+DEAL::Diff prolongate l2: 1.00927e-06
+DEAL::Diff prolongate l3: 1.78966e-06
+DEAL::Diff prolongate l4: 2.55606e-06
+DEAL::Diff restrict l1: 2.80919e-06
+DEAL::Diff restrict add l1: 2.85094e-06
+DEAL::Diff restrict l2: 2.81573e-06
+DEAL::Diff restrict add l2: 3.01700e-06
+DEAL::Diff restrict l3: 4.79409e-06
+DEAL::Diff restrict add l3: 5.48025e-06
+DEAL::Diff restrict l4: 6.45920e-06
+DEAL::Diff restrict add l4: 7.19753e-06
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferBlockMatrixFree by comparison with MGTransferMatrixFree on a
+// series of adaptive meshes for FE_Q. This is, essentially, a
+// copy-paste of transfer_matrix_free_02.cc
+
+#include <deal.II/base/logstream.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_block_vector.h>
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference
+ MGTransferMF<dim, Number> transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferBlockMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ const unsigned int nb = 3;
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::BlockVector<Number> v1(nb), v2(nb),
+ v3(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v1.block(b).reinit(mgdof.locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+ v2.block(b).reinit(mgdof.locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+ v3.block(b).reinit(mgdof.locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+
+ for (unsigned int i = 0; i < v1.block(b).locally_owned_size();
+ ++i)
+ v1.block(b).local_element(i) = random_value<double>();
+
+ transfer_ref.prolongate(level, v2.block(b), v1.block(b));
+ }
+
+ transfer.prolongate(level, v3, v1);
+ v3 -= v2;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::BlockVector<Number> v1(nb), v2(nb),
+ v3(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v1.block(b).reinit(mgdof.locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+ v2.block(b).reinit(mgdof.locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+ v3.block(b).reinit(mgdof.locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+
+ for (unsigned int i = 0; i < v1.block(b).locally_owned_size();
+ ++i)
+ v1.block(b).local_element(i) = random_value<double>();
+
+ transfer_ref.restrict_and_add(level, v2.block(b), v1.block(b));
+ }
+
+ transfer.restrict_and_add(level, v3, v1);
+ v3 -= v2;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ for (unsigned int b = 0; b < nb; ++b)
+ transfer_ref.restrict_and_add(level, v3.block(b), v1.block(b));
+ v3 -= v2;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff prolongate l6: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::Diff restrict l6: 0
+DEAL::Diff restrict add l6: 0
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff prolongate l6: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::Diff restrict l6: 0
+DEAL::Diff restrict add l6: 0
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff prolongate l5: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::Diff restrict l5: 0
+DEAL::Diff restrict add l5: 0
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0
+DEAL::Diff prolongate l2: 0
+DEAL::Diff prolongate l3: 0
+DEAL::Diff prolongate l4: 0
+DEAL::Diff restrict l1: 0
+DEAL::Diff restrict add l1: 0
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::Diff restrict l3: 0
+DEAL::Diff restrict add l3: 0
+DEAL::Diff restrict l4: 0
+DEAL::Diff restrict add l4: 0
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferBlockMatrixFree by comparison with MGTransferMatrixFree on a
+// series of adaptive meshes for FE_Q. This is similar to
+// transfer_matrix_free_02.cc but using separate DoFHandlers for each block.
+
+#include <deal.II/base/logstream.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_block_vector.h>
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ const unsigned int nb = 2;
+
+ FE_Q<dim> fe_1(fe_degree + 1);
+ FE_Q<dim> fe_2(fe_degree);
+
+ deallog << "FE: " << fe_1.get_name() << std::endl;
+ deallog << "FE: " << fe_2.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof_1(tr);
+ mgdof_1.distribute_dofs(fe_1);
+ mgdof_1.distribute_mg_dofs();
+
+ DoFHandler<dim> mgdof_2(tr);
+ mgdof_2.distribute_dofs(fe_2);
+ mgdof_2.distribute_mg_dofs();
+
+ const std::vector<const DoFHandler<dim> *> mgdof_ptr{&mgdof_1, &mgdof_2};
+
+ std::vector<MGConstrainedDoFs> mg_constrained_dofs_vector(2);
+ for (unsigned int i = 0; i < mgdof_ptr.size(); ++i)
+ {
+ mg_constrained_dofs_vector[i].initialize(*mgdof_ptr[i]);
+ mg_constrained_dofs_vector[i].make_zero_boundary_constraints(
+ *mgdof_ptr[i], {0});
+ }
+
+ // build reference
+ std::vector<MGTransferMF<dim, Number>> transfer_ref;
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ transfer_ref.emplace_back(mg_constrained_dofs_vector[b]);
+ transfer_ref[b].build(*mgdof_ptr[b]);
+ }
+
+ // build matrix-free transfer
+ MGTransferBlockMF<dim, Number> transfer(mg_constrained_dofs_vector);
+ transfer.build(mgdof_ptr);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof_ptr[0]->get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::BlockVector<Number> v1(nb), v2(nb),
+ v3(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v1.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+ v2.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+ v3.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+
+ for (unsigned int i = 0; i < v1.block(b).locally_owned_size();
+ ++i)
+ v1.block(b).local_element(i) = random_value<double>();
+
+ transfer_ref[b].prolongate(level, v2.block(b), v1.block(b));
+ }
+
+ transfer.prolongate(level, v3, v1);
+ v3 -= v2;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof_ptr[0]->get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::BlockVector<Number> v1(nb), v2(nb),
+ v3(nb);
+ for (unsigned int b = 0; b < nb; ++b)
+ {
+ v1.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level),
+ MPI_COMM_WORLD);
+ v2.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+ v3.block(b).reinit(mgdof_ptr[b]->locally_owned_mg_dofs(level - 1),
+ MPI_COMM_WORLD);
+
+ for (unsigned int i = 0; i < v1.block(b).locally_owned_size();
+ ++i)
+ v1.block(b).local_element(i) = random_value<double>();
+
+ transfer_ref[b].restrict_and_add(level, v2.block(b), v1.block(b));
+ }
+
+ transfer.restrict_and_add(level, v3, v1);
+ v3 -= v2;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ for (unsigned int b = 0; b < nb; ++b)
+ transfer_ref[b].restrict_and_add(level, v3.block(b), v1.block(b));
+ v3 -= v2;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(2)
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(4)
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(4)
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with adaptive meshes for FE_Q (similar to
+// transfer_matrix_free_02 but on a different mesh refining into a corner)
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, 3);
+ for (unsigned int cycle = 0; cycle < (dim == 2 ? 10 : 7); ++cycle)
+ {
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->vertex(0).norm() < 1e-10)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << " on "
+ << tr.n_global_levels() << " levels" << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 12 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 15 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 18 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 21 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 24 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 27 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 30 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
+DEAL::no. cells: 33 on 9 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::
+DEAL::no. cells: 36 on 10 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::
+DEAL::no. cells: 39 on 11 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff prolongate l10: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::Diff restrict l10: 0.00000
+DEAL::Diff restrict add l10: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(3)
+DEAL::no. cells: 12 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 15 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 18 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 21 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 24 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 27 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 30 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
+DEAL::no. cells: 33 on 9 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::
+DEAL::no. cells: 36 on 10 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::
+DEAL::no. cells: 39 on 11 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff prolongate l10: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::Diff restrict l10: 0.00000
+DEAL::Diff restrict add l10: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 34 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 41 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 48 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 55 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 62 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 69 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 76 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(3)
+DEAL::no. cells: 34 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 41 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 48 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 55 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 62 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 69 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 76 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 12 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 15 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 18 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 21 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 24 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 27 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 30 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
+DEAL::no. cells: 33 on 9 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::
+DEAL::no. cells: 36 on 10 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::
+DEAL::no. cells: 39 on 11 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff prolongate l8: 0.00000
+DEAL::Diff prolongate l9: 0.00000
+DEAL::Diff prolongate l10: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::Diff restrict l8: 0.00000
+DEAL::Diff restrict add l8: 0.00000
+DEAL::Diff restrict l9: 0.00000
+DEAL::Diff restrict add l9: 0.00000
+DEAL::Diff restrict l10: 0.00000
+DEAL::Diff restrict add l10: 0.00000
+DEAL::
+DEAL::FE: FE_Q<3>(2)
+DEAL::no. cells: 34 on 2 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 41 on 3 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 48 on 4 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 55 on 5 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 62 on 6 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 69 on 7 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 76 on 8 levels
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff prolongate l7: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::Diff restrict l7: 0.00000
+DEAL::Diff restrict add l7: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with uniform meshes for FE_DGQ (except for the different
+// element and no constraints the same test as transfer_matrix_free_01)
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_dgq.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_DGQ<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3, 4, 5, 6, 8};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref;
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer;
+ transfer.build(mgdof);
+
+ const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ IndexSet relevant_set;
+ DoFTools::extract_locally_relevant_level_dofs(mgdof,
+ level,
+ relevant_set);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level),
+ relevant_set,
+ MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ deallog << "Vectors have ghosts: " << v2.has_ghost_elements() << ' '
+ << v3.has_ghost_elements() << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 3.02285e-13
+DEAL::Diff restrict add l3: 3.02551e-13
+DEAL::
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 3.02285e-13
+DEAL::Diff restrict add l3: 3.02551e-13
+DEAL::
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(1)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 4
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 36
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 100
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(1)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 27
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 125
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 3.02285e-13
+DEAL::Diff restrict add l3: 3.02551e-13
+DEAL::
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 16
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 144
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 256
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 400
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 576
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1024
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(2)
+DEAL::no. cells: 8
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 64
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 216
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 512
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::no. cells: 1000
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::
+DEAL::no. cells: 1728
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 4096
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Vectors have ghosts: 0 0
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with adaptive meshes for FE_DGQ (except for the different
+// element and no constraints the same test as transfer_matrix_free_01)
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_dgq.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_DGQ<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref;
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer;
+ transfer.build(mgdof);
+
+ const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": "
+ << filter_out_small_numbers(v3.l2_norm(), tolerance)
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff prolongate l6: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::Diff restrict l6: 0.00000
+DEAL::Diff restrict add l6: 0.00000
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::FE: FE_DGQ<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff prolongate l5: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::Diff restrict l5: 0.00000
+DEAL::Diff restrict add l5: 0.00000
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 0.00000
+DEAL::Diff prolongate l4: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 0.00000
+DEAL::Diff restrict add l3: 0.00000
+DEAL::Diff restrict l4: 0.00000
+DEAL::Diff restrict add l4: 0.00000
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with adaptive meshes for FESystem(FE_Q,2). Same as
+// transfer_matrix_free_02 but using two components (and fewer meshes).
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FESystem<dim> fe(FE_Q<dim>(fe_degree), 2);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 6 - 2 * dim;
+ if (fe_degree == 1)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FESystem<2>[FE_Q<2>(1)^2]
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.92296e-16
+DEAL::Diff prolongate l4: 1.57009e-16
+DEAL::Diff prolongate l5: 4.04127e-16
+DEAL::Diff prolongate l6: 3.12789e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 1.08779e-15
+DEAL::Diff restrict add l3: 1.17495e-15
+DEAL::Diff restrict l4: 1.23629e-15
+DEAL::Diff restrict add l4: 1.25607e-15
+DEAL::Diff restrict l5: 1.52226e-15
+DEAL::Diff restrict add l5: 1.77636e-15
+DEAL::Diff restrict l6: 1.80390e-15
+DEAL::Diff restrict add l6: 2.28609e-15
+DEAL::
+DEAL::no. cells: 868
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 5.55112e-17
+DEAL::Diff prolongate l4: 3.68219e-16
+DEAL::Diff prolongate l5: 4.02217e-16
+DEAL::Diff prolongate l6: 5.88130e-16
+DEAL::Diff prolongate l7: 6.83331e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 0.00000
+DEAL::Diff restrict add l2: 0.00000
+DEAL::Diff restrict l3: 9.67870e-16
+DEAL::Diff restrict add l3: 9.93014e-16
+DEAL::Diff restrict l4: 2.38116e-15
+DEAL::Diff restrict add l4: 2.48253e-15
+DEAL::Diff restrict l5: 2.18970e-15
+DEAL::Diff restrict add l5: 2.55110e-15
+DEAL::Diff restrict l6: 2.51705e-15
+DEAL::Diff restrict add l6: 3.00376e-15
+DEAL::Diff restrict l7: 3.57390e-15
+DEAL::Diff restrict add l7: 3.91580e-15
+DEAL::
+DEAL::FE: FESystem<2>[FE_Q<2>(3)^2]
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 1.19375e-15
+DEAL::Diff prolongate l2: 2.65120e-15
+DEAL::Diff prolongate l3: 4.51475e-15
+DEAL::Diff prolongate l4: 5.36184e-15
+DEAL::Diff prolongate l5: 4.26321e-15
+DEAL::Diff restrict l1: 1.93574e-15
+DEAL::Diff restrict add l1: 2.03507e-15
+DEAL::Diff restrict l2: 5.61733e-15
+DEAL::Diff restrict add l2: 6.25283e-15
+DEAL::Diff restrict l3: 8.89530e-15
+DEAL::Diff restrict add l3: 9.36017e-15
+DEAL::Diff restrict l4: 1.09472e-14
+DEAL::Diff restrict add l4: 1.09665e-14
+DEAL::Diff restrict l5: 8.06786e-15
+DEAL::Diff restrict add l5: 8.16750e-15
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 1.04513e-15
+DEAL::Diff prolongate l2: 2.59807e-15
+DEAL::Diff prolongate l3: 5.95414e-15
+DEAL::Diff prolongate l4: 6.00254e-15
+DEAL::Diff prolongate l5: 8.39305e-15
+DEAL::Diff prolongate l6: 8.37666e-15
+DEAL::Diff restrict l1: 2.51215e-15
+DEAL::Diff restrict add l1: 3.20237e-15
+DEAL::Diff restrict l2: 6.21923e-15
+DEAL::Diff restrict add l2: 6.46985e-15
+DEAL::Diff restrict l3: 1.30151e-14
+DEAL::Diff restrict add l3: 1.42247e-14
+DEAL::Diff restrict l4: 1.26215e-14
+DEAL::Diff restrict add l4: 1.28133e-14
+DEAL::Diff restrict l5: 1.56220e-14
+DEAL::Diff restrict add l5: 1.64807e-14
+DEAL::Diff restrict l6: 1.56927e-14
+DEAL::Diff restrict add l6: 1.66947e-14
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(1)^2]
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 3.14018e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 5.55112e-17
+DEAL::Diff prolongate l3: 4.45173e-16
+DEAL::Diff prolongate l4: 5.76095e-16
+DEAL::Diff prolongate l5: 8.29336e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 8.88178e-16
+DEAL::Diff restrict add l2: 8.88178e-16
+DEAL::Diff restrict l3: 2.02292e-15
+DEAL::Diff restrict add l3: 2.22045e-15
+DEAL::Diff restrict l4: 3.95027e-15
+DEAL::Diff restrict add l4: 4.19541e-15
+DEAL::Diff restrict l5: 4.67350e-15
+DEAL::Diff restrict add l5: 5.25453e-15
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(3)^2]
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 7.45167e-15
+DEAL::Diff prolongate l2: 8.99804e-15
+DEAL::Diff restrict l1: 2.31609e-14
+DEAL::Diff restrict add l1: 2.25394e-14
+DEAL::Diff restrict l2: 3.06553e-14
+DEAL::Diff restrict add l2: 3.12389e-14
+DEAL::
+DEAL::FE: FESystem<2>[FE_Q<2>(2)^2]
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 6.86910e-08
+DEAL::Diff prolongate l2: 1.77133e-07
+DEAL::Diff prolongate l3: 3.21812e-07
+DEAL::Diff prolongate l4: 4.07741e-07
+DEAL::Diff prolongate l5: 3.15483e-07
+DEAL::Diff restrict l1: 8.43965e-08
+DEAL::Diff restrict add l1: 3.78172e-07
+DEAL::Diff restrict l2: 4.04207e-07
+DEAL::Diff restrict add l2: 5.76620e-07
+DEAL::Diff restrict l3: 7.63684e-07
+DEAL::Diff restrict add l3: 9.19822e-07
+DEAL::Diff restrict l4: 9.23719e-07
+DEAL::Diff restrict add l4: 1.08789e-06
+DEAL::Diff restrict l5: 7.03670e-07
+DEAL::Diff restrict add l5: 9.16036e-07
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 7.48774e-08
+DEAL::Diff prolongate l2: 1.80284e-07
+DEAL::Diff prolongate l3: 4.12573e-07
+DEAL::Diff prolongate l4: 4.89806e-07
+DEAL::Diff prolongate l5: 7.08827e-07
+DEAL::Diff prolongate l6: 6.86261e-07
+DEAL::Diff restrict l1: 4.86098e-08
+DEAL::Diff restrict add l1: 4.86098e-08
+DEAL::Diff restrict l2: 4.41927e-07
+DEAL::Diff restrict add l2: 4.56242e-07
+DEAL::Diff restrict l3: 8.35079e-07
+DEAL::Diff restrict add l3: 1.19002e-06
+DEAL::Diff restrict l4: 1.03492e-06
+DEAL::Diff restrict add l4: 1.30417e-06
+DEAL::Diff restrict l5: 1.26083e-06
+DEAL::Diff restrict add l5: 1.66426e-06
+DEAL::Diff restrict l6: 1.45183e-06
+DEAL::Diff restrict add l6: 1.82397e-06
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(2)^2]
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 7.18146e-08
+DEAL::Diff prolongate l2: 2.81848e-07
+DEAL::Diff restrict l1: 1.78137e-07
+DEAL::Diff restrict add l1: 1.78137e-07
+DEAL::Diff restrict l2: 5.02891e-07
+DEAL::Diff restrict add l2: 5.02891e-07
+DEAL::
--- /dev/null
+
+DEAL::FE: FESystem<2>[FE_Q<2>(1)^2]
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 9.61481e-17
+DEAL::Diff prolongate l4: 2.54384e-16
+DEAL::Diff prolongate l5: 2.97645e-16
+DEAL::Diff prolongate l6: 3.06884e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 1.08779e-15
+DEAL::Diff restrict add l3: 1.08779e-15
+DEAL::Diff restrict l4: 1.02958e-15
+DEAL::Diff restrict add l4: 9.42055e-16
+DEAL::Diff restrict l5: 1.62032e-15
+DEAL::Diff restrict add l5: 1.89715e-15
+DEAL::Diff restrict l6: 1.36877e-15
+DEAL::Diff restrict add l6: 1.58572e-15
+DEAL::
+DEAL::no. cells: 868
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff prolongate l3: 1.24127e-16
+DEAL::Diff prolongate l4: 2.93737e-16
+DEAL::Diff prolongate l5: 3.78536e-16
+DEAL::Diff prolongate l6: 4.20991e-16
+DEAL::Diff prolongate l7: 7.17496e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 4.44089e-16
+DEAL::Diff restrict l3: 1.29948e-15
+DEAL::Diff restrict add l3: 1.53837e-15
+DEAL::Diff restrict l4: 2.39149e-15
+DEAL::Diff restrict add l4: 2.73755e-15
+DEAL::Diff restrict l5: 2.31289e-15
+DEAL::Diff restrict add l5: 2.52194e-15
+DEAL::Diff restrict l6: 2.37663e-15
+DEAL::Diff restrict add l6: 2.86084e-15
+DEAL::Diff restrict l7: 3.38936e-15
+DEAL::Diff restrict add l7: 3.79430e-15
+DEAL::
+DEAL::FE: FESystem<2>[FE_Q<2>(3)^2]
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 1.24251e-15
+DEAL::Diff prolongate l2: 2.69354e-15
+DEAL::Diff prolongate l3: 4.71393e-15
+DEAL::Diff prolongate l4: 5.25000e-15
+DEAL::Diff prolongate l5: 4.24784e-15
+DEAL::Diff restrict l1: 3.10862e-15
+DEAL::Diff restrict add l1: 3.29345e-15
+DEAL::Diff restrict l2: 4.53980e-15
+DEAL::Diff restrict add l2: 5.00955e-15
+DEAL::Diff restrict l3: 8.75679e-15
+DEAL::Diff restrict add l3: 8.96466e-15
+DEAL::Diff restrict l4: 9.88904e-15
+DEAL::Diff restrict add l4: 9.94006e-15
+DEAL::Diff restrict l5: 8.14781e-15
+DEAL::Diff restrict add l5: 8.59115e-15
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 1.23403e-15
+DEAL::Diff prolongate l2: 2.59030e-15
+DEAL::Diff prolongate l3: 6.19756e-15
+DEAL::Diff prolongate l4: 5.86430e-15
+DEAL::Diff prolongate l5: 8.02510e-15
+DEAL::Diff prolongate l6: 7.89235e-15
+DEAL::Diff restrict l1: 2.04715e-15
+DEAL::Diff restrict add l1: 2.73755e-15
+DEAL::Diff restrict l2: 6.29801e-15
+DEAL::Diff restrict add l2: 6.23704e-15
+DEAL::Diff restrict l3: 1.33072e-14
+DEAL::Diff restrict add l3: 1.33171e-14
+DEAL::Diff restrict l4: 1.26068e-14
+DEAL::Diff restrict add l4: 1.29130e-14
+DEAL::Diff restrict l5: 1.74281e-14
+DEAL::Diff restrict add l5: 1.78908e-14
+DEAL::Diff restrict l6: 1.64922e-14
+DEAL::Diff restrict add l6: 1.73113e-14
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(1)^2]
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 0.00000
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 3.14018e-16
+DEAL::Diff restrict add l2: 0.00000
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 0.00000
+DEAL::Diff prolongate l2: 1.14439e-16
+DEAL::Diff prolongate l3: 4.48405e-16
+DEAL::Diff prolongate l4: 6.43898e-16
+DEAL::Diff prolongate l5: 7.94566e-16
+DEAL::Diff restrict l1: 0.00000
+DEAL::Diff restrict add l1: 0.00000
+DEAL::Diff restrict l2: 4.44089e-16
+DEAL::Diff restrict add l2: 8.88178e-16
+DEAL::Diff restrict l3: 2.38116e-15
+DEAL::Diff restrict add l3: 2.73755e-15
+DEAL::Diff restrict l4: 4.36248e-15
+DEAL::Diff restrict add l4: 4.39626e-15
+DEAL::Diff restrict l5: 4.33982e-15
+DEAL::Diff restrict add l5: 4.80356e-15
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(3)^2]
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 6.10586e-15
+DEAL::Diff prolongate l2: 9.12753e-15
+DEAL::Diff restrict l1: 2.16468e-14
+DEAL::Diff restrict add l1: 2.17558e-14
+DEAL::Diff restrict l2: 3.10285e-14
+DEAL::Diff restrict add l2: 3.09280e-14
+DEAL::
+DEAL::FE: FESystem<2>[FE_Q<2>(2)^2]
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 3.75428e-08
+DEAL::Diff prolongate l2: 1.73474e-07
+DEAL::Diff prolongate l3: 4.06743e-07
+DEAL::Diff prolongate l4: 4.56267e-07
+DEAL::Diff prolongate l5: 3.02844e-07
+DEAL::Diff restrict l1: 7.83696e-08
+DEAL::Diff restrict add l1: 7.83696e-08
+DEAL::Diff restrict l2: 4.84892e-07
+DEAL::Diff restrict add l2: 4.84892e-07
+DEAL::Diff restrict l3: 6.33157e-07
+DEAL::Diff restrict add l3: 8.51716e-07
+DEAL::Diff restrict l4: 7.38227e-07
+DEAL::Diff restrict add l4: 1.08434e-06
+DEAL::Diff restrict l5: 7.53959e-07
+DEAL::Diff restrict add l5: 9.85545e-07
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 3.80021e-08
+DEAL::Diff prolongate l2: 2.05445e-07
+DEAL::Diff prolongate l3: 4.23083e-07
+DEAL::Diff prolongate l4: 4.60938e-07
+DEAL::Diff prolongate l5: 6.34151e-07
+DEAL::Diff prolongate l6: 6.66574e-07
+DEAL::Diff restrict l1: 1.51135e-07
+DEAL::Diff restrict add l1: 1.51135e-07
+DEAL::Diff restrict l2: 4.39691e-07
+DEAL::Diff restrict add l2: 4.99465e-07
+DEAL::Diff restrict l3: 9.43038e-07
+DEAL::Diff restrict add l3: 1.07123e-06
+DEAL::Diff restrict l4: 1.06518e-06
+DEAL::Diff restrict add l4: 1.22748e-06
+DEAL::Diff restrict l5: 1.29055e-06
+DEAL::Diff restrict add l5: 1.51964e-06
+DEAL::Diff restrict l6: 1.36762e-06
+DEAL::Diff restrict add l6: 1.82467e-06
+DEAL::
+DEAL::FE: FESystem<3>[FE_Q<3>(2)^2]
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 6.46984e-08
+DEAL::Diff prolongate l2: 2.68654e-07
+DEAL::Diff restrict l1: 3.14590e-07
+DEAL::Diff restrict add l1: 3.14590e-07
+DEAL::Diff restrict l2: 9.87299e-07
+DEAL::Diff restrict add l2: 1.06546e-06
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree by comparison with MGTransferPrebuilt on a
+// series of meshes with adaptive meshes for FE_DGQLegendre (except for the
+// different element the same test as transfer_matrix_free_05)
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_dgq.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_DGQLegendre<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+ unsigned int sizes[] = {1, 2, 3};
+ for (unsigned int cycle = 0; cycle < sizeof(sizes) / sizeof(unsigned int);
+ ++cycle)
+ {
+ unsigned int n_refinements = 0;
+ unsigned int n_subdiv = sizes[cycle];
+ if (n_subdiv > 1)
+ while (n_subdiv % 2 == 0)
+ {
+ n_refinements += 1;
+ n_subdiv /= 2;
+ }
+ n_refinements += 3 - dim;
+ if (fe_degree < 3)
+ n_refinements += 1;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, n_subdiv);
+ tr.refine_global(n_refinements);
+
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() < 0.5)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.3 &&
+ cell->center().norm() < 0.4)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->center().norm() > 0.33 &&
+ cell->center().norm() < 0.37)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref;
+ transfer_ref.build(mgdof);
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer;
+ transfer.build(mgdof);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+ check<2, double>(3);
+ check<3, double>(1);
+ check<3, double>(3);
+ check<2, float>(2);
+ check<3, float>(2);
+}
--- /dev/null
+
+DEAL::FE: FE_DGQLegendre<2>(1)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 1.17961e-15
+DEAL::Diff prolongate l2: 2.31497e-15
+DEAL::Diff prolongate l3: 3.30061e-15
+DEAL::Diff prolongate l4: 3.68951e-15
+DEAL::Diff prolongate l5: 3.01737e-15
+DEAL::Diff restrict l1: 1.37775e-15
+DEAL::Diff restrict add l1: 1.27555e-15
+DEAL::Diff restrict l2: 2.56074e-15
+DEAL::Diff restrict add l2: 2.68298e-15
+DEAL::Diff restrict l3: 4.18622e-15
+DEAL::Diff restrict add l3: 4.14368e-15
+DEAL::Diff restrict l4: 4.18475e-15
+DEAL::Diff restrict add l4: 4.36531e-15
+DEAL::Diff restrict l5: 2.85019e-15
+DEAL::Diff restrict add l5: 2.95411e-15
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 9.09472e-16
+DEAL::Diff prolongate l2: 2.47191e-15
+DEAL::Diff prolongate l3: 3.78045e-15
+DEAL::Diff prolongate l4: 4.46449e-15
+DEAL::Diff prolongate l5: 5.14809e-15
+DEAL::Diff prolongate l6: 4.75228e-15
+DEAL::Diff restrict l1: 1.33689e-15
+DEAL::Diff restrict add l1: 1.27555e-15
+DEAL::Diff restrict l2: 2.68140e-15
+DEAL::Diff restrict add l2: 2.90573e-15
+DEAL::Diff restrict l3: 5.86300e-15
+DEAL::Diff restrict add l3: 6.12437e-15
+DEAL::Diff restrict l4: 4.88696e-15
+DEAL::Diff restrict add l4: 5.12750e-15
+DEAL::Diff restrict l5: 6.62644e-15
+DEAL::Diff restrict add l5: 7.00145e-15
+DEAL::Diff restrict l6: 6.91582e-15
+DEAL::Diff restrict add l6: 6.98735e-15
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 2.75105e-15
+DEAL::Diff prolongate l2: 6.10804e-15
+DEAL::Diff prolongate l3: 4.90801e-15
+DEAL::Diff prolongate l4: 6.30864e-15
+DEAL::Diff prolongate l5: 7.18050e-15
+DEAL::Diff restrict l1: 3.59935e-15
+DEAL::Diff restrict add l1: 3.78128e-15
+DEAL::Diff restrict l2: 8.14600e-15
+DEAL::Diff restrict add l2: 8.34663e-15
+DEAL::Diff restrict l3: 7.27681e-15
+DEAL::Diff restrict add l3: 7.55849e-15
+DEAL::Diff restrict l4: 8.39312e-15
+DEAL::Diff restrict add l4: 8.53862e-15
+DEAL::Diff restrict l5: 9.82938e-15
+DEAL::Diff restrict add l5: 1.04862e-14
+DEAL::
+DEAL::FE: FE_DGQLegendre<2>(3)
+DEAL::no. cells: 34
+DEAL::Diff prolongate l1: 3.00914e-15
+DEAL::Diff prolongate l2: 6.62459e-15
+DEAL::Diff prolongate l3: 6.49387e-15
+DEAL::Diff prolongate l4: 3.09889e-15
+DEAL::Diff restrict l1: 3.64043e-15
+DEAL::Diff restrict add l1: 3.56656e-15
+DEAL::Diff restrict l2: 6.57463e-15
+DEAL::Diff restrict add l2: 6.49931e-15
+DEAL::Diff restrict l3: 6.23681e-15
+DEAL::Diff restrict add l3: 6.12739e-15
+DEAL::Diff restrict l4: 4.53656e-15
+DEAL::Diff restrict add l4: 4.58698e-15
+DEAL::
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 2.63188e-15
+DEAL::Diff prolongate l2: 5.48505e-15
+DEAL::Diff prolongate l3: 8.92854e-15
+DEAL::Diff prolongate l4: 9.11112e-15
+DEAL::Diff prolongate l5: 6.94348e-15
+DEAL::Diff restrict l1: 3.97198e-15
+DEAL::Diff restrict add l1: 4.05953e-15
+DEAL::Diff restrict l2: 6.33031e-15
+DEAL::Diff restrict add l2: 6.60559e-15
+DEAL::Diff restrict l3: 9.09159e-15
+DEAL::Diff restrict add l3: 9.07128e-15
+DEAL::Diff restrict l4: 9.35191e-15
+DEAL::Diff restrict add l4: 9.59813e-15
+DEAL::Diff restrict l5: 7.73956e-15
+DEAL::Diff restrict add l5: 7.73261e-15
+DEAL::
+DEAL::no. cells: 141
+DEAL::Diff prolongate l1: 8.50986e-15
+DEAL::Diff prolongate l2: 9.70102e-15
+DEAL::Diff prolongate l3: 1.17234e-14
+DEAL::Diff prolongate l4: 1.10643e-14
+DEAL::Diff restrict l1: 9.82721e-15
+DEAL::Diff restrict add l1: 9.94130e-15
+DEAL::Diff restrict l2: 8.95066e-15
+DEAL::Diff restrict add l2: 8.93712e-15
+DEAL::Diff restrict l3: 1.21155e-14
+DEAL::Diff restrict add l3: 1.22089e-14
+DEAL::Diff restrict l4: 1.12588e-14
+DEAL::Diff restrict add l4: 1.14013e-14
+DEAL::
+DEAL::FE: FE_DGQLegendre<3>(1)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 2.50686e-15
+DEAL::Diff prolongate l2: 2.81673e-15
+DEAL::Diff restrict l1: 4.67086e-15
+DEAL::Diff restrict add l1: 4.74158e-15
+DEAL::Diff restrict l2: 3.52878e-15
+DEAL::Diff restrict add l2: 3.40026e-15
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 1.51799e-15
+DEAL::Diff prolongate l2: 7.46319e-15
+DEAL::Diff prolongate l3: 1.27085e-14
+DEAL::Diff prolongate l4: 1.72742e-14
+DEAL::Diff prolongate l5: 1.58362e-14
+DEAL::Diff restrict l1: 4.27400e-15
+DEAL::Diff restrict add l1: 4.35683e-15
+DEAL::Diff restrict l2: 1.31474e-14
+DEAL::Diff restrict add l2: 1.36291e-14
+DEAL::Diff restrict l3: 1.97274e-14
+DEAL::Diff restrict add l3: 1.98513e-14
+DEAL::Diff restrict l4: 2.76798e-14
+DEAL::Diff restrict add l4: 2.79761e-14
+DEAL::Diff restrict l5: 2.40156e-14
+DEAL::Diff restrict add l5: 2.45131e-14
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 1.32337e-14
+DEAL::Diff prolongate l2: 1.43823e-14
+DEAL::Diff prolongate l3: 2.25930e-14
+DEAL::Diff prolongate l4: 2.95496e-14
+DEAL::Diff restrict l1: 2.40047e-14
+DEAL::Diff restrict add l1: 2.40260e-14
+DEAL::Diff restrict l2: 2.30032e-14
+DEAL::Diff restrict add l2: 2.28488e-14
+DEAL::Diff restrict l3: 3.79362e-14
+DEAL::Diff restrict add l3: 3.79409e-14
+DEAL::Diff restrict l4: 4.92435e-14
+DEAL::Diff restrict add l4: 4.94843e-14
+DEAL::
+DEAL::FE: FE_DGQLegendre<3>(3)
+DEAL::no. cells: 1
+DEAL::
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 1.22857e-14
+DEAL::Diff prolongate l2: 1.18723e-14
+DEAL::Diff restrict l1: 1.20501e-14
+DEAL::Diff restrict add l1: 1.20596e-14
+DEAL::Diff restrict l2: 9.27744e-15
+DEAL::Diff restrict add l2: 9.37465e-15
+DEAL::
+DEAL::no. cells: 223
+DEAL::Diff prolongate l1: 2.80933e-14
+DEAL::Diff prolongate l2: 4.15818e-14
+DEAL::Diff prolongate l3: 2.64041e-14
+DEAL::Diff restrict l1: 3.10527e-14
+DEAL::Diff restrict add l1: 3.08610e-14
+DEAL::Diff restrict l2: 4.48476e-14
+DEAL::Diff restrict add l2: 4.52462e-14
+DEAL::Diff restrict l3: 2.91624e-14
+DEAL::Diff restrict add l3: 2.91101e-14
+DEAL::
+DEAL::FE: FE_DGQLegendre<2>(2)
+DEAL::no. cells: 88
+DEAL::Diff prolongate l1: 1.50767e-07
+DEAL::Diff prolongate l2: 3.40269e-07
+DEAL::Diff prolongate l3: 5.31799e-07
+DEAL::Diff prolongate l4: 5.68538e-07
+DEAL::Diff prolongate l5: 5.27410e-07
+DEAL::Diff restrict l1: 1.00439e-07
+DEAL::Diff restrict add l1: 1.75118e-07
+DEAL::Diff restrict l2: 4.36168e-07
+DEAL::Diff restrict add l2: 4.67837e-07
+DEAL::Diff restrict l3: 5.13719e-07
+DEAL::Diff restrict add l3: 6.14205e-07
+DEAL::Diff restrict l4: 5.48251e-07
+DEAL::Diff restrict add l4: 6.62665e-07
+DEAL::Diff restrict l5: 3.55987e-07
+DEAL::Diff restrict add l5: 5.20885e-07
+DEAL::
+DEAL::no. cells: 250
+DEAL::Diff prolongate l1: 1.40461e-07
+DEAL::Diff prolongate l2: 4.13020e-07
+DEAL::Diff prolongate l3: 7.35401e-07
+DEAL::Diff prolongate l4: 8.37297e-07
+DEAL::Diff prolongate l5: 8.92044e-07
+DEAL::Diff prolongate l6: 8.41612e-07
+DEAL::Diff restrict l1: 1.45801e-07
+DEAL::Diff restrict add l1: 1.62850e-07
+DEAL::Diff restrict l2: 3.58578e-07
+DEAL::Diff restrict add l2: 4.84573e-07
+DEAL::Diff restrict l3: 7.21057e-07
+DEAL::Diff restrict add l3: 9.44494e-07
+DEAL::Diff restrict l4: 6.47760e-07
+DEAL::Diff restrict add l4: 8.41653e-07
+DEAL::Diff restrict l5: 8.92925e-07
+DEAL::Diff restrict add l5: 1.05666e-06
+DEAL::Diff restrict l6: 8.33874e-07
+DEAL::Diff restrict add l6: 1.00952e-06
+DEAL::
+DEAL::no. cells: 510
+DEAL::Diff prolongate l1: 5.95223e-07
+DEAL::Diff prolongate l2: 1.08340e-06
+DEAL::Diff prolongate l3: 8.76501e-07
+DEAL::Diff prolongate l4: 1.17615e-06
+DEAL::Diff prolongate l5: 1.31783e-06
+DEAL::Diff restrict l1: 4.69618e-07
+DEAL::Diff restrict add l1: 6.08473e-07
+DEAL::Diff restrict l2: 1.03701e-06
+DEAL::Diff restrict add l2: 1.26830e-06
+DEAL::Diff restrict l3: 9.65744e-07
+DEAL::Diff restrict add l3: 1.14572e-06
+DEAL::Diff restrict l4: 1.06047e-06
+DEAL::Diff restrict add l4: 1.29914e-06
+DEAL::Diff restrict l5: 1.24330e-06
+DEAL::Diff restrict add l5: 1.65485e-06
+DEAL::
+DEAL::FE: FE_DGQLegendre<3>(2)
+DEAL::no. cells: 15
+DEAL::Diff prolongate l1: 5.47934e-07
+DEAL::Diff prolongate l2: 4.76393e-07
+DEAL::Diff restrict l1: 6.08284e-07
+DEAL::Diff restrict add l1: 7.43498e-07
+DEAL::Diff restrict l2: 3.41055e-07
+DEAL::Diff restrict add l2: 4.04700e-07
+DEAL::
+DEAL::no. cells: 694
+DEAL::Diff prolongate l1: 4.96241e-07
+DEAL::Diff prolongate l2: 1.65120e-06
+DEAL::Diff prolongate l3: 2.51597e-06
+DEAL::Diff prolongate l4: 3.45087e-06
+DEAL::Diff prolongate l5: 3.23786e-06
+DEAL::Diff restrict l1: 4.77286e-07
+DEAL::Diff restrict add l1: 5.02006e-07
+DEAL::Diff restrict l2: 1.37508e-06
+DEAL::Diff restrict add l2: 1.48051e-06
+DEAL::Diff restrict l3: 2.58627e-06
+DEAL::Diff restrict add l3: 2.84981e-06
+DEAL::Diff restrict l4: 3.19463e-06
+DEAL::Diff restrict add l4: 3.50298e-06
+DEAL::Diff restrict l5: 3.15360e-06
+DEAL::Diff restrict add l5: 3.41047e-06
+DEAL::
+DEAL::no. cells: 1791
+DEAL::Diff prolongate l1: 3.02960e-06
+DEAL::Diff prolongate l2: 3.11031e-06
+DEAL::Diff prolongate l3: 4.96800e-06
+DEAL::Diff prolongate l4: 6.37747e-06
+DEAL::Diff restrict l1: 2.79504e-06
+DEAL::Diff restrict add l1: 3.06625e-06
+DEAL::Diff restrict l2: 2.58243e-06
+DEAL::Diff restrict add l2: 2.91690e-06
+DEAL::Diff restrict l3: 4.58185e-06
+DEAL::Diff restrict add l3: 5.03720e-06
+DEAL::Diff restrict l4: 5.87275e-06
+DEAL::Diff restrict add l4: 6.48746e-06
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree for high polynomial degrees beyond 10 by
+// checking a linear function that gets prolongated between the mesh
+// levels. Since the function is linear, it should be exactly represented on
+// the finest level. Then also look into the result of restriction
+
+#include <deal.II/base/function_lib.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const FiniteElement<dim> &fe)
+{
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+
+ Triangulation<dim> tr(Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(tr);
+ tr.refine_global(2);
+
+ Triangulation<dim> trcoarse(
+ Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(trcoarse);
+ DoFHandler<dim> dofcoarse(trcoarse);
+ dofcoarse.distribute_dofs(fe);
+ Tensor<1, dim> exponents_monomial;
+ for (unsigned int d = 0; d < dim; ++d)
+ exponents_monomial[d] = 1;
+ LinearAlgebra::distributed::Vector<double> vrefcoarse;
+ vrefcoarse.reinit(dofcoarse.n_dofs());
+ VectorTools::interpolate(dofcoarse,
+ Functions::Monomial<dim>(exponents_monomial),
+ vrefcoarse);
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer;
+ transfer.build(mgdof);
+
+ LinearAlgebra::distributed::Vector<double> vrefdouble;
+ LinearAlgebra::distributed::Vector<Number> vref;
+ AssertDimension(mgdof.n_dofs(tr.n_global_levels() - 1), mgdof.n_dofs());
+ vrefdouble.reinit(mgdof.n_dofs());
+ VectorTools::interpolate(mgdof,
+ Functions::Monomial<dim>(exponents_monomial),
+ vrefdouble);
+
+ vref.reinit(mgdof.n_dofs());
+ vref = vrefdouble;
+ std::vector<LinearAlgebra::distributed::Vector<Number>> vec(
+ tr.n_global_levels());
+ for (unsigned int level = 0; level < tr.n_global_levels(); ++level)
+ vec[level].reinit(mgdof.n_dofs(level));
+ vec.back() = vref;
+
+ // prolongate monomial from coarse to fine, should be exact for monomial
+ vec[0] = vrefcoarse;
+ for (unsigned int level = 1; level < tr.n_global_levels(); ++level)
+ transfer.prolongate(level, vec[level], vec[level - 1]);
+ vec.back() -= vref;
+ const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
+ deallog << "Error after prolongation: "
+ << filter_out_small_numbers(vec.back().linfty_norm(), tolerance)
+ << std::endl;
+
+ // unfortunately, no completely trivial expression of what should happen
+ // during restriction
+ vec.back() = vref;
+ for (unsigned int level = tr.n_global_levels() - 1; level > 0; --level)
+ transfer.restrict_and_add(level, vec[level - 1], vec[level]);
+ deallog << "Norm after restriction: " << vec[0].l2_norm() << std::endl;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ initlog();
+
+ check<2, double>(FE_DGQ<2>(3));
+ check<2, double>(FE_DGQ<2>(8));
+ check<2, double>(FE_DGQ<2>(16));
+ check<2, double>(FE_Q<2>(16));
+ check<3, double>(FE_DGQ<3>(11));
+ check<2, float>(FE_DGQ<2>(3));
+ check<2, float>(FE_DGQ<2>(8));
+ check<2, float>(FE_DGQ<2>(16));
+ check<2, float>(FE_Q<2>(16));
+ check<3, float>(FE_DGQ<3>(11));
+}
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 34.1210
+DEAL::FE: FE_DGQ<2>(8)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 71.6678
+DEAL::FE: FE_DGQ<2>(16)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 151.607
+DEAL::FE: FE_Q<2>(16)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 133.734
+DEAL::FE: FE_DGQ<3>(11)
+DEAL::no. cells: 64
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 774.120
+DEAL::FE: FE_DGQ<2>(3)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 34.1210
+DEAL::FE: FE_DGQ<2>(8)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 71.6678
+DEAL::FE: FE_DGQ<2>(16)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 151.607
+DEAL::FE: FE_Q<2>(16)
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 133.734
+DEAL::FE: FE_DGQ<3>(11)
+DEAL::no. cells: 64
+DEAL::Error after prolongation: 0
+DEAL::Norm after restriction: 774.120
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check that MGTransferMatrixFree::clear works correctly by comparing a
+// cleared transfer system with a freshly constructed one
+#include <deal.II/base/function_lib.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const FiniteElement<dim> &fe)
+{
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ MGTransferMF<dim, Number> transfer;
+ Triangulation<dim> tr(Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(tr);
+ tr.refine_global(6 - dim);
+
+ // run a few different sizes...
+ for (unsigned int c = 0; c < 4; ++c)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2))
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ Tensor<1, dim> exponents_monomial;
+ for (unsigned int d = 0; d < dim; ++d)
+ exponents_monomial[d] = 1;
+ LinearAlgebra::distributed::Vector<double> vref;
+ vref.reinit(mgdof.n_dofs());
+ VectorTools::interpolate(mgdof,
+ Functions::Monomial<dim>(exponents_monomial),
+ vref);
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ const std::set<types::boundary_id> dirichlet_boundary = {0};
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof,
+ dirichlet_boundary);
+
+ // build matrix-free transfer
+ transfer.clear();
+ transfer.initialize_constraints(mg_constrained_dofs);
+ transfer.build(mgdof);
+ MGTransferMF<dim, Number> transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+ MGLevelObject<LinearAlgebra::distributed::Vector<Number>> vectors(
+ 0, tr.n_global_levels() - 1);
+ transfer_ref.copy_to_mg(mgdof, vectors, vref);
+ for (unsigned int level = vectors.max_level(); level > 0; --level)
+ {
+ LinearAlgebra::distributed::Vector<Number> vec2(vectors[level - 1]);
+ transfer_ref.restrict_and_add(level,
+ vectors[level - 1],
+ vectors[level]);
+ transfer.restrict_and_add(level, vec2, vectors[level]);
+ vec2 -= vectors[level - 1];
+ deallog << "Error in restriction: " << (double)vec2.linfty_norm()
+ << std::endl;
+ }
+
+ for (unsigned int level = 1; level < vectors.max_level(); ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> vec2(vectors[level + 1]);
+ transfer_ref.prolongate(level + 1,
+ vectors[level + 1],
+ vectors[level]);
+ transfer.prolongate(level + 1, vec2, vectors[level]);
+ vec2 -= vectors[level + 1];
+ deallog << "Error in prolongation: " << (double)vec2.linfty_norm()
+ << std::endl;
+ }
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ initlog();
+
+ check<2, double>(FE_DGQ<2>(2));
+ check<2, double>(FE_Q<2>(2));
+ check<3, double>(FE_Q<3>(1));
+ check<2, float>(FE_Q<2>(2));
+}
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 757
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 2808
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6847
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 33776
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 - 2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check that MGTransferMatrixFree::build works correctly by comparing the
+// build on an already existing transfer system with a freshly constructed one
+#include <deal.II/base/function_lib.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const FiniteElement<dim> &fe)
+{
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ Triangulation<dim> tr(Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(tr);
+ tr.refine_global(6 - dim);
+
+ // run a few different sizes...
+ for (unsigned int c = 0; c < 4; ++c)
+ {
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if ((cell->center().norm() < 0.5 &&
+ (cell->level() < 5 || cell->center().norm() > 0.45)) ||
+ (dim == 2 && cell->center().norm() > 1.2))
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ Tensor<1, dim> exponents_monomial;
+ for (unsigned int d = 0; d < dim; ++d)
+ exponents_monomial[d] = 1;
+ LinearAlgebra::distributed::Vector<double> vref;
+ vref.reinit(mgdof.n_dofs());
+ VectorTools::interpolate(mgdof,
+ Functions::Monomial<dim>(exponents_monomial),
+ vref);
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ const std::set<types::boundary_id> dirichlet_boundary = {0};
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof,
+ dirichlet_boundary);
+
+ // build matrix-free transfer
+ transfer.build(mgdof);
+ MGTransferMF<dim, Number> transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+ MGLevelObject<LinearAlgebra::distributed::Vector<Number>> vectors(
+ 0, tr.n_global_levels() - 1);
+ transfer_ref.copy_to_mg(mgdof, vectors, vref);
+ for (unsigned int level = vectors.max_level(); level > 0; --level)
+ {
+ LinearAlgebra::distributed::Vector<Number> vec2(vectors[level - 1]);
+ transfer_ref.restrict_and_add(level,
+ vectors[level - 1],
+ vectors[level]);
+ transfer.restrict_and_add(level, vec2, vectors[level]);
+ vec2 -= vectors[level - 1];
+ deallog << "Error in restriction: " << (double)vec2.linfty_norm()
+ << std::endl;
+ }
+
+ for (unsigned int level = 1; level < vectors.max_level(); ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> vec2(vectors[level + 1]);
+ transfer_ref.prolongate(level + 1,
+ vectors[level + 1],
+ vectors[level]);
+ transfer.prolongate(level + 1, vec2, vectors[level]);
+ vec2 -= vectors[level + 1];
+ deallog << "Error in prolongation: " << (double)vec2.linfty_norm()
+ << std::endl;
+ }
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ initlog();
+
+ check<2, double>(FE_DGQ<2>(2));
+ check<2, double>(FE_Q<2>(2));
+ check<3, double>(FE_Q<3>(1));
+ check<2, float>(FE_Q<2>(2));
+}
--- /dev/null
+
+DEAL::FE: FE_DGQ<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<3>(1)
+DEAL::no. cells: 757
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 2808
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6847
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 33776
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::FE: FE_Q<2>(2)
+DEAL::no. cells: 448
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 766
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 1924
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::no. cells: 6082
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in restriction: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
+DEAL::Error in prolongation: 0
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Check MGTransferMatrixFree and MGTransferPrebuilt for periodic boundary
+// conditions
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_tools.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const unsigned int fe_degree)
+{
+ FE_Q<dim> fe(fe_degree);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::hyper_cube(tr, -1, 1, true);
+ std::vector<
+ GridTools::PeriodicFacePair<typename Triangulation<dim>::cell_iterator>>
+ periodicity_vector;
+ GridTools::collect_periodic_faces(tr, 0, 1, 0, periodicity_vector);
+ GridTools::collect_periodic_faces(tr, 2, 3, 1, periodicity_vector);
+ tr.add_periodicity(periodicity_vector);
+ tr.refine_global(2);
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+
+ // build reference
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>> transfer_ref(
+ mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+ deallog << "Transfer matrices: " << std::endl;
+ transfer_ref.print_matrices(deallog.get_file_stream());
+ deallog << std::endl;
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer(mg_constrained_dofs);
+ transfer.build(mgdof);
+
+ // check prolongation for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.prolongate(level, v2, v1);
+ transfer_ref.prolongate(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff prolongate l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ if (v3.l2_norm() > 1e-12)
+ {
+ // On level 0, we expect the matrix-based constraints to be wrong
+ // because it cannot capture the periodicity connections with a
+ // single cell
+ v2_cpy.print(deallog.get_file_stream());
+ v3.print(deallog.get_file_stream());
+ }
+ }
+
+ // check restriction for all levels using random vector
+ for (unsigned int level = 1;
+ level < mgdof.get_triangulation().n_global_levels();
+ ++level)
+ {
+ LinearAlgebra::distributed::Vector<Number> v1, v2;
+ LinearAlgebra::distributed::Vector<double> v1_cpy, v2_cpy, v3;
+ v1.reinit(mgdof.locally_owned_mg_dofs(level), MPI_COMM_WORLD);
+ v2.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ v3.reinit(mgdof.locally_owned_mg_dofs(level - 1), MPI_COMM_WORLD);
+ for (unsigned int i = 0; i < v1.locally_owned_size(); ++i)
+ v1.local_element(i) = random_value<double>();
+ v1_cpy = v1;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict l" << level << ": " << v3.l2_norm()
+ << std::endl;
+
+ v2 = 1.;
+ v3 = 1.;
+ transfer.restrict_and_add(level, v2, v1);
+ transfer_ref.restrict_and_add(level, v3, v1_cpy);
+ v2_cpy = v2;
+ v3 -= v2_cpy;
+ deallog << "Diff restrict add l" << level << ": " << v3.l2_norm()
+ << std::endl;
+ }
+ deallog << std::endl;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2, double>(1);
+}
--- /dev/null
+
+DEAL::FE: FE_Q<2>(1)
+DEAL::no. cells: 16
+DEAL::Transfer matrices:
+Level 0
+(3,3) 0.250000
+(5,3) 0.500000
+(7,3) 0.500000
+(8,3) 1.00000
+
+Level 1
+(3,3) 0.250000
+(3,5) 0.250000
+(3,7) 0.250000
+(3,8) 0.250000
+(5,3) 0.500000
+(5,7) 0.500000
+(7,3) 0.500000
+(7,5) 0.500000
+(8,3) 1.00000
+(10,3) 0.250000
+(10,5) 0.250000
+(10,7) 0.250000
+(10,8) 0.250000
+(12,5) 0.500000
+(12,8) 0.500000
+(13,3) 0.500000
+(13,5) 0.500000
+(14,5) 1.00000
+(16,3) 0.250000
+(16,5) 0.250000
+(16,7) 0.250000
+(16,8) 0.250000
+(17,3) 0.500000
+(17,7) 0.500000
+(19,7) 0.500000
+(19,8) 0.500000
+(20,7) 1.00000
+(21,3) 0.250000
+(21,5) 0.250000
+(21,7) 0.250000
+(21,8) 0.250000
+(22,5) 0.500000
+(22,8) 0.500000
+(23,7) 0.500000
+(23,8) 0.500000
+(24,8) 1.00000
+
+DEAL::
+DEAL::Diff prolongate l1: 0.823013
+Process #0
+Local range: [0, 9), global size: 9
+Vector data:
+0.000e+00 0.000e+00 0.000e+00 7.984e-01 0.000e+00 7.984e-01 0.000e+00 7.984e-01 7.984e-01
+Process #0
+Local range: [0, 9), global size: 9
+Vector data:
+0.000e+00 0.000e+00 0.000e+00 -5.988e-01 0.000e+00 -3.992e-01 0.000e+00 -3.992e-01 0.000e+00
+DEAL::Diff prolongate l2: 0
+DEAL::Diff restrict l1: 0.555735
+DEAL::Diff restrict add l1: 0.555735
+DEAL::Diff restrict l2: 0
+DEAL::Diff restrict add l2: 0
+DEAL::
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 - 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Similar to transfer_matrix_free_08 but using a system of equations: high
+// polynomial degrees beyond 10 that are compared against a linear function
+// that gets prolongated between the mesh levels. Since the function is
+// linear, it should be exactly represented on the finest level. Then also
+// look into the result of restriction
+
+#include <deal.II/base/function_lib.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_system.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include <deal.II/numerics/vector_tools.h>
+
+#include "../tests.h"
+
+
+template <int dim, typename Number>
+void
+check(const FiniteElement<dim> &fe_scalar)
+{
+ FESystem<dim> fe(fe_scalar, dim);
+ deallog << "FE: " << fe.get_name() << std::endl;
+
+ // run a few different sizes...
+
+ Triangulation<dim> tr(Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(tr);
+ tr.refine_global(2);
+
+ Triangulation<dim> trcoarse(
+ Triangulation<dim>::limit_level_difference_at_vertices);
+ GridGenerator::hyper_cube(trcoarse);
+ DoFHandler<dim> dofcoarse(trcoarse);
+ dofcoarse.distribute_dofs(fe);
+ Tensor<1, dim> exponents_monomial;
+ for (unsigned int d = 0; d < dim; ++d)
+ exponents_monomial[d] = 1;
+ LinearAlgebra::distributed::Vector<double> vrefcoarse;
+ vrefcoarse.reinit(dofcoarse.n_dofs());
+ VectorTools::interpolate(dofcoarse,
+ Functions::Monomial<dim>(exponents_monomial, dim),
+ vrefcoarse);
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ // build matrix-free transfer
+ MGTransferMF<dim, Number> transfer;
+ transfer.build(mgdof);
+
+ LinearAlgebra::distributed::Vector<double> vrefdouble;
+ LinearAlgebra::distributed::Vector<Number> vref;
+ AssertDimension(mgdof.n_dofs(tr.n_global_levels() - 1), mgdof.n_dofs());
+ vrefdouble.reinit(mgdof.n_dofs());
+ VectorTools::interpolate(mgdof,
+ Functions::Monomial<dim>(exponents_monomial, dim),
+ vrefdouble);
+
+ vref.reinit(mgdof.n_dofs());
+ vref = vrefdouble;
+ std::vector<LinearAlgebra::distributed::Vector<Number>> vec(
+ tr.n_global_levels());
+ for (unsigned int level = 0; level < tr.n_global_levels(); ++level)
+ vec[level].reinit(mgdof.n_dofs(level));
+ vec.back() = vref;
+
+ // prolongate monomial from coarse to fine, should be exact for monomial
+ vec[0] = vrefcoarse;
+ for (unsigned int level = 1; level < tr.n_global_levels(); ++level)
+ transfer.prolongate(level, vec[level], vec[level - 1]);
+ vec.back() -= vref;
+ const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
+ deallog << "Error after prolongation: "
+ << filter_out_small_numbers(vec.back().linfty_norm(), tolerance)
+ << std::endl;
+
+ // unfortunately, no completely trivial expression of what should happen
+ // during restriction
+ vec.back() = vref;
+ for (unsigned int level = tr.n_global_levels() - 1; level > 0; --level)
+ transfer.restrict_and_add(level, vec[level - 1], vec[level]);
+ deallog << "Norm after restriction: " << vec[0].l2_norm() << std::endl;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ // no threading in this test...
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ initlog();
+
+ check<2, double>(FE_DGQ<2>(3));
+ check<2, double>(FE_DGQ<2>(8));
+ check<2, double>(FE_DGQ<2>(16));
+ check<2, double>(FE_Q<2>(16));
+ check<3, double>(FE_DGQ<3>(11));
+ check<2, float>(FE_DGQ<2>(3));
+ check<2, float>(FE_DGQ<2>(8));
+ check<2, float>(FE_DGQ<2>(16));
+ check<2, float>(FE_Q<2>(16));
+ check<3, float>(FE_DGQ<3>(11));
+}
--- /dev/null
+
+DEAL::FE: FESystem<2>[FE_DGQ<2>(3)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 48.2543
+DEAL::FE: FESystem<2>[FE_DGQ<2>(8)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 101.354
+DEAL::FE: FESystem<2>[FE_DGQ<2>(16)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 214.405
+DEAL::FE: FESystem<2>[FE_Q<2>(16)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 189.129
+DEAL::FE: FESystem<3>[FE_DGQ<3>(11)^3]
+DEAL::no. cells: 64
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 1340.82
+DEAL::FE: FESystem<2>[FE_DGQ<2>(3)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 48.2544
+DEAL::FE: FESystem<2>[FE_DGQ<2>(8)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 101.354
+DEAL::FE: FESystem<2>[FE_DGQ<2>(16)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 214.405
+DEAL::FE: FESystem<2>[FE_Q<2>(16)^2]
+DEAL::no. cells: 16
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 189.129
+DEAL::FE: FESystem<3>[FE_DGQ<3>(11)^3]
+DEAL::no. cells: 64
+DEAL::Error after prolongation: 0.00000
+DEAL::Norm after restriction: 1340.82
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 - 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// document a bug in MGLevelGlobalTransfer in 3d:
+
+/*
+An error occurred in line <341> of file
+<../source/multigrid/mg_level_global_transfer.cc> in function void
+dealii::MGLevelGlobalTransfer<dealii::LinearAlgebra::distributed::Vector<Number,
+dealii::MemorySpace::Host> >::fill_and_communicate_copy_indices(const
+dealii::DoFHandler<dh_dim, spacedim>&) [with int dim = 3; int spacedim = 3;
+Number = double] The violated condition was:
+ ::dealii::deal_II_exceptions::internals::compare_for_equality(this->copy_indices_level_mine.back().n_rows(),
+0) Additional information: Dimension 2 not equal to 0.
+*/
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+template <int dim>
+void
+check()
+{
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ typename parallel::distributed::Triangulation<dim>::Settings(
+ parallel::distributed::Triangulation<
+ dim>::mesh_reconstruction_after_repartitioning |
+ parallel::distributed::Triangulation<
+ dim>::construct_multigrid_hierarchy));
+
+ GridGenerator::hyper_cube(tr);
+
+ tr.refine_global(2);
+
+ // coarsen a few cells:
+ for (const auto &cell : tr.active_cell_iterators())
+ {
+ if (cell->is_artificial())
+ continue;
+ const std::string id = cell->parent()->id().to_string();
+ if (id == "0_1:0" || id == "0_1:1" || id == "0_1:2" || id == "0_1:3")
+ cell->set_coarsen_flag();
+ }
+
+ tr.execute_coarsening_and_refinement();
+
+ FE_Q<dim> fe(1);
+ DoFHandler<dim> mgdof(tr);
+ MGTransferMF<dim, double> transfer_mf;
+
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ deallog << "n_dofs = " << mgdof.n_dofs() << std::endl;
+
+ transfer_mf.build(mgdof);
+
+ tr.coarsen_global();
+ deallog << "OK" << std::endl;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ MPILogInitAll all;
+
+ check<2>();
+ check<3>();
+}
--- /dev/null
+
+DEAL:0::n_dofs = 9
+DEAL:0::OK
+DEAL:0::n_dofs = 84
+DEAL:0::OK
+
+DEAL:1::n_dofs = 9
+DEAL:1::OK
+DEAL:1::n_dofs = 84
+DEAL:1::OK
+
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2000 - 2020 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Deadlock reported by Kronbichler (github
+// https://github.com/dealii/dealii/issues/2051) with 3 processes
+// in MGTransferPrebuilt
+
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/multigrid/mg_transfer.h>
+#include <deal.II/multigrid/mg_transfer_global_coarsening.h>
+
+#include "../tests.h"
+
+
+template <int dim>
+void
+check()
+{
+ FE_Q<dim> fe(1);
+
+ parallel::distributed::Triangulation<dim> tr(
+ MPI_COMM_WORLD,
+ Triangulation<dim>::limit_level_difference_at_vertices,
+ parallel::distributed::Triangulation<dim>::construct_multigrid_hierarchy);
+ GridGenerator::subdivided_hyper_cube(tr, 3);
+ for (unsigned int cycle = 0; cycle < (dim == 2 ? 10 : 7); ++cycle)
+ {
+ // adaptive refinement into a circle
+ for (typename Triangulation<dim>::active_cell_iterator cell =
+ tr.begin_active();
+ cell != tr.end();
+ ++cell)
+ if (cell->is_locally_owned() && cell->vertex(0).norm() < 1e-10)
+ cell->set_refine_flag();
+ tr.execute_coarsening_and_refinement();
+
+ deallog << "no. cells: " << tr.n_global_active_cells() << " on "
+ << tr.n_global_levels() << " levels" << std::endl;
+
+ DoFHandler<dim> mgdof(tr);
+ mgdof.distribute_dofs(fe);
+ mgdof.distribute_mg_dofs();
+
+ MGConstrainedDoFs mg_constrained_dofs;
+ mg_constrained_dofs.initialize(mgdof);
+ mg_constrained_dofs.make_zero_boundary_constraints(mgdof, {0});
+
+ unsigned int myid = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
+
+ if (0)
+ {
+ std::ofstream grid_output(
+ ("out" + Utilities::to_string(myid) + ".svg").c_str());
+ GridOut grid_out;
+ GridOutFlags::Svg flags;
+ flags.label_level_subdomain_id = true;
+ flags.coloring = GridOutFlags::Svg::level_subdomain_id;
+ flags.convert_level_number_to_height = true;
+ grid_out.set_flags(flags);
+
+ grid_out.write_svg(tr, grid_output);
+ }
+#ifdef DEAL_II_WITH_TRILINOS
+ {
+ // MGTransferPrebuilt internally uses Trilinos matrices, so only
+ // create this if we have Trilinos
+ MGTransferPrebuilt<LinearAlgebra::distributed::Vector<double>>
+ transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+ }
+#endif
+ {
+ // but the matrix free transfer will work without Trilinos
+ MGTransferMF<dim, double> transfer_ref(mg_constrained_dofs);
+ transfer_ref.build(mgdof);
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+ mpi_initlog();
+
+ check<2>();
+}
--- /dev/null
+
+DEAL::no. cells: 12 on 2 levels
+DEAL::no. cells: 15 on 3 levels
+DEAL::no. cells: 18 on 4 levels
+DEAL::no. cells: 21 on 5 levels
+DEAL::no. cells: 24 on 6 levels
+DEAL::no. cells: 27 on 7 levels
+DEAL::no. cells: 30 on 8 levels
+DEAL::no. cells: 33 on 9 levels
+DEAL::no. cells: 36 on 10 levels
+DEAL::no. cells: 39 on 11 levels
--- /dev/null
+
+DEAL::no. cells: 12 on 2 levels
+DEAL::no. cells: 15 on 3 levels
+DEAL::no. cells: 18 on 4 levels
+DEAL::no. cells: 21 on 5 levels
+DEAL::no. cells: 24 on 6 levels
+DEAL::no. cells: 27 on 7 levels
+DEAL::no. cells: 30 on 8 levels
+DEAL::no. cells: 33 on 9 levels
+DEAL::no. cells: 36 on 10 levels
+DEAL::no. cells: 39 on 11 levels