Skip to content

Commit

Permalink
Merge pull request #16088 from peterrum/assert_dof_handler
Browse files Browse the repository at this point in the history
MGTransferMF: check compatibility of DoFHandlers
  • Loading branch information
kronbichler committed Oct 11, 2023
2 parents 91ad9f1 + 1dbe570 commit e56363a
Show file tree
Hide file tree
Showing 5 changed files with 725 additions and 54 deletions.
7 changes: 7 additions & 0 deletions doc/news/changes/minor/20231003Munch
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Improved: MGTransferMF can now permute DoFs during
MGTransferMF::copy_to_mg(), MGTransferMF::copy_to_mg(),
and MGTransferMF::interpolate_to_mg() if the outer
solver and the multigrid preconditioner have been set up
with different DoFHandler objects.
<br>
(Peter Munch, Laura Prieto Saavedra, 2023/10/03)
157 changes: 120 additions & 37 deletions include/deal.II/multigrid/mg_transfer_global_coarsening.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ namespace RepartitioningPolicyTools
template <int dim, int spacedim>
class Base;
}

template <int dim, typename Number>
class MGTransferMF;
#endif


Expand Down Expand Up @@ -706,7 +709,19 @@ class MGTwoLevelTransfer<dim, LinearAlgebra::distributed::Vector<Number>>
*/
unsigned int n_components;

/**
* Pointer to the DoFHandler object used during initialization.
*/
SmartPointer<const DoFHandler<dim>> dof_handler_fine;

/**
* Muligird level used during initialization.
*/
unsigned int mg_level_fine;

friend class internal::MGTwoLevelTransferImplementation;

friend class MGTransferMF<dim, Number>;
};


Expand Down Expand Up @@ -919,6 +934,16 @@ class MGTwoLevelTransferNonNested<dim,
LinearAlgebra::distributed::Vector<Number> &dst,
const LinearAlgebra::distributed::Vector<Number> &src) const;

/**
* Pointer to the DoFHandler object used during initialization.
*/
SmartPointer<const DoFHandler<dim>> dof_handler_fine;

/**
* Multigrid level used during initialization.
*/
unsigned int mg_level_fine;

/**
* Object to evaluate shape functions on one mesh on visited support points of
* the other mesh.
Expand Down Expand Up @@ -954,6 +979,8 @@ class MGTwoLevelTransferNonNested<dim,
* point.
*/
std::vector<unsigned int> level_dof_indices_fine_ptrs;

friend class MGTransferMF<dim, Number>;
};


Expand Down Expand Up @@ -1001,7 +1028,7 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
*
* @note See also MGTransferMatrixFree.
*/
MGTransferMF() = default;
MGTransferMF();

/**
* @name Global coarsening.
Expand Down Expand Up @@ -1073,10 +1100,21 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
void
initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs);

/** @} */

/**
* @name Global coarsening and local smoothing.
*/
/** @{ */

/**
* Actually build the information for the prolongation for each level.
*
* @note See also MGTransferMatrixFree.
* @note In the case of global coarsening, you can pass a @p dof_handler
* with different DoF numbering as the one used within the provided
* two-level transfer objects into this function. In this case, vector
* entries are permuted during copy_to_mg(), copy_from_mg(), and
* interpolate_to_mg().
*/
void
build(const DoFHandler<dim> &dof_handler,
Expand All @@ -1087,7 +1125,10 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
* Same as above but taking a lambda for initializing vector instead of
* partitioners.
*
* @note See also MGTransferMatrixFree.
* @note In the case of global coarsening, you can pass into this function
* a @p dof_handler with different DoF numbering as the one used within the
* provided two-level transfer objects. In this case, vector entries are
* permuted during copy_to_mg(), copy_from_mg(), and interpolate_to_mg().
*/
void
build(const DoFHandler<dim> &dof_handler,
Expand Down Expand Up @@ -1126,10 +1167,13 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
const VectorType &src) const override;

/**
* Initialize internal vectors and copy @p src vector to the finest
* multigrid level.
* Initialize internal vectors and copy @p src vector
* (associated to @p dof_handler) to the finest multigrid level.
*
* @note DoFHandler is not needed here, but is required by the interface.
* @note The @p dof_handler object needs to be the same as the DoFHandler passed
* directly to the function build() or indirectly to the function
* initialize_two_level_transfers(). Alternatively, the numbering of the DoFs
* need to be same.
*/
template <class InVector>
void
Expand All @@ -1138,10 +1182,13 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
const InVector &src) const;

/**
* Initialize internal vectors and copy the values on the finest
* multigrid level to @p dst vector.
* Copy the values on the finest multigrid level to @p dst
* vector (associated to @p dof_handler).
*
* @note DoFHandler is not needed here, but is required by the interface.
* @note The @p dof_handler object needs to be the same as the DoFHandler passed
* directly to the function build() or indirectly to the function
* initialize_two_level_transfers(). Alternatively, the numbering of the DoFs
* need to be same.
*/
template <class OutVector>
void
Expand All @@ -1150,32 +1197,40 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
const MGLevelObject<VectorType> &src) const;

