Commit 7c678ccb authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Merge branch 'issue/communicator_construction' into 'master'

communicator construction

See merge request amdis/amdis-core!137
parents 54d43006 7541665c
......@@ -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;
};
......
Supports Markdown
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