Commit 7541665c authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

ParallelGlobalBasis derived from DefaultGlobalBasis and Comm depending on...

ParallelGlobalBasis derived from DefaultGlobalBasis and Comm depending on GlobalId and LocalIndex only
parent 54d43006
......@@ -39,6 +39,48 @@ namespace AMDiS
template <class PreBasis, class TP, class = void>
class NodeIdSet;
/// \brief Type of a global used used to represent DOFs uniquely
/**
* A global DOF id is a pair an id of the entity the DOF is related to and
* the local number on that entity. See also LocalBasisKey.
**/
template <class EntityIdType>
class GlobalIdType : public std::pair<EntityIdType, std::size_t>
{
using Super = std::pair<EntityIdType, std::size_t>;
public:
GlobalIdType(std::size_t i = 0)
: Super(EntityIdType{}, i)
{}
using Super::Super;
/// Increment the second index only
GlobalIdType& operator++()
{
++this->second;
return *this;
}
// Add to the second index only
GlobalIdType operator+(std::size_t shift) const
{
return GlobalIdType{this->first, this->second + shift};
}
friend std::ostream& operator<<(std::ostream& os, GlobalIdType const& id)
{
os << "(" << id.first << "," << id.second << ")";
return os;
}
};
template <class Basis>
using GlobalIdType_t
= GlobalIdType<typename Basis::GridView::Grid::GlobalIdSet::IdType>;
/// \brief Provide global ids for all DOFs in a global basis
/**
* A GlobalBasisIdSet provides and interface to retrieve unique IDs
......@@ -73,31 +115,7 @@ namespace AMDiS
using Element = typename GridView::template Codim<0>::Entity;
using EntityIdType = typename Grid::GlobalIdSet::IdType;
using PartitionType = Dune::PartitionType;
struct IdType : std::pair<EntityIdType, std::size_t>
{
using Super = std::pair<EntityIdType, std::size_t>;
IdType(std::size_t i = 0) : Super(EntityIdType{}, i) {};
using Super::Super;
IdType& operator++()
{
++this->second;
return *this;
}
IdType operator+(std::size_t shift) const
{
return IdType{this->first, this->second + shift};
}
friend std::ostream& operator<<(std::ostream& os, IdType const& id)
{
os << "(" << id.first << "," << id.second << ")";
return os;
}
};
using IdType = GlobalIdType_t<GB>;
using PreBasis = typename GlobalBasis::PreBasis;
using TreePath = typename GlobalBasis::PrefixPath;
......
......@@ -15,6 +15,7 @@
#include <dune/functions/common/type_traits.hh>
#include <dune/functions/functionspacebases/concepts.hh>
#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
#include <dune/functions/functionspacebases/defaultlocalview.hh>
#include <dune/functions/functionspacebases/flatmultiindex.hh>
......@@ -33,16 +34,6 @@
#include <dune/functions/functionspacebases/defaultlocalindexset.hh>
#endif
namespace Dune
{
namespace Functions
{
// Forward declaration
template <class PB>
class DefaultGlobalBasis;
}
}
namespace AMDiS
{
/**
......@@ -55,43 +46,24 @@ namespace AMDiS
*/
template <class PB>
class ParallelGlobalBasis
: public Notifier<event::adapt>
: public Dune::Functions::DefaultGlobalBasis<PB>
, public Notifier<event::adapt>
, private Observer<event::adapt>
{
using Self = ParallelGlobalBasis<PB>;
using Super = Dune::Functions::DefaultGlobalBasis<PB>;
public:
/// Pre-basis providing the implementation details
using PreBasis = PB;
/// The empty prefix path that identifies the root in the local ansatz tree
using PrefixPath = Dune::TypeTree::HybridTreePath<>;
/// The grid view that the FE space is defined on
using GridView = typename PreBasis::GridView;
using Grid = typename GridView::Grid;
/// Type used for global numbering of the basis vectors
using MultiIndex = typename PreBasis::MultiIndex;
/// Type used for indices and size information
using size_type = std::size_t;
/// Type of the local view on the restriction of the basis to a single element
using LocalView = Dune::Functions::DefaultLocalView<Self>;
/// Type used for prefixes handed to the size() method
using SizePrefix = typename PreBasis::SizePrefix;
#if DUNE_VERSION_LT(DUNE_FUNCTIONS,2,7)
/// Node index set provided by PreBasis
using NodeIndexSet = typename PreBasis::template IndexSet<PrefixPath>;
/// Type of local index set exported by localIndexSet()
using LocalIndexSet = Dune::Functions::DefaultLocalIndexSet<LocalView, NodeIndexSet>;
#endif
/// Type of the communicator
using Comm = typename BackendTraits<Self>::Comm;
......@@ -103,6 +75,7 @@ namespace AMDiS
/// Construct this global basis with given name and grid, and constructing a preBasis.
/**
* \param name Name associated with this basis for initfile parameter attachment.
* \param grid The Grid providing the GridView for this basis
* \param args... Argument list for PreBasis
*
......@@ -111,15 +84,15 @@ namespace AMDiS
template <class... Args,
Dune::Functions::enableIfConstructible<PreBasis, Args...> = 0>
ParallelGlobalBasis(std::string const& name, Grid const& grid, Args&&... args)
: Observer<event::adapt>(grid)
, preBasis_(FWD(args)...)
{
static_assert(Dune::models<Dune::Functions::Concept::PreBasis<GridView>, PreBasis>(),
"Type passed to ParallelGlobalBasis does not model the PreBasis concept.");
preBasis_.initializeIndices();
comm_ = CommunicationCreator<Comm>::create(*this, name + "->solver");
}
: Super(FWD(args)...)
, Observer<event::adapt>(grid)
, comm_([&]() {
// need to call initialize, before it can be passed to the constructor of
// a communicator.
Super::preBasis().initializeIndices();
return CommunicationCreator<Comm>::create(static_cast<Super const&>(*this), name + "->solver");
}())
{}
/// Construct this global basis with empty name
template <class... Args,
......@@ -141,24 +114,6 @@ namespace AMDiS
public:
/// Obtain the grid view that the basis is defined on
GridView const& gridView() const
{
return preBasis_.gridView();
}
/// Obtain the pre-basis providing the implementation details
PreBasis const& preBasis() const
{
return preBasis_;
}
/// Obtain the pre-basis providing the implementation details
PreBasis& preBasis()
{
return preBasis_;
}
/// \brief Update the stored grid view
/**
* This will update the indexing information of the global basis as well as the communicator.
......@@ -166,27 +121,9 @@ namespace AMDiS
*/
void update(GridView const& gv)
{
preBasis_.update(gv);
preBasis_.initializeIndices();
comm_->update(*this);
}
/// Get the total dimension of the space spanned by this basis
size_type dimension() const
{
return preBasis_.dimension();
}
/// Return number of possible values for next position in empty multi index
size_type size() const
{
return preBasis_.size();
}
/// Return number of possible values for next position in multi index
size_type size(SizePrefix const& prefix) const
{
return preBasis_.size(prefix);
Super::preBasis().update(gv);
Super::preBasis().initializeIndices();
comm_.update(*this);
}
/// Return local view for basis
......@@ -201,19 +138,13 @@ namespace AMDiS
return *this;
}
/// Return empty path, because this is the root in the local ansatz tree
PrefixPath const& prefixPath() const
{
return prefixPath_;
}
/// \brief Return the communicator.
/**
* This provides the means to communicate data associated to the basis with
* other processes.
**/
Comm const& communicator() const { return *comm_; }
Comm& communicator() { return *comm_; }
Comm const& communicator() const { return comm_; }
Comm& communicator() { return comm_; }
ADH globalRefineCallback() const
{
......@@ -223,20 +154,17 @@ namespace AMDiS
}
protected:
/// Updates the underlying basis when event::adapt is triggered by the observed grid
void updateImpl(event::adapt e) override
{
if (e.value) {
update(gridView());
this->notify(e);
update(Super::gridView());
Notifier<event::adapt>::notify(e);
}
}
protected:
PreBasis preBasis_;
PrefixPath prefixPath_ = {};
std::unique_ptr<Comm> comm_;
Comm comm_;
};
......
......@@ -35,9 +35,9 @@ namespace AMDiS
using Communication = C;
template <class Basis>
static std::unique_ptr<C> create(Basis const& basis)
static Communication create(Basis const& basis)
{
return std::make_unique<Communication>(Environment::comm());
return {Environment::comm()};
}
};
......@@ -49,7 +49,7 @@ namespace AMDiS
using Communication = C;
template <class Basis>
static std::unique_ptr<C> create(Basis const& basis, std::string const& prefix = "")
static Communication create(Basis const& basis, std::string const& prefix = "")
{
DUNE_UNUSED_PARAMETER(prefix);
return DefaultCommunicationCreator<C>::create(basis);
......
......@@ -22,7 +22,7 @@ namespace AMDiS
* required to provide the typedefs listed here.
*
* \tparam Basis A global basis from dune-functions
* \tparam T The type of the coefficients stored inthe matrix and vector
* \tparam T The type of the coefficients stored in the matrix and vector
*/
template <class Basis, class T = double>
class BackendTraits
......
......@@ -17,7 +17,7 @@
namespace AMDiS
{
/// Dummy implementation for ISTL-specific communication when no MPI is found
template <class Basis>
template <class G, class L>
class SequentialISTLCommunication
{
using Impl = Dune::Amg::SequentialInformation;
......@@ -27,6 +27,7 @@ namespace AMDiS
SequentialISTLCommunication() = default;
template <class Basis>
SequentialISTLCommunication(Basis const&, typename Dune::SolverCategory::Category cat)
{
assert(cat == Dune::SolverCategory::sequential);
......@@ -47,6 +48,7 @@ namespace AMDiS
return *this;
}
template <class Basis>
void update(Basis const&) { /* do nothing */ }
private:
......@@ -56,19 +58,18 @@ namespace AMDiS
#if HAVE_MPI
/// Implementation class for ISTL-specific communication to be used in parallel solvers
template <class Basis>
template <class GlobalId, class LocalIndex>
class ISTLCommunication
{
using GlobalId = typename GlobalBasisIdSet<Basis>::IdType;
using LocalIndex = typename Basis::size_type;
using Impl = Dune::OwnerOverlapCopyCommunication<GlobalId, LocalIndex>;
public:
using Sequential = SequentialISTLCommunication<Basis>;
using Sequential = SequentialISTLCommunication<GlobalId, LocalIndex>;
using IndexSet = typename Impl::ParallelIndexSet;
using RemoteIndices = typename Impl::RemoteIndices;
public:
template <class Basis>
ISTLCommunication(Basis const& basis, typename Dune::SolverCategory::Category cat)
: cat_(cat)
{
......@@ -103,9 +104,10 @@ namespace AMDiS
return Sequential{};
}
template <class Basis>
void update(Basis const& basis)
{
impl_.emplace(Environment::comm(), cat_);
impl_ = std::make_unique<Impl>(Environment::comm(), cat_);
auto& pis = impl_->indexSet();
buildParallelIndexSet(basis, pis);
......@@ -117,21 +119,25 @@ namespace AMDiS
private:
typename Dune::SolverCategory::Category cat_;
Dune::Std::optional<Impl> impl_ = {};
std::unique_ptr<Impl> impl_ = nullptr;
};
#else // !HAVE_MPI
template <class Basis>
using ISTLCommunication = SequentialISTLCommunication<Basis>;
template <class G, class L>
using ISTLCommunication = SequentialISTLCommunication<G,L>;
#endif
template <class B>
using ISTLCommunication_t
= ISTLCommunication<GlobalIdType_t<B>, typename B::size_type>;
template <class Basis>
struct CommunicationCreator<ISTLCommunication<Basis>>
template <class G, class L>
struct CommunicationCreator<ISTLCommunication<G,L>>
{
using Communication = ISTLCommunication<Basis>;
using Communication = ISTLCommunication<G,L>;
/**
* ISTLCommunication creator function. Takes the global basis and the solver's initfile prefix
......@@ -141,7 +147,8 @@ namespace AMDiS
* \param basis Global basis associated to the solvers' matrices and vectors
* \param prefix Solver prefix used in the initfile, usually "<problem name>->solver"
**/
static std::unique_ptr<Communication> create(Basis const& basis, std::string const& prefix = "");
template <class Basis>
static Communication create(Basis const& basis, std::string const& prefix = "");
};
} // end namespace AMDiS
......
......@@ -7,9 +7,9 @@ namespace AMDiS {
#if HAVE_MPI
template <class Basis>
std::unique_ptr<ISTLCommunication<Basis>>
CommunicationCreator<ISTLCommunication<Basis>>
template <class G, class L>
template <class Basis>
ISTLCommunication<G,L> CommunicationCreator<ISTLCommunication<G,L>>
::create(Basis const& basis, std::string const& prefix)
{
using SolverType = Dune::SolverCategory::Category;
......@@ -71,7 +71,7 @@ CommunicationCreator<ISTLCommunication<Basis>>
error_exit("Unknown solver category\n");
}
return std::make_unique<Communication>(basis, cat);
return {basis, cat};
}
#else // HAVE_MPI
......
......@@ -49,7 +49,7 @@ namespace AMDiS
using Mat = Dune::BCRSMatrix<typename BlockMatrixType<T>::type>;
using Vec = Dune::BlockVector<typename BlockVectorType<T>::type>;
using CoefficientType = T;
using Comm = ISTLCommunication<Basis>;
using Comm = ISTLCommunication_t<Basis>;
using PartitionSet = Dune::Partitions::All;
using ScalProd = Dune::ScalarProduct<Vec>;
......
......@@ -15,20 +15,19 @@
namespace AMDiS
{
template <class Basis>
template <class GlobalId, class LocalIndex>
class DistributedCommunication
{
public:
using GlobalIdType = typename GlobalBasisIdSet<Basis>::IdType;
#if HAVE_MPI
using LocalIndexType = Dune::ParallelLocalIndex<DefaultAttributeSet::Type>;
using IndexSet = Dune::ParallelIndexSet<GlobalIdType, LocalIndexType, 512>;
using LocalIndex = Dune::ParallelLocalIndex<DefaultAttributeSet::Type>;
using IndexSet = Dune::ParallelIndexSet<GlobalId, LocalIndex, 512>;
using RemoteIndices = Dune::RemoteIndices<IndexSet>;
#else
struct IndexSet
{
constexpr std::size_t size() const { return size_; }
std::size_t size_ = 0;
constexpr LocalIndex size() const { return size_; }
LocalIndex size_ = 0;
};
struct RemoteIndices {};
......@@ -36,6 +35,7 @@ namespace AMDiS
using DofMap = DofMapping<IndexSet, PetscInt>;
public:
template <class Basis>
DistributedCommunication(Basis const& basis)
{
update(basis);
......@@ -54,6 +54,7 @@ namespace AMDiS
DofMap& dofMap() { return dofMap_; }
/// Update the indexSet, remoteIndices and dofmapping
template <class Basis>
void update(Basis const& basis)
{
indexSet_.emplace();
......@@ -75,15 +76,20 @@ namespace AMDiS
DofMap dofMap_;
};
template <class B>
using DistributedCommunication_t
= DistributedCommunication<GlobalIdType_t<B>, typename B::size_type>;
template <class Basis>
struct CommunicationCreator<DistributedCommunication<Basis>>
template <class G, class L>
struct CommunicationCreator<DistributedCommunication<G,L>>
{
using Communication = DistributedCommunication<Basis>;
using Communication = DistributedCommunication<G,L>;
static std::unique_ptr<Communication> create(Basis const& basis, std::string const& prefix = "")
template <class Basis>
static Communication create(Basis const& basis, std::string const& prefix = "")
{
return std::make_unique<Communication>(basis);
return {basis};
}
};
......
......@@ -21,7 +21,7 @@ namespace AMDiS
using Mat = ::Mat;
using Vec = ::Vec;
using CoefficientType = PetscScalar;
using Comm = DistributedCommunication<Basis>;
using Comm = DistributedCommunication_t<Basis>;
using PartitionSet = Dune::Partitions::Interior;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment