Commit 5d5e8c7d authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

optimized assembler, i.e. ommit assembling of empty blocks

parent c4446c8c
Pipeline #196 failed with stage
# This file contains local changes to the doxygen configuration # This file contains local changes to the doxygen configuration
# please us '+=' to add file/directories to the lists # please us '+=' to add file/directories to the lists
FILE_PATTERNS += *.hpp \
*.cpp
HIDE_SCOPE_NAMES = YES
HIDE_UNDOC_CLASSES = NO
INTERNAL_DOCS = NO
MARKDOWN_SUPPORT = YES
EXCLUDE_SYMBOLS = AMDiS::Impl \
AMDiS::traits::Impl \
AMDiS::detail \
itl::details
PREDEFINED += HAVE_UMFPACK \
HAVE_ALBERTA \
HAVE_UG \
AMDIS_BACKEND_MTL
# The INPUT tag can be used to specify the files and/or directories that contain # The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or # documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # with spaces.
INPUT += @top_srcdir@/dune/ INPUT += @top_srcdir@/dune/amdis \
@top_srcdir@/dune/amdis/common \
@top_srcdir@/dune/amdis/utility \
@top_srcdir@/dune/amdis/linear_algebra \
@top_srcdir@/dune/amdis/linear_algebra/mtl
# see e.g. dune-grid for the examples of mainpage and modules # see e.g. dune-grid for the examples of mainpage and modules
# INPUT += @srcdir@/mainpage \ #INPUT += @srcdir@/mainpage \
# @srcdir@/modules # @srcdir@/modules
# The EXCLUDE tag can be used to specify files and/or directories that should # The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a # excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag. # subdirectory from a directory tree whose root is specified with the INPUT tag.
# EXCLUDE += @top_srcdir@/dune/amdis/test EXCLUDE += @top_srcdir@/dune/amdis/test \
@top_srcdir@/dune/amdis/linear_algebra/istl
# The EXAMPLE_PATH tag can be used to specify one or more files or # The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see # directories that contain example code fragments that are included (see
# the \include command). # the \include command).
# EXAMPLE_PATH += @top_srcdir@/src EXAMPLE_PATH += @top_srcdir@/src
# The IMAGE_PATH tag can be used to specify one or more files or # The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see # directories that contain image that are included in the documentation (see
......
...@@ -9,7 +9,7 @@ DEPENDENCIES=@REQUIRES@ ...@@ -9,7 +9,7 @@ DEPENDENCIES=@REQUIRES@
Name: @PACKAGE_NAME@ Name: @PACKAGE_NAME@
Version: @VERSION@ Version: @VERSION@
Description: amdis module Description: amdis module
URL: http://dune-project.org/ URL: http://www.github.com/spraetor
Requires: dune-common dune-geometry dune-localfunctions dune-istl dune-typetree dune-grid dune-functions Requires: dune-common dune-geometry dune-localfunctions dune-istl dune-typetree dune-grid dune-functions
Libs: -L${libdir} Libs: -L${libdir}
Cflags: -I${includedir} Cflags: -I${includedir}
...@@ -10,13 +10,28 @@ ...@@ -10,13 +10,28 @@
namespace AMDiS namespace AMDiS
{ {
/// Implements a boundary condition of Dirichlet-type.
/**
* By calling the methods \ref init() and \ref finish before and after
* assembling the system-matrix, respectively, dirichlet boundary conditions
* can be applied to the matrix and system vector. Therefore a predicate
* functions indicates the DOFs where values should be enforced and a second
* functor provided in the constructor is responsible for determining the
* values to be set at the DOFs.
*
* In the \ref finish method the matrix is called with \ref applyDirichletBC
* to erase the corresponding rows and columns for the DOF indices. This
* application of boundary conditions can be symmetric if the matrix does
* support this symmetric modification. As a result, this method returns a list
* of columns values, that should be subtracted from the rhs.
**/
template <class WorldVector> template <class WorldVector>
class DirichletBC class DirichletBC
{ {
public: public:
template <class Predicate, class Values, template <class Predicate, class Values,
class = std::enable_if_t< concepts::Functor<Predicate, bool(WorldVector)> && class = std::enable_if_t< Concepts::Functor<Predicate, bool(WorldVector)> &&
concepts::Functor<Values, double(WorldVector)> > > Concepts::Functor<Values, double(WorldVector)> > >
DirichletBC(Predicate&& predicate, Values&& values) DirichletBC(Predicate&& predicate, Values&& values)
: predicate(std::forward<Predicate>(predicate)) : predicate(std::forward<Predicate>(predicate))
, values(std::forward<Values>(values)) , values(std::forward<Values>(values))
......
/** \defgroup Common Common
*/
#pragma once #pragma once
#include <string> #include <string>
...@@ -8,26 +5,40 @@ ...@@ -8,26 +5,40 @@
#include <cmath> #include <cmath>
#include <cfloat> #include <cfloat>
#include <boost/math/special_functions/pow.hpp>
#include <dune/amdis/common/ScalarTypes.hpp>
namespace AMDiS namespace AMDiS
{ {
namespace math namespace Math
{ {
template <class T> /// Implementation of the absolute value \f$|a|\f$ of arithmetic types.
std::enable_if_t<std::is_arithmetic<T>::value, T> template <class T,
constexpr abs(T a) class = std::enable_if_t<Concepts::Arithmetic<T>> >
constexpr T abs(T a)
{ {
return a >= 0 ? a : -a; return a >= 0 ? a : -a;
} }
template <class T> /// Implementation of the square \f$ a^2 \f$ of arithmetic types.
std::enable_if_t<std::is_arithmetic<T>::value, T> template <class T,
constexpr sqr(T a) class = std::enable_if_t<Concepts::Arithmetic<T>> >
constexpr auto sqr(T a)
{ {
return a*a; return a*a;
} }
template <size_t p, class T,
class = std::enable_if_t<Concepts::Arithmetic<T>> >
constexpr auto pow(T v)
{
return boost::math::pow<p>(v);
}
/// Implementation of the minimum of two values \f$ min(a,b)\f$ of any type
/// supporting the `>` relation.
template <class T0, class T1> template <class T0, class T1>
constexpr auto min(T0 a, T1 b) constexpr auto min(T0 a, T1 b)
{ {
...@@ -35,13 +46,15 @@ namespace AMDiS ...@@ -35,13 +46,15 @@ namespace AMDiS
} }
/// Implementation of the maximum of two values \f$ max(a,b)\f$ of any type
/// supporting the `>` relation.
template <class T0, class T1> template <class T0, class T1>
constexpr auto max(T0 a, T1 b) constexpr auto max(T0 a, T1 b)
{ {
return a > b ? a : b; return a > b ? a : b;
} }
} // end namespace math } // end namespace Math
template <class T> inline void nullify(T& a) template <class T> inline void nullify(T& a)
......
...@@ -129,6 +129,9 @@ namespace AMDiS ...@@ -129,6 +129,9 @@ namespace AMDiS
} else { } else {
AMDIS_ERROR_EXIT("Construction of UGGrid without filename not yet implemented!"); AMDIS_ERROR_EXIT("Construction of UGGrid without filename not yet implemented!");
} }
AMDIS_ERROR_EXIT("No way to construct UG-Grid found");
return {};
} }
}; };
#endif #endif
......
#pragma once #pragma once
#include <list> #include <list>
#include <vector>
#include "OperatorTerm.hpp" #include <dune/amdis/OperatorTermBase.hpp>
#include "TermGenerator.hpp" #include <dune/amdis/terms/TermGenerator.hpp>
#include <dune/amdis/common/TypeDefs.hpp>
#include <dune/amdis/utility/GetDegree.hpp>
namespace AMDiS namespace AMDiS
{ {
...@@ -20,6 +24,11 @@ namespace AMDiS ...@@ -20,6 +24,11 @@ namespace AMDiS
using Self = Operator; using Self = Operator;
using OperatorTermType = OperatorTerm<MeshView>; using OperatorTermType = OperatorTerm<MeshView>;
using ElementVector = Impl::ElementVector;
using ElementMatrix = Impl::ElementMatrix;
using IdType = typename MeshView::Grid::LocalIdSet::IdType;
public: public:
/// Add coefficients for zero-order operator < c * u, v >. /// Add coefficients for zero-order operator < c * u, v >.
/// The coefficient \p c must be a scalar expression. /// The coefficient \p c must be a scalar expression.
...@@ -115,52 +124,46 @@ namespace AMDiS ...@@ -115,52 +124,46 @@ namespace AMDiS
int getQuadratureDegree(int order, FirstOrderType firstOrderType = GRD_PHI); int getQuadratureDegree(int order, FirstOrderType firstOrderType = GRD_PHI);
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
bool getElementMatrix(RowView const& rowView, bool getElementMatrix(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix,
double* factor = NULL); double* factor = NULL);
template <class RowView, class ElementVector> template <class RowView>
bool getElementVector(RowView const& rowView, bool getElementVector(RowView const& rowView,
ElementVector& elementVector, ElementVector& elementVector,
double* factor = NULL); double* factor = NULL);
protected: protected:
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
void assembleZeroOrderTerms(RowView const& rowView, void assembleZeroOrderTerms(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix);
double factor);
template <class RowView, class ElementVector> template <class RowView>
void assembleZeroOrderTerms(RowView const& rowView, void assembleZeroOrderTerms(RowView const& rowView,
ElementVector& elementVector, ElementVector& elementVector);
double factor);
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
void assembleFirstOrderTermsGrdPhi(RowView const& rowView, void assembleFirstOrderTermsGrdPhi(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix);
double factor);
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
void assembleFirstOrderTermsGrdPsi(RowView const& rowView, void assembleFirstOrderTermsGrdPsi(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix);
double factor);
template <class RowView, class ElementVector> template <class RowView>
void assembleFirstOrderTermsGrdPsi(RowView const& rowView, void assembleFirstOrderTermsGrdPsi(RowView const& rowView,
ElementVector& elementVector, ElementVector& elementVector);
double factor);
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
void assembleSecondOrderTerms(RowView const& rowView, void assembleSecondOrderTerms(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix);
double factor);
private: private:
template <class Term> template <class Term>
...@@ -179,6 +182,7 @@ namespace AMDiS ...@@ -179,6 +182,7 @@ namespace AMDiS
template <class Term, size_t I, size_t J> template <class Term, size_t I, size_t J>
Self& addSOTImpl(Term const& term, const index_<I>, const index_<J>); Self& addSOTImpl(Term const& term, const index_<I>, const index_<J>);
template <class... Args> template <class... Args>
static shared_ptr<Self> create(index_<0>, Args&&... args) static shared_ptr<Self> create(index_<0>, Args&&... args)
{ {
...@@ -197,6 +201,9 @@ namespace AMDiS ...@@ -197,6 +201,9 @@ namespace AMDiS
return sot(std::forward<Args>(args)...); return sot(std::forward<Args>(args)...);
} }
private:
template <class LocalView>
IdType getElementId(LocalView const& localView);
private: private:
/// List of all second order terms /// List of all second order terms
...@@ -213,6 +220,12 @@ namespace AMDiS ...@@ -213,6 +220,12 @@ namespace AMDiS
int psiDegree = 1; int psiDegree = 1;
int phiDegree = 1; int phiDegree = 1;
IdType lastMatrixId = 0;
IdType lastVectorId = 0;
ElementMatrix cachedElementMatrix;
ElementVector cachedElementVector;
}; };
} // end namespace AMDiS } // end namespace AMDiS
......
#pragma once #pragma once
#include <vector>
namespace AMDiS namespace AMDiS
{ {
template <class MeshView> template <class MeshView>
...@@ -11,14 +9,18 @@ namespace AMDiS ...@@ -11,14 +9,18 @@ namespace AMDiS
{ {
AMDIS_FUNCNAME("Operator::init()"); AMDIS_FUNCNAME("Operator::init()");
// const auto& rowFE = rowView.tree().finiteElement(); using IdType = typename Operator<MeshView>::IdType;
// const auto& colFE = colView.tree().finiteElement(); lastMatrixId = std::numeric_limits<IdType>::max();
lastVectorId = std::numeric_limits<IdType>::max();
// auto const& rowFE = rowView.tree().finiteElement();
// auto const& colFE = colView.tree().finiteElement();
// psiDegree = rowFE.localBasis().order(); // psiDegree = rowFE.localBasis().order();
// phiDegree = colFE.localBasis().order(); // phiDegree = colFE.localBasis().order();
psiDegree = GetDegree<RowFeSpace>::value; psiDegree = getPolynomialDegree<RowFeSpace>;
phiDegree = GetDegree<ColFeSpace>::value; phiDegree = getPolynomialDegree<ColFeSpace>;
// TODO: calc quadrature degree here. // TODO: calc quadrature degree here.
} }
...@@ -54,7 +56,20 @@ namespace AMDiS ...@@ -54,7 +56,20 @@ namespace AMDiS
template <class MeshView> template <class MeshView>
template <class RowView, class ColView, class ElementMatrix> template <class LocalView>
typename Operator<MeshView>::IdType
Operator<MeshView>::getElementId(LocalView const& localView)
{
auto const& element = localView.element();
auto const& grid = localView.globalBasis().gridView().grid();
auto const& idSet = grid.localIdSet();
return idSet.id(element);
}
template <class MeshView>
template <class RowView, class ColView>
bool Operator<MeshView>::getElementMatrix(RowView const& rowView, bool Operator<MeshView>::getElementMatrix(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix,
...@@ -67,21 +82,44 @@ namespace AMDiS ...@@ -67,21 +82,44 @@ namespace AMDiS
if (fac == 0.0) if (fac == 0.0)
return false; return false;
const auto nRows = rowView.tree().finiteElement().size();
const auto nCols = colView.tree().finiteElement().size();
auto currentId = getElementId(rowView);
bool useCachedMatrix = (lastMatrixId == currentId
&& num_rows(cachedElementMatrix) == nRows
&& num_cols(cachedElementMatrix) == nCols);
bool assign = true;
if (!useCachedMatrix) {
cachedElementMatrix.change_dim(nRows, nCols);
set_to_zero(cachedElementMatrix);
if (!zeroOrder.empty()) if (!zeroOrder.empty())
assembleZeroOrderTerms(rowView, colView, elementMatrix, fac); assembleZeroOrderTerms(rowView, colView, cachedElementMatrix);
if (!firstOrderGrdPhi.empty()) if (!firstOrderGrdPhi.empty())
assembleFirstOrderTermsGrdPhi(rowView, colView, elementMatrix, fac); assembleFirstOrderTermsGrdPhi(rowView, colView, cachedElementMatrix);
if (!firstOrderGrdPsi.empty()) if (!firstOrderGrdPsi.empty())
assembleFirstOrderTermsGrdPsi(rowView, colView, elementMatrix, fac); assembleFirstOrderTermsGrdPsi(rowView, colView, cachedElementMatrix);
if (!secondOrder.empty()) if (!secondOrder.empty())
assembleSecondOrderTerms(rowView, colView, elementMatrix, fac); assembleSecondOrderTerms(rowView, colView, cachedElementMatrix);
assign = !zeroOrder.empty() || !firstOrderGrdPhi.empty() ||
!firstOrderGrdPsi.empty() || !secondOrder.empty();
}
if (assign)
elementMatrix += fac * cachedElementMatrix;
lastMatrixId = currentId;
return true; return true;
} }
template <class MeshView> template <class MeshView>
template <class RowView, class ElementVector> template <class RowView>
bool Operator<MeshView>::getElementVector(RowView const& rowView, bool Operator<MeshView>::getElementVector(RowView const& rowView,
ElementVector& elementVector, ElementVector& elementVector,
double* factor) double* factor)
...@@ -96,21 +134,38 @@ namespace AMDiS ...@@ -96,21 +134,38 @@ namespace AMDiS
AMDIS_TEST_EXIT( firstOrderGrdPhi.empty() && secondOrder.empty(), AMDIS_TEST_EXIT( firstOrderGrdPhi.empty() && secondOrder.empty(),
"Derivatives on ansatz-functions not allowed on the vector-side!"); "Derivatives on ansatz-functions not allowed on the vector-side!");
const auto nRows = rowView.tree().finiteElement().size();
auto currentId = getElementId(rowView);
bool useCachedVector = (lastVectorId == currentId && size(cachedElementVector) == nRows);
bool assign = true;
if (!useCachedVector) {
cachedElementVector.change_dim(nRows);
set_to_zero(cachedElementVector);
if (!zeroOrder.empty()) if (!zeroOrder.empty())
assembleZeroOrderTerms(rowView, elementVector, fac); assembleZeroOrderTerms(rowView, cachedElementVector);
if (!firstOrderGrdPsi.empty()) if (!firstOrderGrdPsi.empty())
assembleFirstOrderTermsGrdPsi(rowView, elementVector, fac); assembleFirstOrderTermsGrdPsi(rowView, cachedElementVector);
assign = !zeroOrder.empty() || !firstOrderGrdPsi.empty();
}
if (assign)
elementVector += fac * cachedElementVector;
lastVectorId = currentId;
return true; return true;
} }
template <class MeshView> template <class MeshView>
template <class RowView, class ColView, class ElementMatrix> template <class RowView, class ColView>
void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView, void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView,
ColView const& colView, ColView const& colView,
ElementMatrix& elementMatrix, ElementMatrix& elementMatrix)
double factor)
{ {
AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementMatrix)"); AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementMatrix)");
...@@ -119,11 +174,11 @@ namespace AMDiS ...@@ -119,11 +174,11 @@ namespace AMDiS
const int dim = Element::dimension; const int dim = Element::dimension;
auto geometry = element.geometry(); auto geometry = element.geometry();
const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis();
const auto& colLocalBasis = colView.tree().finiteElement().localBasis(); auto const& colLocalBasis = colView.tree().finiteElement().localBasis();
int order = getQuadratureDegree(0); int order = getQuadratureDegree(0);
const auto& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), order); auto const& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), order);
for (auto* operatorTerm : zeroOrder) for (auto* operatorTerm : zeroOrder)
operatorTerm->init(element, quad); operatorTerm->init(element, quad);
...@@ -133,7 +188,7 @@ namespace AMDiS ...@@ -133,7 +188,7 @@ namespace AMDiS
const Dune::FieldVector<double,dim>& quadPos = quad[iq].position(); const Dune::FieldVector<double,dim>& quadPos = quad[iq].position();