Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MGTransferMF: check compatibility of DoFHandlers #16088

Merged
merged 4 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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