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

moved the sparsity pattern update method to the bilinear form

parent b0110464
...@@ -23,12 +23,13 @@ add_subdirectory("src") ...@@ -23,12 +23,13 @@ add_subdirectory("src")
add_subdirectory("test") add_subdirectory("test")
target_link_libraries(amdis fmt) target_link_libraries(amdis fmt)
target_compile_options(amdis PUBLIC "-Wfatal-errors" "-Wall" "-Wpedantic")
option(ENABLE_ALL_WARNINGS "enable all meaningful warnings" OFF) option(ENABLE_ALL_WARNINGS "enable all meaningful warnings" OFF)
if (ENABLE_ALL_WARNINGS) if (ENABLE_ALL_WARNINGS)
target_compile_options(amdis PUBLIC "-Wall" "-Wextra" "-pedantic" "-Wnon-virtual-dtor" target_compile_options(amdis PUBLIC "-Wextra" "-Wnon-virtual-dtor"
"-Wold-style-cast" "-Wcast-align" "-Woverloaded-virtual" "-Wold-style-cast" "-Wcast-align"
"-Wpedantic" "-Wconversion") "-Woverloaded-virtual" "-Wconversion")
endif (ENABLE_ALL_WARNINGS) endif (ENABLE_ALL_WARNINGS)
# finalize the dune project, e.g. generating config.h etc. # finalize the dune project, e.g. generating config.h etc.
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <cmath> #include <cmath>
#include <amdis/LinearAlgebra.hpp> #include <amdis/LinearAlgebra.hpp>
#include <amdis/Observer.hpp>
#include <amdis/OperatorList.hpp> #include <amdis/OperatorList.hpp>
#include <amdis/common/FlatMatrix.hpp> #include <amdis/common/FlatMatrix.hpp>
#include <amdis/common/TypeTraits.hpp> #include <amdis/common/TypeTraits.hpp>
...@@ -22,10 +23,11 @@ namespace AMDiS ...@@ -22,10 +23,11 @@ namespace AMDiS
**/ **/
template <class RB, class CB, class T = double, class Traits = BackendTraits<RB,T>> template <class RB, class CB, class T = double, class Traits = BackendTraits<RB,T>>
class BiLinearForm class BiLinearForm
: public MatrixFacade<T, typename Traits::SparsityPattern, Traits::template MatrixImpl> : public MatrixFacade<T, Traits::template MatrixImpl>
, private ObserverSequence<event::adapt,2>
{ {
using Self = BiLinearForm; using Self = BiLinearForm;
using Super = MatrixFacade<T, typename Traits::SparsityPattern, Traits::template MatrixImpl>; using Super = MatrixFacade<T, Traits::template MatrixImpl>;
public: public:
/// The type of the finite element space / basis of the row /// The type of the finite element space / basis of the row
...@@ -42,13 +44,18 @@ namespace AMDiS ...@@ -42,13 +44,18 @@ namespace AMDiS
/// The type of the matrix filled on an element with local contributions /// The type of the matrix filled on an element with local contributions
using ElementMatrix = FlatMatrix<CoefficientType>; using ElementMatrix = FlatMatrix<CoefficientType>;
/// Type of the sparsity pattern of the backend
using SparsityPattern = typename Traits::SparsityPattern;
public: public:
/// Constructor. Stores the row and column basis in a local `shared_ptr` to const /// Constructor. Stores the row and column basis in a local `shared_ptr` to const
BiLinearForm(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis) BiLinearForm(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis)
: Super(*rowBasis, *colBasis) : Super(*rowBasis, *colBasis)
, ObserverSequence<event::adapt,2>(*rowBasis, *colBasis)
, rowBasis_(rowBasis) , rowBasis_(rowBasis)
, colBasis_(colBasis) , colBasis_(colBasis)
{ {
pattern_.init(*rowBasis_, *colBasis_);
operators_.init(*rowBasis_, *colBasis_); operators_.init(*rowBasis_, *colBasis_);
auto const rowSize = rowBasis_->localView().maxSize(); auto const rowSize = rowBasis_->localView().maxSize();
...@@ -128,7 +135,34 @@ namespace AMDiS ...@@ -128,7 +135,34 @@ namespace AMDiS
/// Assemble all matrix operators, TODO: incorporate boundary conditions /// Assemble all matrix operators, TODO: incorporate boundary conditions
void assemble(SymmetryStructure symmetry = SymmetryStructure::unknown); void assemble(SymmetryStructure symmetry = SymmetryStructure::unknown);
void init(SymmetryStructure symmetry = SymmetryStructure::unknown)
{
Super::init(pattern_, symmetry);
}
using Super::init;
void updateImpl(event::adapt e, index_t<0> i) override { updateImpl2(e,i); }
void updateImpl(event::adapt e, index_t<1> i) override { updateImpl2(e,i); }
private:
// Track for each basis wether updated and if both are, update the sparsity pattern
template <std::size_t I>
void updateImpl2(event::adapt, index_t<I>)
{
assert(!updateCounter_.test(I));
updateCounter_.set(I);
if (updateCounter_.all()) {
pattern_.init(*rowBasis_, *colBasis_);
updateCounter_.reset();
}
}
protected: protected:
/// The structure of the non-zeros in the matrix
SparsityPattern pattern_;
/// Dense matrix to store coefficients during \ref assemble() /// Dense matrix to store coefficients during \ref assemble()
ElementMatrix elementMatrix_; ElementMatrix elementMatrix_;
...@@ -137,6 +171,9 @@ namespace AMDiS ...@@ -137,6 +171,9 @@ namespace AMDiS
std::shared_ptr<RowBasis const> rowBasis_; std::shared_ptr<RowBasis const> rowBasis_;
std::shared_ptr<ColBasis const> colBasis_; std::shared_ptr<ColBasis const> colBasis_;
private:
std::bitset<2> updateCounter_ = 0;
}; };
......
...@@ -145,6 +145,19 @@ namespace AMDiS ...@@ -145,6 +145,19 @@ namespace AMDiS
/// Read backup data from file /// Read backup data from file
void restore(std::string const& filename); void restore(std::string const& filename);
void resize()
{
Coefficients::resize(sizeInfo(*basis_));
}
using Coefficients::resize;
void resizeZero()
{
Coefficients::resizeZero(sizeInfo(*basis_));
}
using Coefficients::resizeZero;
/// Return the associated DataTransfer object /// Return the associated DataTransfer object
DataTransfer const& dataTransfer() const DataTransfer const& dataTransfer() const
...@@ -189,7 +202,7 @@ namespace AMDiS ...@@ -189,7 +202,7 @@ namespace AMDiS
void updateImpl(event::adapt e) override void updateImpl(event::adapt e) override
{ {
assert(e.value); assert(e.value);
this->resize(); resize();
dataTransfer_.adapt(*this); dataTransfer_.adapt(*this);
} }
......
...@@ -48,7 +48,7 @@ restore(std::string const& filename) ...@@ -48,7 +48,7 @@ restore(std::string const& filename)
// assume the order of element traversal is not changed // assume the order of element traversal is not changed
auto localView = this->basis()->localView(); auto localView = this->basis()->localView();
std::vector<value_type> data; std::vector<value_type> data;
this->init(true); this->init(sizeInfo(*this->basis()), true);
for (auto const& element : elements(this->basis()->gridView())) for (auto const& element : elements(this->basis()->gridView()))
{ {
std::uint64_t len = 0; std::uint64_t len = 0;
......
...@@ -148,7 +148,7 @@ preAdapt(C const& coeff, bool mightCoarsen) ...@@ -148,7 +148,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
template <class C, class B> template <class C, class B>
void DataTransfer<C,B>::adapt(C& coeff) void DataTransfer<C,B>::adapt(C& coeff)
{ {
coeff.init(false); coeff.resize();
test_exit(!persistentContainer_.empty(), "No data was saved before adapting the grid, make " test_exit(!persistentContainer_.empty(), "No data was saved before adapting the grid, make "
"sure to call DataTransfer::preAdapt before calling adapt() on the grid"); "sure to call DataTransfer::preAdapt before calling adapt() on the grid");
......
...@@ -20,17 +20,15 @@ namespace AMDiS ...@@ -20,17 +20,15 @@ namespace AMDiS
* Looks for the `key` in the parameter-tree and returns * Looks for the `key` in the parameter-tree and returns
* the stored and parsed value if found and parsable. * the stored and parsed value if found and parsable.
* *
* Does not thrown an exception if something goes wrong! * May throw an exception if the value can not be parsed into type T
**/ **/
template <class T> template <class T>
static Dune::Std::optional<T> get(std::string const& key) static Dune::Std::optional<T> get(std::string const& key)
{ {
try { if (pt().hasKey(key))
return pt().get<T>(key); return pt().get<T>(key);
} else
catch (...) {
return {}; return {};
}
} }
/// \brief Get parameter-values from parameter-tree with default value /// \brief Get parameter-values from parameter-tree with default value
......
...@@ -59,7 +59,7 @@ assemble() ...@@ -59,7 +59,7 @@ assemble()
{ {
auto localView = this->basis()->localView(); auto localView = this->basis()->localView();
this->init(true); this->init(sizeInfo(*this->basis()), true);
for (auto const& element : elements(this->basis()->gridView(), typename Traits::PartitionSet{})) { for (auto const& element : elements(this->basis()->gridView(), typename Traits::PartitionSet{})) {
localView.bind(element); localView.bind(element);
this->assemble(localView); this->assemble(localView);
......
...@@ -132,7 +132,7 @@ namespace AMDiS ...@@ -132,7 +132,7 @@ namespace AMDiS
return *this; return *this;
} }
/// Set the Notifier* to nullptr. Used by the Notifer to avoid segfaults when destruction occurs /// Set the Notifier* to nullptr. Used by the Notifier to avoid segfaults when destruction occurs
/// out of order. /// out of order.
void unset() final void unset() final
{ {
......
...@@ -167,7 +167,7 @@ restore(Flag initFlag) ...@@ -167,7 +167,7 @@ restore(Flag initFlag)
if (initFlag.isSet(INIT_FILEWRITER)) if (initFlag.isSet(INIT_FILEWRITER))
createFileWriter(); createFileWriter();
solution_->resize(); solution_->resize(sizeInfo(*globalBasis_));
solution_->restore(solution_filename); solution_->restore(solution_filename);
} }
...@@ -516,7 +516,7 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as ...@@ -516,7 +516,7 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
Parameters::get(name_ + "->symmetry", symmetryStr); Parameters::get(name_ + "->symmetry", symmetryStr);
systemMatrix_->init(symmetryStructure(symmetryStr)); systemMatrix_->init(symmetryStructure(symmetryStr));
rhs_->init(asmVector); rhs_->init(sizeInfo(*globalBasis_), asmVector);
// statistic about system size // statistic about system size
if (Environment::mpiSize() > 1) if (Environment::mpiSize() > 1)
...@@ -543,7 +543,7 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as ...@@ -543,7 +543,7 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
info(2," assemble operators needed {} seconds", t2.elapsed()); info(2," assemble operators needed {} seconds", t2.elapsed());
t2.reset(); t2.reset();
solution_->resize(); solution_->resize(sizeInfo(*globalBasis_));
for_each_node(localView.tree(), [&,this](auto const& rowNode, auto row_tp) -> void { for_each_node(localView.tree(), [&,this](auto const& rowNode, auto row_tp) -> void {
for_each_node(localView.tree(), [&,this](auto const& colNode, auto col_tp) -> void { for_each_node(localView.tree(), [&,this](auto const& colNode, auto col_tp) -> void {
// finish boundary condition // finish boundary condition
......
...@@ -60,7 +60,8 @@ namespace AMDiS ...@@ -60,7 +60,8 @@ namespace AMDiS
template <class... Args> template <class... Args>
constexpr explicit FakeContainer(Args&&...) noexcept {} constexpr explicit FakeContainer(Args&&...) noexcept {}
constexpr void init(bool) noexcept { /* do nothing */ } template <class S>
constexpr void init(S const&, bool) noexcept { /* do nothing */ }
constexpr void finish() noexcept { /* do nothing */ } constexpr void finish() noexcept { /* do nothing */ }
......
...@@ -53,8 +53,8 @@ namespace AMDiS ...@@ -53,8 +53,8 @@ namespace AMDiS
// Obtain a local view of f // Obtain a local view of f
auto lf = localFunction(gf); auto lf = localFunction(gf);
vector.init(false); vector.init(sizeInfo(basis), false);
counter.init(true); // set to zero counter.init(sizeInfo(basis), true); // set to zero
for (const auto& e : elements(basis.gridView(), typename BackendTraits<B>::PartitionSet{})) for (const auto& e : elements(basis.gridView(), typename BackendTraits<B>::PartitionSet{}))
{ {
localView.bind(e); localView.bind(e);
......
...@@ -22,22 +22,18 @@ namespace AMDiS ...@@ -22,22 +22,18 @@ namespace AMDiS
* \tparam Pattern The type of the sparsity pattern * \tparam Pattern The type of the sparsity pattern
* \tparam MatrixImpl A linear-algebra backend for the matrix storage * \tparam MatrixImpl A linear-algebra backend for the matrix storage
**/ **/
template <class T, class Pattern, template <class> class MatrixImpl> template <class T, template <class> class MatrixImpl>
class MatrixFacade class MatrixFacade
{ {
using Self = MatrixFacade; using Self = MatrixFacade;
using Impl = MatrixImpl<T>; using Impl = MatrixImpl<T>;
/// Type of the sparsity pattern of the backend
using SparsityPattern = Pattern;
public: public:
/// Constructor. Forwards the bases to the implementation class and /// Constructor. Forwards the bases to the implementation class and
/// constructs a matrix sparsity pattern. /// constructs a matrix sparsity pattern.
template <class RowBasis, class ColBasis> template <class RowBasis, class ColBasis>
MatrixFacade(RowBasis const& rowBasis, ColBasis const& colBasis) MatrixFacade(RowBasis const& rowBasis, ColBasis const& colBasis)
: impl_(rowBasis, colBasis) : impl_(rowBasis, colBasis)
, pattern_(rowBasis, colBasis)
{} {}
/// Return the underlying matrix backend /// Return the underlying matrix backend
...@@ -50,9 +46,10 @@ namespace AMDiS ...@@ -50,9 +46,10 @@ namespace AMDiS
* structure of the values or the sparsity pattern can be provided. * structure of the values or the sparsity pattern can be provided.
* See \ref SymmetryStructure. * See \ref SymmetryStructure.
**/ **/
void init(SymmetryStructure symmetry = SymmetryStructure::unknown) template <class SparsityPattern>
void init(SparsityPattern const& pattern, SymmetryStructure symmetry = SymmetryStructure::unknown)
{ {
impl_.init(pattern_, symmetry); impl_.init(pattern, symmetry);
} }
/// Finish the matrix insertion, e.g. cleanup or final insertion /// Finish the matrix insertion, e.g. cleanup or final insertion
...@@ -99,9 +96,6 @@ namespace AMDiS ...@@ -99,9 +96,6 @@ namespace AMDiS
protected: protected:
/// The matrix backend /// The matrix backend
Impl impl_; Impl impl_;
/// The structure of the non-zeros in the matrix
SparsityPattern pattern_;
}; };
} // end namespace AMDiS } // end namespace AMDiS
...@@ -4,27 +4,15 @@ ...@@ -4,27 +4,15 @@
#include <dune/istl/matrixindexset.hh> #include <dune/istl/matrixindexset.hh>
#include <amdis/Observer.hpp>
#include <amdis/common/Index.hpp> #include <amdis/common/Index.hpp>
namespace AMDiS namespace AMDiS
{ {
/// \brief A general sparsity pattern implementation using the full pattern of the /// \brief A general sparsity pattern implementation using the full pattern of the
/// basis by adding all local indices /// basis by adding all local indices
template <class RowBasis, class ColBasis>
class SparsityPattern class SparsityPattern
: private ObserverSequence<event::adapt,2>
{ {
public: public:
/// Constructor. Stores pointers to the passed bases.
SparsityPattern(RowBasis const& rowBasis, ColBasis const& colBasis)
: ObserverSequence<event::adapt,2>(rowBasis, colBasis)
, rowBasis_(&rowBasis)
, colBasis_(&colBasis)
{
updateImpl3();
}
/// Number of rows in the matrix /// Number of rows in the matrix
std::size_t rows() const std::size_t rows() const
{ {
...@@ -66,42 +54,17 @@ namespace AMDiS ...@@ -66,42 +54,17 @@ namespace AMDiS
pattern_.exportIdx(matrix); pattern_.exportIdx(matrix);
} }
protected:
void updateImpl(event::adapt e, index_t<0> i) override { updateImpl2(e,i); }
void updateImpl(event::adapt e, index_t<1> i) override { updateImpl2(e,i); }
private:
// Track for each basis wether updated and if both are, call updateImpl3()
template <std::size_t I>
void updateImpl2(event::adapt, index_t<I>)
{
assert(!updateCounter_.test(I));
updateCounter_.set(I);
if (updateCounter_.all()) {
updateImpl3();
updateCounter_.reset();
}
}
void updateImpl3()
{
rowBasis_ == colBasis_
? updateSameBasis()
: updateDifferentBasis();
}
// Update pattern when basis is updated. This method is called if rowBasis == colBasis. // Update pattern when basis is updated. This method is called if rowBasis == colBasis.
void updateSameBasis() template <class Basis>
void init(Basis const& basis)
{ {
rows_ = rowBasis_->dimension(); rows_ = basis.dimension();
cols_ = rows_; cols_ = rows_;
pattern_.resize(0, 0); // clear the old pattern
pattern_.resize(rows_, cols_); pattern_.resize(rows_, cols_);
auto localView = rowBasis_->localView(); auto localView = basis.localView();
for (const auto& element : elements(rowBasis_->gridView())) { for (const auto& element : elements(basis.gridView())) {
localView.bind(element); localView.bind(element);
for (std::size_t i = 0, size = localView.size(); i < size; ++i) { for (std::size_t i = 0, size = localView.size(); i < size; ++i) {
...@@ -117,15 +80,20 @@ namespace AMDiS ...@@ -117,15 +80,20 @@ namespace AMDiS
} }
// Update pattern when basis is updated. This method is called if rowBasis != colBasis. // Update pattern when basis is updated. This method is called if rowBasis != colBasis.
void updateDifferentBasis() template <class RowBasis, class ColBasis>
void init(RowBasis const& rowBasis, ColBasis const& colBasis)
{ {
rows_ = rowBasis_->dimension(); if (uintptr_t(&rowBasis) == uintptr_t(&colBasis))
cols_ = colBasis_->dimension(); return init(rowBasis);
rows_ = rowBasis.dimension();
cols_ = colBasis.dimension();
pattern_.resize(0, 0); // clear the old pattern
pattern_.resize(rows_, cols_); pattern_.resize(rows_, cols_);
auto rowLocalView = rowBasis_->localView(); auto rowLocalView = rowBasis.localView();
auto colLocalView = colBasis_->localView(); auto colLocalView = colBasis.localView();
for (const auto& element : elements(rowBasis_->gridView())) { for (const auto& element : elements(rowBasis.gridView())) {
rowLocalView.bind(element); rowLocalView.bind(element);
colLocalView.bind(element); colLocalView.bind(element);
...@@ -142,11 +110,6 @@ namespace AMDiS ...@@ -142,11 +110,6 @@ namespace AMDiS
} }
private: private:
RowBasis const* rowBasis_;
ColBasis const* colBasis_;
std::bitset<2> updateCounter_ = 0;
std::size_t rows_; std::size_t rows_;
std::size_t cols_; std::size_t cols_;
Dune::MatrixIndexSet pattern_; Dune::MatrixIndexSet pattern_;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <amdis/common/FakeContainer.hpp> #include <amdis/common/FakeContainer.hpp>
#include <amdis/common/TypeTraits.hpp> #include <amdis/common/TypeTraits.hpp>
#include <amdis/functions/NodeIndices.hpp> #include <amdis/functions/NodeIndices.hpp>
#include <amdis/functions/SizeInfo.hpp>
#include <amdis/operations/Assigner.hpp> #include <amdis/operations/Assigner.hpp>
#include <amdis/typetree/MultiIndex.hpp> #include <amdis/typetree/MultiIndex.hpp>
...@@ -57,15 +56,14 @@ namespace AMDiS ...@@ -57,15 +56,14 @@ namespace AMDiS
using size_type = typename Impl::size_type; using size_type = typename Impl::size_type;
using value_type = typename Impl::value_type; using value_type = typename Impl::value_type;
/// Constructor. Forwards the basis to the implementation class and /// Constructor. Forwards the basis to the implementation class and
/// constructs a (type-erased) size-info object. /// constructs a (type-erased) size-info object.
template <class GlobalBasis, template <class GlobalBasis,
class = void_t<decltype(std::declval<GlobalBasis>().dimension())> > class = void_t<decltype(std::declval<GlobalBasis>().dimension())> >
VectorFacade(GlobalBasis const& basis) VectorFacade(GlobalBasis const& basis)
: impl_(basis) : impl_(basis)
, sizeInfo_(sizeInfo(basis))
{ {
resizeZero(); resizeZero(sizeInfo(basis));
} }
/// Return the underlying linear algebra backend /// Return the underlying linear algebra backend
...@@ -96,22 +94,25 @@ namespace AMDiS ...@@ -96,22 +94,25 @@ namespace AMDiS
} }
/// Resize the \ref vector to the size of the \ref basis /// Resize the \ref vector to the size of the \ref basis
void resize() template <class SizeInfo>
void resize(SizeInfo const& sizeInfo)
{