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

started to rewrite Assembler using dune-functions globalBasis

parent beb6bd46
...@@ -7,6 +7,8 @@ if(NOT (dune-common_DIR OR dune-common_ROOT OR ...@@ -7,6 +7,8 @@ if(NOT (dune-common_DIR OR dune-common_ROOT OR
${PROJECT_BINARY_DIR}) ${PROJECT_BINARY_DIR})
endif() endif()
set(CXX_MAX_STANDARD 14)
#find dune-common and set the module path #find dune-common and set the module path
find_package(dune-common REQUIRED) find_package(dune-common REQUIRED)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules" list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules"
......
...@@ -6,139 +6,89 @@ ...@@ -6,139 +6,89 @@
#include <dune/common/fmatrix.hh> #include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh> #include <dune/common/fvector.hh>
#include <dune/amdis/FiniteElementSpaces.hpp>
#include <dune/amdis/LinearAlgebra.hpp> #include <dune/amdis/LinearAlgebra.hpp>
#include <dune/amdis/common/Mpl.hpp> #include <dune/amdis/common/Mpl.hpp>
#include <dune/amdis/common/TypeDefs.hpp> #include <dune/amdis/common/TypeDefs.hpp>
namespace AMDiS namespace AMDiS
{ {
template <class FeSpaces> template <class GlobalBasis>
class Assembler class Assembler
{ {
template <std::size_t I>
using FeSpace = std::tuple_element_t<I, FeSpaces>;
/// Number of problem components
static constexpr int nComponents = std::tuple_size<FeSpaces>::value;
/// The grid view the global FE basis lives on /// The grid view the global FE basis lives on
using GridView = typename FeSpace<0>::GridView; using GridView = typename GlobalBasis::GridView;
using SystemMatrixType = SystemMatrix<FeSpaces>;
using SystemVectorType = SystemVector<FeSpaces>;
template <class T>
using MatrixEntries = Dune::FieldMatrix<T, nComponents, nComponents>;
template <class T> using SystemMatrixType = SystemMatrix<GlobalBasis>;
using VectorEntries = Dune::FieldVector<T, nComponents>; using SystemVectorType = SystemVector<GlobalBasis>;
using ElementVector = Impl::ElementVector; using TypeTree = typename GlobalBasis::LocalView::Tree;
using ElementMatrix = Impl::ElementMatrix; using
public: public:
/// Constructor, stores a shared-pointer to the feSpaces /// Constructor, stores a shared-pointer to the feSpaces
Assembler(std::shared_ptr<FeSpaces> const& feSpaces, bool asmMatrix, bool asmVector) Assembler(std::shared_ptr<GlobalBasis> const& globalBasis, bool asmMatrix, bool asmVector)
: globalBases_(feSpaces) : globalBasis_(globalBasis)
, asmMatrix_(asmMatrix) , asmMatrix_(asmMatrix)
, asmVector_(asmVector) , asmVector_(asmVector)
{} {}
/// Assemble the linear system /// Assemble the linear system
template <class Operators> template <class MatrixOperators, class VectorOperators>
void assemble( void assemble(
GridView const& gv, GridView const& gv,
SystemMatrixType& matrix, SystemMatrixType& matrix,
SystemVectorType& solution, SystemVectorType& solution,
SystemVectorType& rhs, SystemVectorType& rhs,
MatrixEntries<Operators>& matrix_operators, MatrixOperators& matrixOperators,
VectorEntries<Operators>& rhs_operators); VectorOperators& rhsOperators);
private: private:
/// Sets the system to zero and initializes all operators and boundary conditions /// Sets the system to zero and initializes all operators and boundary conditions
template <class Operators> template <class MatrixOperators, class VectorOperators>
void initMatrixVector( void initMatrixVector(
SystemMatrixType& matrix, SystemMatrixType& matrix,
SystemVectorType& solution, SystemVectorType& solution,
SystemVectorType& rhs, SystemVectorType& rhs,
MatrixEntries<Operators>& matrix_operators, MatrixOperators& matrixOperators,
VectorEntries<Operators>& rhs_operators) const; VectorOperators& rhsOperators) const;
/// Assemble a block-matrix of element-matrices and return a matrix of flags, whether template <class MatrixOperators, class VectorOperators>
/// a given block has received some entries. void assembleElement(
template <class Operators> SystemMatrixType& matrix,
MatrixEntries<bool> assembleElementMatrices( SystemVectorType& rhs,
MatrixEntries<Operators>& operators, MatrixOperators& matrixOperators,
MatrixEntries<ElementMatrix>& elementMatrix) const; VectorOperators& rhsOperators) const;
/// Assemble a block-vector of element-vectors and return a vector of flags, whether
/// a given block has received some entries.
template <class Operators>
VectorEntries<bool> assembleElementVectors(
VectorEntries<Operators>& operators,
VectorEntries<ElementVector>& elementVector) const;
/// Assemble one block of the block-element-matrix template <class ElementContainer, class Container, class Operators, class... Bases>
// The MatrixData argument stores all matrix-operators void assembleElementOperators(
template <class Operators, class RowView, class ColView> ElementContainer& elementContainer,
bool assembleElementMatrix( Container& container,
Operators& operators, Operators& operators,
ElementMatrix& elementMatrix, Bases const&... subBases) const;
RowView const& rowLocalView,
ColView const& colLocalView) const;
/// Assemble one block of the block-element-vector
// The VectorData argument stores all vector-operators
template <class Operators, class RowView>
bool assembleElementVector(
Operators& operators,
ElementVector& elementVector,
RowView const& rowLocalView) const;
/// Add the block-element-matrix to the system-matrix
void addElementMatrices(
SystemMatrixType& dofmatrix,
MatrixEntries<bool> const& addMat,
MatrixEntries<ElementMatrix> const& elementMatrix) const;
/// Add the block-element-vector to the system-vector
void addElementVectors(
SystemVectorType& dofvector,
VectorEntries<bool> const& addVec,
VectorEntries<ElementVector> const& elementVector) const;
/// Finish insertion into the matrix and assembles boundary conditions /// Finish insertion into the matrix and assembles boundary conditions
/// Return the number of nonzeros assembled into the matrix /// Return the number of nonzeros assembled into the matrix
template <class Operators> template <class MatrixOperators, class VectorOperators>
std::size_t finishMatrixVector( std::size_t finishMatrixVector(
SystemMatrixType& matrix, SystemMatrixType& matrix,
SystemVectorType& solution, SystemVectorType& solution,
SystemVectorType& rhs, SystemVectorType& rhs,
MatrixEntries<Operators>& matrix_operators, MatrixOperators& matrixOperators,
VectorEntries<Operators>& rhs_operators) const; VectorOperators& rhsOperators) const;
/// Return whether the matrix-block needs to be assembled /// Return whether the matrix-block needs to be assembled
template <std::size_t R, std::size_t C, class Operators> template <class Basis0, class... Bases>
bool assembleMatrix(const index_t<R>, const index_t<C>, auto getElement(Basis0 const& basis0, Bases const&... bases) const
MatrixEntries<Operators> const& matrix_operators) const
{
return asmMatrix_ && (!matrix_operators[R][C].assembled || matrix_operators[R][C].changing);
}
/// Return whether the vector-block needs to be assembled
template <std::size_t R, class Operators>
bool assembleVector(const index_t<R>, VectorEntries<Operators> const& rhs_operators) const
{ {
return asmVector_ && (!rhs_operators[R].assembled || rhs_operators[R].changing); return basis0.localView().element();
} }
private: private:
FiniteElementSpaces<FeSpaces> globalBases_; std::shared_ptr<GlobalBasis> globalBasis_;
bool asmMatrix_; bool asmMatrix_;
bool asmVector_; bool asmVector_;
}; };
......
...@@ -2,224 +2,131 @@ ...@@ -2,224 +2,131 @@
namespace AMDiS { namespace AMDiS {
template <class FeSpaces> template <class GlobalBasis>
template <class Operators> template <class MatrixOperators, class VectorOperators>
void Assembler<FeSpaces>::assemble( void Assembler<GlobalBasis>::assemble(
GridView const& gv, GridView const& gv,
SystemMatrixType& matrix, SystemMatrixType& matrix,
SystemVectorType& solution, SystemVectorType& solution,
SystemVectorType& rhs, SystemVectorType& rhs,
MatrixEntries<Operators>& matrix_operators, MatrixOperators& matrixOperators,
VectorEntries<Operators>& rhs_operators) VectorOperators& rhsOperators)
{ {
// 1. Update global bases // 1. Update global bases
globalBases_.update(gv); globalBasis_.update(gv);
// 2. init matrix and rhs vector and initialize dirichlet boundary conditions // 2. init matrix and rhs vector and initialize dirichlet boundary conditions
initMatrixVector(matrix, solution, rhs, matrix_operators, rhs_operators); initMatrixVector(matrix, solution, rhs, matrixOperators, rhsOperators);
// 3. traverse grid and assemble operators on the elements // 3. traverse grid and assemble operators on the elements
for (auto const& element : elements(globalBases_.gridView())) for (auto const& element : elements(globalBasis_.gridView()))
{ {
globalBases_.bind(element); globalBasis_.bind(element);
assembleElement(matrix, rhs, matrixOperators, rhsOperators);
MatrixEntries<ElementMatrix> elementMatrix; globalBasis_.unbind();
VectorEntries<ElementVector> elementVector;
MatrixEntries<bool> addMat = assembleElementMatrices(matrix_operators, elementMatrix);
VectorEntries<bool> addVec = assembleElementVectors(rhs_operators, elementVector);
addElementMatrices(matrix, addMat, elementMatrix);
addElementVectors(rhs, addVec, elementVector);
globalBases_.unbind();
} }
// 4. finish matrix insertion and apply dirichlet boundary conditions // 4. finish matrix insertion and apply dirichlet boundary conditions
std::size_t nnz = finishMatrixVector(matrix, solution, rhs, matrix_operators, rhs_operators); std::size_t nnz = finishMatrixVector(matrix, solution, rhs, matrixOperators, rhsOperators);
msg("fillin of assembled matrix: ", nnz); msg("fillin of assembled matrix: ", nnz);
} }
template <class FeSpaces> template <class GlobalBasis>
template <class Operators> template <class MatrixOperators, class VectorOperators>
void Assembler<FeSpaces>::initMatrixVector( void Assembler<GlobalBasis>::initMatrixVector(
SystemMatrixType& matrix, SystemMatrixType& matrix,
SystemVectorType& solution, SystemVectorType& solution,
SystemVectorType& rhs, SystemVectorType& rhs,
MatrixEntries<Operators>& matrix_operators, MatrixOperators& matrixOperators,
VectorEntries<Operators>& rhs_operators) const VectorOperators& rhsOperators) const
{ {
forEach(range_<0, nComponents>, [&,this](auto const _r) matrix.init(globalBasis_);
{ solution.init(globalBasis_);
static const int R = decltype(_r)::value; rhs.init(globalBasis_);
auto const& rowFeSpace = globalBases_.basis(_r);
msg(rowFeSpace.size(), " DOFs for FeSpace[", R, "]");
if (this->assembleVector(_r, rhs_operators)) {
rhs.compress(_r);
rhs.getVector(_r) = 0.0;
// init vector operators
for (auto& scaled : rhs_operators[R].element)
scaled.op->init(rowFeSpace);
for (auto& scaled : rhs_operators[R].boundary)
scaled.op->init(rowFeSpace);
for (auto& scaled : rhs_operators[R].intersection)
scaled.op->init(rowFeSpace);
}
forEach(range_<0, nComponents>, [&,this](auto const _c) auto localView = globalBasis_.localView();
{ forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
static const int C = decltype(_c)::value; {
auto const& colFeSpace = globalBases_.basis(_c); if (rowNode.isLeaf)
msg(globalBasis_.size(rowTreePath), " DOFs for Basis[", Dune::TypeTree::treePathIndex(rowTreePath), "]");
bool asmMatrix = this->assembleMatrix(_r, _c, matrix_operators);
matrix(_r, _c).init(asmMatrix);
if (asmMatrix) {
// init matrix operators
for (auto& scaled : matrix_operators[R][C].element)
scaled.op->init(rowFeSpace, colFeSpace);
for (auto& scaled : matrix_operators[R][C].boundary)
scaled.op->init(rowFeSpace, colFeSpace);
for (auto& scaled : matrix_operators[R][C].intersection)
scaled.op->init(rowFeSpace, colFeSpace);
// init boundary condition
for (int c = 0; c < nComponents; ++c)
for (auto bc : matrix_operators[R][c].dirichlet)
bc->init(c == C, matrix(_r, _c), solution[_c], rhs[_r]);
}
});
});
}
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
if (rhsOperators[rowNode].assemble(asmVector_))
rhsOperators[rowNode].init(rowBasis);
template <class FeSpaces> forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
template <class Operators>
typename Assembler<FeSpaces>::template MatrixEntries<bool>
Assembler<FeSpaces>::assembleElementMatrices(
MatrixEntries<Operators>& operators,
MatrixEntries<ElementMatrix>& elementMatrix) const
{
MatrixEntries<bool> addMat;
forEach(range_<0, nComponents>, [&,this](auto const _r)
{
static const std::size_t R = decltype(_r)::value;
forEach(range_<0, nComponents>, [&,this](auto const _c)
{ {
static const std::size_t C = decltype(_c)::value; auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
if (matrixOperators[rowNode][colNode].assemble(asmMatrix_))
// assemble block of element matrix matrixOperators[rowNode][colNode].init(rowBasis, colBasis);
addMat[R][C] = this->assembleMatrix(_r, _c, operators)
? this->assembleElementMatrix(operators[R][C], elementMatrix[R][C], // init boundary condition
globalBases_.localView(_r), globalBases_.localView(_c)) // for (int c = 0; c < nComponents; ++c)
: false; // for (auto bc : matrixOperators[R][c].dirichlet)
// bc->init(c == C, matrix(_r, _c), solution[_c], rhs[_r]);
}); });
}); });
return addMat;
} }
template <class FeSpaces> template <class GlobalBasis>
template <class Operators> template <class MatrixOperators, class VectorOperators>
typename Assembler<FeSpaces>::template VectorEntries<bool> void Assembler<GlobalBasis>::assembleElement(
Assembler<FeSpaces>::assembleElementVectors( SystemMatrixType& matrix,
VectorEntries<Operators>& operators, SystemVectorType& rhs,
VectorEntries<ElementVector>& elementVector) const MatrixOperators& matrixOperators,
VectorOperators& rhsOperators) const
{ {
VectorEntries<bool> addVec; auto localView = globalBasis_.localView();
forEach(range_<0, nComponents>, [&,this](auto const _r) forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{ {
static const std::size_t R = decltype(_r)::value; auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
// assemble block of element vector
addVec[R] = this->assembleVector(_r, operators)
? this->assembleElementVector(operators[R], elementVector[R], globalBases_.localView(_r))
: false;
});
return addVec;
}
template <class FeSpaces>
template <class Operators, class RowView, class ColView>
bool Assembler<FeSpaces>::assembleElementMatrix(
Operators& operators,
ElementMatrix& elementMatrix,
RowView const& rowLocalView,
ColView const& colLocalView) const
{
if (operators.element.empty() && operators.boundary.empty() && operators.intersection.empty())
return false; // nothing to do
auto const nRows = rowLocalView.tree().finiteElement().size();
auto const nCols = colLocalView.tree().finiteElement().size();
auto const& element = rowLocalView.element(); auto& rhsOp = rhsOperators[rowNode];
auto const& gridView = rowLocalView.globalBasis().gridView(); if (rhsOp.assemble(asmVector_) && !rhsOp.empty()) {
auto elementVector = makeElementVector(rowNode);
set_to_zero(elementVector);
// fills the entire matrix with zeroes assembleElementOperators(elementVector, rhs, rhsOp, rowBasis);
elementMatrix.change_dim(nRows, nCols);
set_to_zero(elementMatrix);
bool add = false;
auto assemble_operators = [&](auto& e, auto& operator_list) {
for (auto scaled : operator_list) {
bool add_op = scaled.op->getElementMatrix(e, rowLocalView, colLocalView, elementMatrix, scaled.factor);
add = add || add_op;
} }
};
// assemble element operators forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
assemble_operators(element, operators.element); {
auto& matOp = matrixOperators[rowNode][colNode];
if (matOp.assemble(asmMatrix_) && !matOp.empty()) {
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
// assemble intersection operators auto elementMatrix = makeElementMatrix(rowNode, colNode);
if (!operators.intersection.empty() set_to_zero(elementMatrix);
|| (!operators.boundary.empty() && element.hasBoundaryIntersections()))
{
for (auto const& intersection : intersections(gridView, element)) {
if (intersection.boundary())
assemble_operators(intersection, operators.boundary);
else
assemble_operators(intersection, operators.intersection);
}
}
return add; assembleElementOperators(elementMatrix, matrix, matOp, rowBasis, colBasis);
}
});
});
} }
template <class FeSpaces> template <class GlobalBasis>
template <class Operators, class RowView> template <class ElementContainer, class Container, class Operators, class... Bases>
bool Assembler<FeSpaces>::assembleElementVector( void Assembler<GlobalBasis>::assembleElementOperators(
ElementContainer& elementContainer,
Container& container,
Operators& operators, Operators& operators,
ElementVector& elementVector, Bases const&... subBases) const
RowView const& rowLocalView) const
{ {
if (operators.element.empty() && operators.boundary.empty() && operators.intersection.empty()) if (operators.empty())
return false; return false;
auto const nRows = rowLocalView.tree().finiteElement().size(); auto const& element = getElement(subBases...);
auto const& gridView = subBasis.gridView();
auto const& element = rowLocalView.element();
auto const& gridView = rowLocalView.globalBasis().gridView();
// Set all entries to zero
elementVector.change_dim(nRows);
set_to_zero(elementVector);
bool add = false; bool add = false;
auto assemble_operators = [&](auto& e, auto& operator_list) { auto assemble_operators = [&](auto const& context, auto& operator_list) {
for (auto scaled : operator_list) { for (auto scaled : operator_list) {
bool add_op = scaled.op->getElementVector(e, rowLocalView, elementVector, scaled.factor); bool add_op = scaled.op->assemble(gridView, context, subBases.localView()..., elementContainer, scaled.factor);
add = add || add_op; add = add || add_op;
} }
}; };
...@@ -239,109 +146,50 @@ bool Assembler<FeSpaces>::assembleElementVector( ...@@ -239,109 +146,50 @@ bool Assembler<FeSpaces>::assembleElementVector(
} }
} }
return add; if (!add)
} return;
elementContainer.apply(subBases.localIndexSet()..., container);
template <class FeSpaces>
void Assembler<FeSpaces>::addElementMatrices(
SystemMatrixType& dofmatrix,
MatrixEntries<bool> const& addMat,
MatrixEntries<ElementMatrix> const& elementMatrix) const
{
forEach(range_<0, nComponents>, [&,this](auto const _r)
{
static const std::size_t R = decltype(_r)::value;
forEach(range_<0, nComponents>, [&,this](auto const _c)
{
static const std::size_t C = decltype(_c)::value;
if (!addMat[R][C])
return;
auto const& rowIndexSet = globalBases_.localIndexSet(_r);
auto const& colIndexSet = globalBases_.localIndexSet(_c);
// NOTE: current implementation does not utilize the multi-indices that we get from localIndexSet.
for (std::size_t i = 0; i < num_rows(elementMatrix[R][C]); ++i) {
// The global index of the i−th vertex of the element
auto const row = rowIndexSet.index(i);
for (std::size_t j = 0; j < num_cols(elementMatrix[R][C]); ++j) {
// The global index of the j−th vertex of the element
auto const col = colIndexSet.index(j);
dofmatrix(_r,_c)(row,col) += elementMatrix[R][C](i,j);
}