Skip to content

Commit

Permalink
Merge branch 'simplify_solverfactory' into 'master'
Browse files Browse the repository at this point in the history
simplify and cleanup the SolverFactory

See merge request core/dune-istl!453
  • Loading branch information
chr-engwer committed Sep 19, 2024
2 parents 9d1e346 + f1d2294 commit 43a98e6
Show file tree
Hide file tree
Showing 16 changed files with 576 additions and 374 deletions.
55 changes: 26 additions & 29 deletions dune/istl/cholmod.hh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh>
#include<dune/istl/solver.hh>
#include <dune/istl/solverfactory.hh>
#include <dune/istl/solverregistry.hh>
#include <dune/istl/foreach.hh>

#include <vector>
Expand Down Expand Up @@ -524,34 +524,31 @@ private:
std::vector<std::size_t> subIndices_;
};

struct CholmodCreator{
template<class F> struct isValidBlock : std::false_type{};
template<int k> struct isValidBlock<FieldVector<double,k>> : std::true_type{};
template<int k> struct isValidBlock<FieldVector<float,k>> : std::true_type{};

template<class TL, typename M>
std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator()(TL /*tl*/, const M& mat, const Dune::ParameterTree& /*config*/,
std::enable_if_t<isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
{
using D = typename Dune::TypeListElement<1, TL>::type;
auto solver = std::make_shared<Dune::Cholmod<D>>();
solver->setMatrix(mat);
return solver;
}

// second version with SFINAE to validate the template parameters of Cholmod
template<typename TL, typename M>
std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator() (TL /*tl*/, const M& /*mat*/, const Dune::ParameterTree& /*config*/,
std::enable_if_t<!isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
{
DUNE_THROW(UnsupportedType, "Unsupported Type in Cholmod");
}
};
DUNE_REGISTER_DIRECT_SOLVER("cholmod", Dune::CholmodCreator());
DUNE_REGISTER_SOLVER("cholmod",
[](auto opTraits, const auto& op, const Dune::ParameterTree& config)
-> std::shared_ptr<typename decltype(opTraits)::solver_type>
{
using OpTraits = decltype(opTraits);
using M = typename OpTraits::matrix_type;
using D = typename OpTraits::domain_type;
// works only for sequential operators
if constexpr (OpTraits::isParallel){
if(opTraits.getCommOrThrow(op).communicator().size() > 1)
DUNE_THROW(Dune::InvalidStateException, "CholMod works only for sequential operators.");
}
if constexpr (OpTraits::isAssembled &&
// check whether the Matrix field_type is double or float
(std::is_same_v<typename FieldTraits<D>::field_type, double> ||
std::is_same_v<typename FieldTraits<D>::field_type, float>)){
const auto& A = opTraits.getAssembledOpOrThrow(op);
const M& mat = A->getmat();
auto solver = std::make_shared<Dune::Cholmod<D>>();
solver->setMatrix(mat);
return solver;
}
DUNE_THROW(UnsupportedType,
"Unsupported Type in Cholmod (only double and float supported)");
});

} /* namespace Dune */

Expand Down
2 changes: 1 addition & 1 deletion dune/istl/common/registry.hh
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace Dune {
}

/*
Register all creators from the registry in the Parameterizedobjectfactory An
Register all creators from the registry in the Parameterizedobjectfactory. An
object of V is passed in the creator and should be used to determine the
template arguments.
*/
Expand Down
57 changes: 28 additions & 29 deletions dune/istl/ldl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern "C"
#include <dune/istl/bccsmatrixinitializer.hh>
#include <dune/istl/solvers.hh>
#include <dune/istl/solvertype.hh>
#include <dune/istl/solverfactory.hh>
#include <dune/istl/solverregistry.hh>

namespace Dune {
/**
Expand Down Expand Up @@ -370,34 +370,33 @@ namespace Dune {
enum {value = true};
};

struct LDLCreator {
template<class F> struct isValidBlock : std::false_type{};
template<int k> struct isValidBlock<FieldVector<double,k>> : std::true_type{};

template<typename TL, typename M>
std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator() (TL /*tl*/, const M& mat, const Dune::ParameterTree& config,
std::enable_if_t<
isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
{
int verbose = config.get("verbose", 0);
return std::make_shared<Dune::LDL<M>>(mat,verbose);
}

// second version with SFINAE to validate the template parameters of LDL
template<typename TL, typename M>
std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator() (TL /*tl*/, const M& /*mat*/, const Dune::ParameterTree& /*config*/,
std::enable_if_t<
!isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
{
DUNE_THROW(UnsupportedType,
"Unsupported Type in LDL (only double and std::complex<double> supported)");
}
};
DUNE_REGISTER_DIRECT_SOLVER("ldl", Dune::LDLCreator());
DUNE_REGISTER_SOLVER("ldl",
[](auto opTraits, const auto& op, const Dune::ParameterTree& config)
-> std::shared_ptr<typename decltype(opTraits)::solver_type>
{
using OpTraits = decltype(opTraits);
using M = typename OpTraits::matrix_type;
// works only for sequential operators
if constexpr (OpTraits::isParallel){
if(opTraits.getCommOrThrow(op).communicator().size() > 1)
DUNE_THROW(Dune::InvalidStateException, "LDL works only for sequential operators.");
}
// check if LDL<M>* is convertible to
// InverseOperator*. This allows only the explicit
// specialized variants of LDL
if constexpr (std::is_convertible_v<LDL<M>*,
Dune::InverseOperator<typename OpTraits::domain_type,
typename OpTraits::range_type>*> &&
std::is_same_v<typename FieldTraits<M>::field_type, double>
){
const auto& A = opTraits.getAssembledOpOrThrow(op);
const M& mat = A->getmat();
int verbose = config.get("verbose", 0);
return std::make_shared<LDL<M>>(mat,verbose);
}
DUNE_THROW(UnsupportedType,
"Unsupported Type in LDL (only FieldMatrix<double,...> supported)");
});

} // end namespace Dune

Expand Down
4 changes: 2 additions & 2 deletions dune/istl/novlpschwarz.hh
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ namespace Dune {
y += y1;
}

//! get matrix via *
const matrix_type& getmat () const override
//! get reference to matrix
const M& getmat () const override
{
return *_A_;
}
Expand Down
12 changes: 9 additions & 3 deletions dune/istl/operators.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_ISTL_OPERATORS_HH
#define DUNE_ISTL_OPERATORS_HH
Expand Down Expand Up @@ -116,7 +115,7 @@ namespace Dune {
typedef Y range_type;
typedef typename X::field_type field_type;

//! get matrix via *
//! get reference to matrix
virtual const M& getmat () const = 0;
};

Expand Down Expand Up @@ -159,7 +158,7 @@ namespace Dune {
_A_->usmv(alpha,x,y);
}

//! get matrix via *
//! get reference to matrix
const M& getmat () const override
{
return *_A_;
Expand All @@ -180,3 +179,10 @@ namespace Dune {
} // end namespace

#endif

// Emacs configuration
// Local Variables:
// tab-width: 4
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
32 changes: 19 additions & 13 deletions dune/istl/paamg/amg.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <dune/istl/superlu.hh>
#include <dune/istl/umfpack.hh>
#include <dune/istl/solvertype.hh>
#include <dune/istl/solverregistry.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/scalarvectorview.hh>
Expand Down Expand Up @@ -1167,8 +1168,8 @@ namespace Dune
} // end namespace Amg

struct AMGCreator{
template<class> struct isValidBlockType : std::false_type{};
template<class T, int n, int m> struct isValidBlockType<FieldMatrix<T,n,m>> : std::true_type{};
template<class> struct isValidMatrix : std::false_type{};
template<class T, int n, int m, class A> struct isValidMatrix<BCRSMatrix<FieldMatrix<T,n,m>, A>> : std::true_type{};

template<class OP>
std::shared_ptr<Dune::Preconditioner<typename OP::element_type::domain_type, typename OP::element_type::range_type> >
Expand Down Expand Up @@ -1242,13 +1243,13 @@ namespace Dune
DUNE_THROW(Dune::Exception, "Unknown smoother for AMG");
}

template<typename TL, typename OP>
std::shared_ptr<Dune::Preconditioner<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator() (TL tl, const std::shared_ptr<OP>& op, const Dune::ParameterTree& config,
std::enable_if_t<isValidBlockType<typename OP::matrix_type::block_type>::value,int> = 0) const
template<typename OpTraits, typename OP>
std::shared_ptr<Dune::Preconditioner<typename OpTraits::domain_type,
typename OpTraits::range_type>>
operator() (OpTraits opTraits, const std::shared_ptr<OP>& op, const Dune::ParameterTree& config,
std::enable_if_t<isValidMatrix<typename OpTraits::matrix_type>::value,int> = 0) const
{
using field_type = typename OP::matrix_type::field_type;
using field_type = typename OpTraits::matrix_type::field_type;
using real_type = typename FieldTraits<field_type>::real_type;
if (!std::is_convertible<field_type, real_type>())
DUNE_THROW(UnsupportedType, "AMG needs field_type(" <<
Expand All @@ -1257,14 +1258,19 @@ namespace Dune
className<real_type>() <<
").");
std::string smoother = config.get("smoother", "ssor");
// we can irgnore the OpTraits here. As the AMG can only work
// with actual matrices, the operator op must be of type
// MatrixAdapter or *SchwarzOperator. In any case these
// operators provide all necessary information about matrix,
// domain and range type
return makeAMG(op, smoother, config);
}

template<typename TL, typename OP>
std::shared_ptr<Dune::Preconditioner<typename Dune::TypeListElement<1, TL>::type,
typename Dune::TypeListElement<2, TL>::type>>
operator() (TL /*tl*/, const std::shared_ptr<OP>& /*mat*/, const Dune::ParameterTree& /*config*/,
std::enable_if_t<!isValidBlockType<typename OP::matrix_type::block_type>::value,int> = 0) const
template<typename OpTraits, typename OP>
std::shared_ptr<Dune::Preconditioner<typename OpTraits::domain_type,
typename OpTraits::range_type>>
operator() (OpTraits opTraits, const std::shared_ptr<OP>& op, const Dune::ParameterTree& config,
std::enable_if_t<!isValidMatrix<typename OpTraits::matrix_type>::value,int> = 0) const
{
DUNE_THROW(UnsupportedType, "AMG needs a FieldMatrix as Matrix block_type");
}
Expand Down
11 changes: 6 additions & 5 deletions dune/istl/preconditioners.hh
Original file line number Diff line number Diff line change
Expand Up @@ -949,11 +949,12 @@ namespace Dune {
//! \brief The relaxation factor to use.
real_field_type _w;
};
DUNE_REGISTER_PRECONDITIONER("richardson", [](auto tl, const auto& /* mat */, const ParameterTree& config){
using D = typename Dune::TypeListElement<1, decltype(tl)>::type;
using R = typename Dune::TypeListElement<2, decltype(tl)>::type;
return std::make_shared<Richardson<D,R>>(config);
});
DUNE_REGISTER_PRECONDITIONER("richardson", [](auto opTraits, const auto& op, const ParameterTree& config){
using OpTraits = std::decay_t<decltype(opTraits)>;
using D = typename OpTraits::domain_type;
using R = typename OpTraits::range_type;
return std::make_shared<Richardson<D,R>>(config);
});


/**
Expand Down
Loading

0 comments on commit 43a98e6

Please sign in to comment.