Program Listing for File local_preconditioner.h¶
↰ Return to documentation for file (include/immersx/algebra/local_preconditioner.h)
// ---------------------------------------------------------------------
//
// Copyright (C) 2026 by Luca Heltai
//
// This file is part of the ImmersX application, based on the deal.II
// library.
//
// ---------------------------------------------------------------------
#ifndef immersx_local_preconditioner_h
#define immersx_local_preconditioner_h
#include <deal.II/lac/linear_operator.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/vector_memory.h>
#include <immersx/algebra/linear_algebra.h>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
namespace ImmersX
{
namespace detail
{
template <typename PreconditionerType, typename VectorType, typename = void>
struct has_transpose_apply : std::false_type
{};
template <typename PreconditionerType, typename VectorType>
struct has_transpose_apply<
PreconditionerType,
VectorType,
std::void_t<decltype(std::declval<const PreconditionerType &>().Tvmult(
std::declval<VectorType &>(),
std::declval<const VectorType &>()))>> : std::true_type
{};
} // namespace detail
template <typename VectorType,
typename MatrixType,
typename PreconditionerType>
dealii::LinearOperator<VectorType>
make_local_preconditioner(
const MatrixType &matrix,
const std::function<void(VectorType &, bool)> &reinit_vector,
const typename PreconditionerType::AdditionalData &additional_data = {})
{
auto preconditioner = std::make_shared<PreconditionerType>();
preconditioner->initialize(matrix, additional_data);
auto vector_memory =
std::make_shared<dealii::GrowingVectorMemory<VectorType>>();
dealii::LinearOperator<VectorType> result;
result.reinit_range_vector = reinit_vector;
result.reinit_domain_vector = result.reinit_range_vector;
result.vmult = [preconditioner](VectorType &dst, const VectorType &src) {
preconditioner->vmult(dst, src);
};
result.vmult_add = [preconditioner, vector_memory](VectorType &dst,
const VectorType &src) {
typename dealii::VectorMemory<VectorType>::Pointer contribution(
*vector_memory);
contribution->reinit(dst);
preconditioner->vmult(*contribution, src);
dst += *contribution;
};
result.Tvmult = [preconditioner](VectorType &dst, const VectorType &src) {
if constexpr (detail::has_transpose_apply<PreconditionerType,
VectorType>::value)
preconditioner->Tvmult(dst, src);
else
AssertThrow(false,
dealii::ExcMessage(
"The local preconditioner has no transpose action."));
};
result.Tvmult_add = [preconditioner, vector_memory](VectorType &dst,
const VectorType &src) {
if constexpr (detail::has_transpose_apply<PreconditionerType,
VectorType>::value)
{
typename dealii::VectorMemory<VectorType>::Pointer contribution(
*vector_memory);
contribution->reinit(dst);
preconditioner->Tvmult(*contribution, src);
dst += *contribution;
}
else
AssertThrow(false,
dealii::ExcMessage(
"The local preconditioner has no transpose action."));
};
return result;
}
template <typename VectorType, typename MatrixType>
dealii::LinearOperator<VectorType>
make_amg_preconditioner(
const MatrixType &matrix,
const std::function<void(VectorType &, bool)> &reinit_vector,
const typename ImmersXLA::MPI::PreconditionAMG::AdditionalData
&additional_data = {})
{
return make_local_preconditioner<VectorType,
MatrixType,
ImmersXLA::MPI::PreconditionAMG>(
matrix, reinit_vector, additional_data);
}
} // namespace ImmersX
#endif // immersx_local_preconditioner_h