Commit bd9cc7c0 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Matrix-Vector facade class

parent 6804ddd9
......@@ -10,6 +10,7 @@ HIDE_SCOPE_NAMES = YES
HIDE_UNDOC_CLASSES = NO
INTERNAL_DOCS = NO
MARKDOWN_SUPPORT = YES
GENERATE_XML = YES
EXCLUDE_SYMBOLS = AMDiS::Impl \
AMDiS::Math::Impl_ \
......@@ -30,6 +31,7 @@ PREDEFINED += HAVE_UMFPACK \
INPUT += @top_srcdir@/src/amdis \
@top_srcdir@/src/amdis/common \
@top_srcdir@/src/amdis/functions \
@top_srcdir@/src/amdis/gridfunctions \
@top_srcdir@/src/amdis/linearalgebra \
@top_srcdir@/src/amdis/linearalgebra/mtl \
......@@ -47,7 +49,8 @@ INPUT += @top_srcdir@/src/amdis \
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE += @top_srcdir@/src/amdis/linearalgebra/eigen \
@top_srcdir@/src/amdis/linearalgebra/istl
@top_srcdir@/src/amdis/linearalgebra/istl \
@top_srcdir@/src/amdis/linearalgebra/petsc
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
......
......@@ -20,14 +20,12 @@ namespace AMDiS
* \tparam CB Basis of matrix columns
* \tparam T Coefficient type to store in the matrix
**/
template <class RB, class CB, class T = double>
template <class RB, class CB, class T = double, class Traits = BackendTraits<RB,T>>
class BiLinearForm
: public MatrixBase<RB,CB,MatrixBackend<BackendTraits<RB,T>>>
: public MatrixFacade<T, typename Traits::SparsityPattern, Traits::template MatrixImpl>
{
using Self = BiLinearForm;
using Traits = BackendTraits<RB,T>;
using Backend = MatrixBackend<Traits>;
using Super = MatrixBase<RB,CB,Backend>;
using Super = MatrixFacade<T, typename Traits::SparsityPattern, Traits::template MatrixImpl>;
public:
/// The type of the finite element space / basis of the row
......@@ -47,23 +45,21 @@ namespace AMDiS
public:
/// Constructor. Wraps the reference into a non-destroying shared_ptr or moves the basis into
/// a new shared_ptr.
template <class RB_, class CB_>
BiLinearForm(RB_&& rowBasis, CB_&& colBasis)
: Super(FWD(rowBasis), FWD(colBasis))
BiLinearForm(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis)
: Super(*rowBasis, *colBasis)
, rowBasis_(rowBasis)
, colBasis_(colBasis)
{
operators_.init(*Super::rowBasis(), *Super::colBasis());
}
/// Prepare the matrix for insertion. Clears all the entries.
void init(SymmetryStructure symmetry = SymmetryStructure::unknown)
{
Super::init(symmetry);
operators_.init(*rowBasis, *colBasis);
auto const rowSize = this->rowBasis()->localView().maxSize();
auto const colSize = this->colBasis()->localView().maxSize();
auto const rowSize = rowBasis->localView().maxSize();
auto const colSize = colBasis->localView().maxSize();
elementMatrix_.resize(rowSize, colSize);
}
std::shared_ptr<RowBasis const> const& rowBasis() const { return rowBasis_; }
std::shared_ptr<ColBasis const> const& colBasis() const { return colBasis_; }
/// \brief Associate a local operator with this BiLinearForm
/**
* Stores an operator in a list that gets assembled during a call to \ref assemble().
......@@ -118,6 +114,9 @@ namespace AMDiS
/// List of operators associated to row/col node
MatrixOperators<RowBasis,ColBasis,ElementMatrix> operators_;
std::shared_ptr<RowBasis const> rowBasis_;
std::shared_ptr<ColBasis const> colBasis_;
};
......
......@@ -9,9 +9,9 @@
namespace AMDiS {
template <class RB, class CB, class T>
template <class RB, class CB, class T, class Traits>
template <class ContextTag, class Expr, class RowTreePath, class ColTreePath>
void BiLinearForm<RB,CB,T>::
void BiLinearForm<RB,CB,T,Traits>::
addOperator(ContextTag contextTag, Expr const& expr,
RowTreePath row, ColTreePath col)
{
......@@ -24,16 +24,16 @@ addOperator(ContextTag contextTag, Expr const& expr,
auto j = child(this->colBasis()->localView().tree(), makeTreePath(col));
using LocalContext = typename ContextTag::type;
using Traits = DefaultAssemblerTraits<LocalContext, ElementMatrix>;
using Tr = DefaultAssemblerTraits<LocalContext, ElementMatrix>;
auto op = makeLocalOperator<LocalContext>(expr, this->rowBasis()->gridView());
auto localAssembler = makeUniquePtr(makeAssembler<Traits>(std::move(op), i, j));
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), i, j));
operators_[i][j].push(contextTag, std::move(localAssembler));
}
template <class RB, class CB, class T>
void BiLinearForm<RB,CB,T>::
template <class RB, class CB, class T, class Traits>
void BiLinearForm<RB,CB,T,Traits>::
assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
{
elementMatrix_.resize(rowLocalView.size(), colLocalView.size());
......@@ -58,8 +58,8 @@ assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
}
template <class RB, class CB, class T>
void BiLinearForm<RB,CB,T>::
template <class RB, class CB, class T, class Traits>
void BiLinearForm<RB,CB,T,Traits>::
assemble(SymmetryStructure symmetry)
{
auto rowLocalView = this->rowBasis()->localView();
......
......@@ -33,38 +33,40 @@ namespace AMDiS
/**
* \tparam GB Basis of the vector
* \tparam T Type of the coefficients
* \tparam TraitsType Collection of parameter for the linear-algebra backend
**/
template <class GB, class T = double>
template <class GB, class T = double, class TraitsType = BackendTraits<GB,T>>
class DOFVector
: public VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>
: public VectorFacade<T, TraitsType::template VectorImpl>
, private Observer<event::preAdapt>
, private Observer<event::adapt>
, private Observer<event::postAdapt>
{
using Self = DOFVector;
using Super = VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>;
using Coefficients = VectorFacade<T, TraitsType::template VectorImpl>;
public:
using Backend = VectorBackend<BackendTraits<GB,T>>;
using GlobalBasis = GB;
/// The index/size - type
using size_type = typename GlobalBasis::size_type;
/// The type of the elements of the DOFVector
using value_type = typename Backend::value_type;
using value_type = T;
/// Wrapper for the implementation of the transfer of data during grid adaption
using DataTransfer = DataTransferWrapper<Self>;
/// Collection of parameter for the linear-algebra backend
using Traits = TraitsType;
public:
/// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
DOFVector(std::shared_ptr<GB> const& basis,
DataTransferOperation op = DataTransferOperation::INTERPOLATE)
: Super(basis)
: Coefficients(*basis)
, Observer<event::preAdapt>(basis->gridView().grid())
, Observer<event::adapt>(*basis)
, Observer<event::adapt>(basis)
, Observer<event::postAdapt>(basis->gridView().grid())
, dataTransfer_(op, basis)
, basis_(basis)
......@@ -83,19 +85,20 @@ namespace AMDiS
: DOFVector(Dune::wrap_or_move(FWD(basis)), op)
{}
std::shared_ptr<GlobalBasis const> const& basis() const { return basis_; }
template <class TreePath = RootTreePath>
auto child(TreePath const& path = {})
{
auto&& tp = makeTreePath(path);
return makeDiscreteFunction(*this, tp);
return makeDiscreteFunction(coefficients(), *basis_, tp);
}
template <class TreePath = RootTreePath>
auto child(TreePath const& path = {}) const
{
auto&& tp = makeTreePath(path);
return makeDiscreteFunction(*this, tp);
return makeDiscreteFunction(coefficients(), *basis_, tp);
}
......@@ -103,7 +106,7 @@ namespace AMDiS
/// reference to this DOFVector in the expression.
/// See \ref DiscreteFunction::interpolate_noalias
template <class Expr, class Tag = tag::average>
void interpolate_noalias(Expr&& expr, Tag strategy)
void interpolate_noalias(Expr&& expr, Tag strategy = {})
{
child().interpolate_noalias(FWD(expr), strategy);
}
......@@ -111,7 +114,7 @@ namespace AMDiS
/// Interpolation of GridFunction to DOFVector.
/// See \ref DiscreteFunction::interpolate
template <class Expr, class Tag = tag::average>
void interpolate(Expr&& expr, Tag strategy)
void interpolate(Expr&& expr, Tag strategy = {})
{
child().interpolate(FWD(expr), strategy);
}
......@@ -126,6 +129,16 @@ namespace AMDiS
}
Coefficients const& coefficients() const
{
return static_cast<Coefficients const&>(*this);
}
Coefficients& coefficients()
{
return static_cast<Coefficients&>(*this);
}
/// Write DOFVector to file
void backup(std::string const& filename);
......@@ -192,7 +205,7 @@ namespace AMDiS
/// to \ref DataTransferOperation::INTERPOLATE.
DataTransfer dataTransfer_;
std::shared_ptr<GB> basis_;
std::shared_ptr<GlobalBasis const> basis_;
};
#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
......@@ -218,6 +231,20 @@ namespace AMDiS
return {FWD(basis), op};
}
/// A Generator for a mutable \ref DiscreteFunction
template <class GB, class T, class Path = RootTreePath>
auto makeDiscreteFunction(DOFVector<GB,T>& dofVec, Path const& path = {})
{
return dofVec.child(path);
}
/// A Generator for a mutable \ref DiscreteFunction
template <class GB, class T, class Path = RootTreePath>
auto makeDiscreteFunction(DOFVector<GB,T> const& dofVec, Path const& path = {})
{
return dofVec.child(path);
}
} // end namespace AMDiS
#include <amdis/DOFVector.inc.hpp>
......@@ -10,8 +10,8 @@
namespace AMDiS {
template <class GB, class B>
void DOFVector<GB,B>::
template <class GB, class T, class Traits>
void DOFVector<GB,T,Traits>::
backup(std::string const& filename)
{
std::ofstream out(filename, std::ios::binary);
......@@ -35,8 +35,8 @@ backup(std::string const& filename)
}
template <class GB, class B>
void DOFVector<GB,B>::
template <class GB, class T, class Traits>
void DOFVector<GB,T,Traits>::
restore(std::string const& filename)
{
std::ifstream in(filename, std::ios::binary);
......
......@@ -82,7 +82,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
auto maxLevel = gv.grid().maxLevel();
using std::sqrt;
typename Grid::ctype const checkInsideTolerance = sqrt(std::numeric_limits<typename Grid::ctype>::epsilon());
for (auto const& e : elements(gv, typename C::Backend::Traits::PartitionSet{}))
for (auto const& e : elements(gv, typename C::Traits::PartitionSet{}))
{
auto father = e;
while (father.mightVanish() && father.hasFather())
......@@ -162,7 +162,7 @@ void DataTransfer<C,B>::adapt(C& coeff)
mapper_.update();
std::vector<bool> finished(mapper_.size(), false);
for (const auto& e : elements(gv, typename C::Backend::Traits::PartitionSet{}))
for (const auto& e : elements(gv, typename C::Traits::PartitionSet{}))
{
auto index = mapper_.index(e);
if (finished[index])
......
......@@ -37,7 +37,7 @@
#endif
#include <amdis/linearalgebra/MatrixBase.hpp>
#include <amdis/linearalgebra/VectorBase.hpp>
#include <amdis/linearalgebra/MatrixFacade.hpp>
#include <amdis/linearalgebra/VectorFacade.hpp>
#include <amdis/linearalgebra/LinearSolver.hpp>
#include <amdis/linearalgebra/SolverInfo.hpp>
......@@ -17,24 +17,20 @@ namespace AMDiS
*
* \tparam GB Basis of the vector
* \tparam T Coefficient type to store in the vector
* \tparam Traits Collection of parameter for the linear-algebra backend
**/
template <class GB, class T = double>
template <class GB, class T = double, class Traits = BackendTraits<GB,T>>
class LinearForm
: public VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>
: public VectorFacade<T, Traits::template VectorImpl>
{
using Super = VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>;
using Super = VectorFacade<T, Traits::template VectorImpl>;
using Self = LinearForm;
public:
using Backend = VectorBackend<BackendTraits<GB,T>>;
/// The type of the functionspace basis associated to this linearform
using GlobalBasis = GB;
using LocalView = typename GlobalBasis::LocalView;
/// A traits class collecting several parameters of the linear algebra backend
using Traits = typename Backend::Traits;
/// The type of the elements of the DOFVector
using CoefficientType = typename Traits::CoefficientType;
......@@ -43,24 +39,18 @@ namespace AMDiS
public:
/// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
template <class GB_,
Dune::disableCopyMove<Self, GB_> = 0>
explicit LinearForm(GB_&& basis)
: Super(FWD(basis))
explicit LinearForm(std::shared_ptr<GB> const& basis)
: Super(*basis)
, basis_(basis)
{
operators_.init(*Super::basis());
}
operators_.init(*basis);
/// Prepare the LinearForm for insertion of values, finish the insertion with
/// \ref finish().
void init(bool clear)
{
Super::init(clear);
auto const localSize = this->basis()->localView().maxSize();
auto const localSize = basis->localView().maxSize();
elementVector_.resize(localSize);
}
std::shared_ptr<GlobalBasis const> const& basis() const { return basis_; }
/// \brief Associate a local operator with this LinearForm
/**
* Stores an operator in a list that gets assembled during a call to \ref assemble().
......@@ -112,6 +102,8 @@ namespace AMDiS
/// List of operators associated to nodes, filled in \ref addOperator().
VectorOperators<GlobalBasis,ElementVector> operators_;
std::shared_ptr<GlobalBasis const> basis_;
};
......
......@@ -10,9 +10,9 @@
namespace AMDiS {
template <class GB, class B>
template <class GB, class T, class Traits>
template <class ContextTag, class Expr, class TreePath>
void LinearForm<GB,B>::
void LinearForm<GB,T,Traits>::
addOperator(ContextTag contextTag, Expr const& expr, TreePath path)
{
static_assert( Concepts::PreTreePath<TreePath>,
......@@ -21,16 +21,16 @@ addOperator(ContextTag contextTag, Expr const& expr, TreePath path)
auto i = child(this->basis()->localView().tree(), makeTreePath(path));
using LocalContext = typename ContextTag::type;
using Traits = DefaultAssemblerTraits<LocalContext, ElementVector>;
using Tr = DefaultAssemblerTraits<LocalContext, ElementVector>;
auto op = makeLocalOperator<LocalContext>(expr, this->basis()->gridView());
auto localAssembler = makeUniquePtr(makeAssembler<Traits>(std::move(op), i));
auto localAssembler = makeUniquePtr(makeAssembler<Tr>(std::move(op), i));
operators_[i].push(contextTag, std::move(localAssembler));
}
template <class GB, class B>
void LinearForm<GB,B>::
template <class GB, class T, class Traits>
void LinearForm<GB,T,Traits>::
assemble(typename GB::LocalView const& localView)
{
elementVector_.resize(localView.size());
......@@ -53,8 +53,8 @@ assemble(typename GB::LocalView const& localView)
}
template <class GB, class B>
void LinearForm<GB,B>::
template <class GB, class T, class Traits>
void LinearForm<GB,T,Traits>::
assemble()
{
auto localView = this->basis()->localView();
......
#pragma once
#include <algorithm>
#include <list>
#include <memory>
#include <set>
#include <type_traits>
#include <dune/common/shared_ptr.hh>
#include <dune/common/typeutilities.hh>
#include <amdis/common/ConceptsBase.hpp>
#include <amdis/Output.hpp>
#include <amdis/common/Index.hpp>
namespace AMDiS
{
......@@ -75,19 +76,17 @@ namespace AMDiS
/// Attach a new observer that gets called on \ref notify
void attach(ObserverInterface<Event>* o)
{
observers_.push_back(o);
observers_.insert(o);
}
/// Detaches the passed observer from the list, if stored.
void detach(ObserverInterface<Event>* o)
{
auto it = std::find(observers_.begin(), observers_.end(), o);
if (it != observers_.end())
observers_.erase(it);
observers_.erase(o);
}
private:
std::list<ObserverInterface<Event>*> observers_;
std::set<ObserverInterface<Event>*> observers_;
};
......@@ -98,17 +97,23 @@ namespace AMDiS
{
public:
template <class Notifier>
Observer(Notifier const& notifier)
: notifier_(const_cast<Notifier*>(&notifier))
Observer(std::shared_ptr<Notifier> notifier)
: notifier_(std::const_pointer_cast<std::remove_const_t<Notifier>>(std::move(notifier)))
{
notifier_->attach(this);
}
template <class Notifier,
class = void_t<decltype(std::declval<std::remove_const_t<Notifier>>().notify(std::declval<Event>()))> >
Observer(Notifier& notifier)
: Observer(Dune::stackobject_to_shared_ptr(notifier))
{}
/// Destructor, detaches from the notifier
virtual ~Observer()
{
assert(notifier_);
notifier_->detach(this);
if (notifier_)
notifier_->detach(this);
}
/// Copy constructor. Attaches this to the copied notifier
......@@ -121,23 +126,11 @@ namespace AMDiS
/// Copy-assignment operator, copies the notifier and attaches this.
Observer& operator=(Observer const& other)
{
notifier_ = other.notifier_;
notifier_->attach(this);
return *this;
}
/// Move assignment operator, implemented in terms of the move
/// assignment operator
Observer(Observer&& other)
{
*this = std::move(other);
}
/// Move-assignment operator, copies the notifier and attaches this.
Observer& operator=(Observer&& other)
{
notifier_ = other.notifier_;
notifier_->attach(this);
if (&other != this) {
notifier_->detach(this);
notifier_ = other.notifier_;
notifier_->attach(this);
}
return *this;
}
......@@ -155,7 +148,31 @@ namespace AMDiS
virtual void updateImpl(Event e, Tags...) = 0;
private:
Notifier<Event>* notifier_ = nullptr;
std::shared_ptr<Notifier<Event>> notifier_ = nullptr;
};
namespace Impl
{
template <class Event, class Tags>
class ObserverSequenceImpl;
/// Combination of multiple observers of the same event but with different tags
template <class Event, std::size_t... Is>
class ObserverSequenceImpl<Event, std::index_sequence<Is...>>
: private Observer<Event,index_t<Is>>...
{
public:
template <class... Notifiers,
REQUIRES(sizeof...(Notifiers) == sizeof...(Is))>
ObserverSequenceImpl(Notifiers&&... notifiers)
: Observer<Event,index_t<Is>>(FWD(notifiers))...
{}
};
} // end namespace Impl
template <class Event, std::size_t N>
using ObserverSequence = Impl::ObserverSequenceImpl<Event, std::make_index_sequence<N>>;
} // end namespace AMDiS
......@@ -382,8 +382,8 @@ solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData)
solverInfo.setStoreMatrixData(storeMatrixData);
solution_->resize();
linearSolver_->solve(systemMatrix_->backend().matrix(), solution_->backend().vector(),
rhs_->backend().vector(), globalBasis_->communicator(), solverInfo);
linearSolver_->solve(systemMatrix_->impl().matrix(), solution_->impl().vector(),
rhs_->impl().vector(), globalBasis_->communicator(), solverInfo);
if (solverInfo.info() > 0) {
msg("solution of discrete system needed {} seconds", t.elapsed());
......
......@@ -6,4 +6,5 @@ install(FILES
NodeIndices.hpp
Nodes.hpp
ParallelGlobalBasis.hpp
SizeInfo.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/functions)
......@@ -16,6 +16,7 @@
#include <amdis/functions/HierarchicNodeToRangeMap.hpp>
#include <amdis/functions/NodeIndices.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/linearalgebra/Traits.hpp>
#include <amdis/operations/Assigner.hpp>
#include <amdis/typetree/Traversal.hpp>
......@@ -39,7 +40,7 @@ namespace AMDiS
// set vector to zero at subtree
if (! std::is_same<Assign, Assigner::assign>::value) {
for (const auto& e : elements(basis.gridView(), typename Vec::Backend::Traits::PartitionSet{}))
for (const auto& e : elements(basis.gridView(), typename BackendTraits<B>::PartitionSet{}))
{
localView.bind(e);
auto&& subTree = Dune::TypeTree::child(localView.tree(), treePath);
......@@ -54,7 +55,7 @@ namespace AMDiS
vector.init(false);
counter.init(true); // set to zero
for (const auto& e : elements(basis.gridView(), typename Vec::Backend::Traits::PartitionSet{}))
for (const auto& e : elements(basis.gridView(), typename BackendTraits<B>::PartitionSet{}))
{
localView.bind(e);
lf.bind(e);
......@@ -68,7 +69,7 @@ namespace AMDiS