/**
* Interpolate fine-mesh field @p src to each multigrid level in
* @p dof_handler and store the result in @p dst. This function is different
* from restriction, where a weighted residual is
* transferred to a coarser level (transposition of prolongation matrix).
* Interpolate fine-mesh field @p src (associated to @p dof_handler)
* to each multigrid level and
* store the result in @p dst. This function is different from
* restriction, where a weighted residual is transferred to a coarser
* level (transposition of prolongation matrix).
*
* The argument @p dst has to be initialized with the correct size according
* to the number of levels of the triangulation.
*
* If an inner vector of @p dst is empty or has incorrect locally owned size,
* it will be resized to locally relevant degrees of freedom on each level.
*
* @note The @p dof_handler object needs to be the same as the DoFHandler passed
* directly to the function build() or indirectly to the function
* initialize_two_level_transfers(). Alternatively, the numbering of the DoFs
* need to be same.
*/
template <class InVector>
void
interpolate_to_mg(MGLevelObject<VectorType> &dst, const InVector &src) const;
interpolate_to_mg(const DoFHandler<dim> &dof_handler,
MGLevelObject<VectorType> &dst,
const InVector &src) const;

/**
* 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 MGTransferMF and
* MGTransferMatrixFree as template argument.
* Interpolate fine-mesh field @p src to each multigrid level and
* store the result in @p dst.
*
* @note In contrast to the last function, no @p dof_handler object needs passed.
* This function used the DoFHandler passed directly to the function build()
* or indirectly to the function initialize_two_level_transfers().
*/
template <class InVector>
void
interpolate_to_mg(const DoFHandler<dim> &dof_handler,
MGLevelObject<VectorType> &dst,
const InVector &src) const;
interpolate_to_mg(MGLevelObject<VectorType> &dst, const InVector &src) const;

/** @} */

Expand Down Expand Up @@ -1225,6 +1280,21 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
const DoFHandler<dim> &dof_handler,
const SmartPointer<const MGConstrainedDoFs> &mg_constrained_dofs);

/**
* Retrieve finest DoFHandler from two-level transfer objects.
*/
std::pair<const DoFHandler<dim> *, unsigned int>
get_dof_handler_fine() const;

/**
* Initialize copy indices for MGTransferMF::copy_to_mg(),
* MGTransferMF::copy_to_mg(), and MGTransferMF::interpolate_to_mg()
* in the case of global coarsening.
*/
void
fill_and_communicate_copy_indices_global_coarsening(
const DoFHandler<dim> &dof_handler);

/**
* Set references to two-level transfer operators to be used.
*/
Expand All @@ -1243,6 +1313,14 @@ class MGTransferMF : public dealii::MGLevelGlobalTransfer<
const InVector &vector_reference,
const bool omit_zeroing_entries) const;

/**
* Check that the internal DoFHandler is compatible with the external one
* provided by copy_to_mg(), copy_from_mg() and interpolate_to_mg()
* used, e.g., by PreconditionMG.
*/
void
assert_dof_handler(const DoFHandler<dim> &dof_handler_out) const;

/**
* Internal transfer operator.
*
Expand Down Expand Up @@ -1374,6 +1452,9 @@ MGTransferMF<dim, Number>::MGTransferMF(
const std::function<void(const unsigned int, VectorType &)>
&initialize_dof_vector)
{
this->transfer.clear();
this->internal_transfer.clear();

this->initialize_transfer_references(transfer);
this->build(initialize_dof_vector);
}
Expand Down Expand Up @@ -1465,7 +1546,7 @@ MGTransferMF<dim, Number>::copy_to_mg(const DoFHandler<dim> &dof_handler,
MGLevelObject<VectorType> &dst,
const InVector &src) const
{
(void)dof_handler;
assert_dof_handler(dof_handler);

for (unsigned int level = dst.min_level(); level <= dst.max_level(); ++level)
{
Expand Down Expand Up @@ -1524,7 +1605,7 @@ MGTransferMF<dim, Number>::copy_from_mg(
OutVector &dst,
const MGLevelObject<VectorType> &src) const
{
(void)dof_handler;
assert_dof_handler(dof_handler);

if (this->perform_plain_copy)
{
Expand Down Expand Up @@ -1576,6 +1657,22 @@ void
MGTransferMF<dim, Number>::interpolate_to_mg(MGLevelObject<VectorType> &dst,
const InVector &src) const
{
DoFHandler<dim> dof_handler_dummy;

this->interpolate_to_mg(dof_handler_dummy, dst, src);
}



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
{
assert_dof_handler(dof_handler);

const unsigned int min_level = transfer.min_level();
const unsigned int max_level = transfer.max_level();

Expand Down Expand Up @@ -1636,20 +1733,6 @@ MGTransferMF<dim, Number>::interpolate_to_mg(MGLevelObject<VectorType> &dst,
}
}



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
{
(void)dof_handler;

this->interpolate_to_mg(dst, src);
}

#endif

DEAL_II_NAMESPACE_CLOSE
Expand Down

0 comments on commit e56363a

Please sign in to comment.