diff --git a/doc/doxygen/Doxylocal b/doc/doxygen/Doxylocal index c222d6b5c15445d47c50ab68cfca74d9a089e70b..46c6ffc56e3feacfe289982244995b54ae226876 100644 --- a/doc/doxygen/Doxylocal +++ b/doc/doxygen/Doxylocal @@ -1,27 +1,50 @@ # This file contains local changes to the doxygen configuration # 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 # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # 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 -# INPUT += @srcdir@/mainpage \ -# @srcdir@/modules +#INPUT += @srcdir@/mainpage \ +# @srcdir@/modules # 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 # 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 # directories that contain example code fragments that are included (see # 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 # directories that contain image that are included in the documentation (see diff --git a/dune-amdis.pc.in b/dune-amdis.pc.in index 81ec962ed91025de68e4548e5114de4f406781e2..03b2511183256c5e3590b1d13ce0771a9ee8f9a0 100644 --- a/dune-amdis.pc.in +++ b/dune-amdis.pc.in @@ -9,7 +9,7 @@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ 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 Libs: -L${libdir} Cflags: -I${includedir} diff --git a/dune/amdis/DirichletBC.hpp b/dune/amdis/DirichletBC.hpp index 2769429469a117be547e2472a4495a36db1599f1..33148455794d132e9b6cc581b81580cc463c59fb 100644 --- a/dune/amdis/DirichletBC.hpp +++ b/dune/amdis/DirichletBC.hpp @@ -10,13 +10,28 @@ 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> class DirichletBC { public: template <class Predicate, class Values, - class = std::enable_if_t< concepts::Functor<Predicate, bool(WorldVector)> && - concepts::Functor<Values, double(WorldVector)> > > + class = std::enable_if_t< Concepts::Functor<Predicate, bool(WorldVector)> && + Concepts::Functor<Values, double(WorldVector)> > > DirichletBC(Predicate&& predicate, Values&& values) : predicate(std::forward<Predicate>(predicate)) , values(std::forward<Values>(values)) diff --git a/dune/amdis/Math.hpp b/dune/amdis/Math.hpp index bc6e353fbec7717321137f9d1a5e167d667a8eb5..962571e1594f8d51138a8a0805dd700fff8d6f31 100644 --- a/dune/amdis/Math.hpp +++ b/dune/amdis/Math.hpp @@ -1,6 +1,3 @@ -/** \defgroup Common Common - */ - #pragma once #include <string> @@ -8,26 +5,40 @@ #include <cmath> #include <cfloat> +#include <boost/math/special_functions/pow.hpp> + +#include <dune/amdis/common/ScalarTypes.hpp> + namespace AMDiS { - namespace math + namespace Math { - template <class T> - std::enable_if_t<std::is_arithmetic<T>::value, T> - constexpr abs(T a) + /// Implementation of the absolute value \f$|a|\f$ of arithmetic types. + template <class T, + class = std::enable_if_t<Concepts::Arithmetic<T>> > + constexpr T abs(T a) { return a >= 0 ? a : -a; } - template <class T> - std::enable_if_t<std::is_arithmetic<T>::value, T> - constexpr sqr(T a) + /// Implementation of the square \f$ a^2 \f$ of arithmetic types. + template <class T, + class = std::enable_if_t<Concepts::Arithmetic<T>> > + constexpr auto sqr(T 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> constexpr auto min(T0 a, T1 b) { @@ -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> constexpr auto max(T0 a, T1 b) { return a > b ? a : b; } - } // end namespace math + } // end namespace Math template <class T> inline void nullify(T& a) diff --git a/dune/amdis/Mesh.hpp b/dune/amdis/Mesh.hpp index 53fe71de4ccbfc46da0710f5326763aed57834b0..2b7e3846688c9c9e51c625fe5b4cef1a64809a3e 100644 --- a/dune/amdis/Mesh.hpp +++ b/dune/amdis/Mesh.hpp @@ -129,6 +129,9 @@ namespace AMDiS } else { AMDIS_ERROR_EXIT("Construction of UGGrid without filename not yet implemented!"); } + + AMDIS_ERROR_EXIT("No way to construct UG-Grid found"); + return {}; } }; #endif diff --git a/dune/amdis/Operator.hpp b/dune/amdis/Operator.hpp index ba8faf9c19a9b763b574b8b4c6387e40add1f7c8..64249eff44ac6d1f3629698c8237f287ebc24cdd 100644 --- a/dune/amdis/Operator.hpp +++ b/dune/amdis/Operator.hpp @@ -1,9 +1,13 @@ #pragma once #include <list> +#include <vector> -#include "OperatorTerm.hpp" -#include "TermGenerator.hpp" +#include <dune/amdis/OperatorTermBase.hpp> +#include <dune/amdis/terms/TermGenerator.hpp> + +#include <dune/amdis/common/TypeDefs.hpp> +#include <dune/amdis/utility/GetDegree.hpp> namespace AMDiS { @@ -19,6 +23,11 @@ namespace AMDiS { using Self = Operator; using OperatorTermType = OperatorTerm<MeshView>; + + using ElementVector = Impl::ElementVector; + using ElementMatrix = Impl::ElementMatrix; + + using IdType = typename MeshView::Grid::LocalIdSet::IdType; public: /// Add coefficients for zero-order operator < c * u, v >. @@ -115,52 +124,46 @@ namespace AMDiS 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, ColView const& colView, ElementMatrix& elementMatrix, double* factor = NULL); - template <class RowView, class ElementVector> + template <class RowView> bool getElementVector(RowView const& rowView, ElementVector& elementVector, double* factor = NULL); protected: - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void assembleZeroOrderTerms(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor); + ElementMatrix& elementMatrix); - template <class RowView, class ElementVector> + template <class RowView> void assembleZeroOrderTerms(RowView const& rowView, - ElementVector& elementVector, - double factor); + ElementVector& elementVector); - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void assembleFirstOrderTermsGrdPhi(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor); + ElementMatrix& elementMatrix); - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void assembleFirstOrderTermsGrdPsi(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor); + ElementMatrix& elementMatrix); - template <class RowView, class ElementVector> + template <class RowView> void assembleFirstOrderTermsGrdPsi(RowView const& rowView, - ElementVector& elementVector, - double factor); + ElementVector& elementVector); - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void assembleSecondOrderTerms(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor); + ElementMatrix& elementMatrix); private: template <class Term> @@ -179,6 +182,7 @@ namespace AMDiS template <class Term, size_t I, size_t J> Self& addSOTImpl(Term const& term, const index_<I>, const index_<J>); + template <class... Args> static shared_ptr<Self> create(index_<0>, Args&&... args) { @@ -197,6 +201,9 @@ namespace AMDiS return sot(std::forward<Args>(args)...); } + private: + template <class LocalView> + IdType getElementId(LocalView const& localView); private: /// List of all second order terms @@ -213,6 +220,12 @@ namespace AMDiS int psiDegree = 1; int phiDegree = 1; + + IdType lastMatrixId = 0; + IdType lastVectorId = 0; + + ElementMatrix cachedElementMatrix; + ElementVector cachedElementVector; }; } // end namespace AMDiS diff --git a/dune/amdis/Operator.inc.hpp b/dune/amdis/Operator.inc.hpp index 5e6859f4f2425c34ff215cf872b3307de5fa3aa3..e7d4f8cc03545053fb05fe1d5fbedeb88a31423d 100644 --- a/dune/amdis/Operator.inc.hpp +++ b/dune/amdis/Operator.inc.hpp @@ -1,7 +1,5 @@ #pragma once -#include <vector> - namespace AMDiS { template <class MeshView> @@ -11,14 +9,18 @@ namespace AMDiS { AMDIS_FUNCNAME("Operator::init()"); -// const auto& rowFE = rowView.tree().finiteElement(); -// const auto& colFE = colView.tree().finiteElement(); + using IdType = typename Operator<MeshView>::IdType; + 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(); // phiDegree = colFE.localBasis().order(); - psiDegree = GetDegree<RowFeSpace>::value; - phiDegree = GetDegree<ColFeSpace>::value; + psiDegree = getPolynomialDegree<RowFeSpace>; + phiDegree = getPolynomialDegree<ColFeSpace>; // TODO: calc quadrature degree here. } @@ -52,9 +54,22 @@ namespace AMDiS return psiDegree + phiDegree - order + maxTermDegree; } + + template <class MeshView> + 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, class ElementMatrix> + template <class RowView, class ColView> bool Operator<MeshView>::getElementMatrix(RowView const& rowView, ColView const& colView, ElementMatrix& elementMatrix, @@ -67,21 +82,44 @@ namespace AMDiS if (fac == 0.0) return false; - if (!zeroOrder.empty()) - assembleZeroOrderTerms(rowView, colView, elementMatrix, fac); - if (!firstOrderGrdPhi.empty()) - assembleFirstOrderTermsGrdPhi(rowView, colView, elementMatrix, fac); - if (!firstOrderGrdPsi.empty()) - assembleFirstOrderTermsGrdPsi(rowView, colView, elementMatrix, fac); - if (!secondOrder.empty()) - assembleSecondOrderTerms(rowView, colView, elementMatrix, fac); + 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()) + assembleZeroOrderTerms(rowView, colView, cachedElementMatrix); + if (!firstOrderGrdPhi.empty()) + assembleFirstOrderTermsGrdPhi(rowView, colView, cachedElementMatrix); + if (!firstOrderGrdPsi.empty()) + assembleFirstOrderTermsGrdPsi(rowView, colView, cachedElementMatrix); + if (!secondOrder.empty()) + assembleSecondOrderTerms(rowView, colView, cachedElementMatrix); + + assign = !zeroOrder.empty() || !firstOrderGrdPhi.empty() || + !firstOrderGrdPsi.empty() || !secondOrder.empty(); + } + + if (assign) + elementMatrix += fac * cachedElementMatrix; + + lastMatrixId = currentId; return true; } template <class MeshView> - template <class RowView, class ElementVector> + template <class RowView> bool Operator<MeshView>::getElementVector(RowView const& rowView, ElementVector& elementVector, double* factor) @@ -96,21 +134,38 @@ namespace AMDiS AMDIS_TEST_EXIT( firstOrderGrdPhi.empty() && secondOrder.empty(), "Derivatives on ansatz-functions not allowed on the vector-side!"); - if (!zeroOrder.empty()) - assembleZeroOrderTerms(rowView, elementVector, fac); - if (!firstOrderGrdPsi.empty()) - assembleFirstOrderTermsGrdPsi(rowView, elementVector, fac); + 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()) + assembleZeroOrderTerms(rowView, cachedElementVector); + if (!firstOrderGrdPsi.empty()) + assembleFirstOrderTermsGrdPsi(rowView, cachedElementVector); + + assign = !zeroOrder.empty() || !firstOrderGrdPsi.empty(); + } + + if (assign) + elementVector += fac * cachedElementVector; + + lastVectorId = currentId; return true; } template <class MeshView> - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor) + ElementMatrix& elementMatrix) { AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementMatrix)"); @@ -119,11 +174,11 @@ namespace AMDiS const int dim = Element::dimension; auto geometry = element.geometry(); - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); - const auto& colLocalBasis = colView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); + auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); 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) operatorTerm->init(element, quad); @@ -133,7 +188,7 @@ namespace AMDiS const Dune::FieldVector<double,dim>& quadPos = quad[iq].position(); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); std::vector<Dune::FieldVector<double,1> > rowShapeValues, colShapeValues; rowLocalBasis.evaluateFunction(quadPos, rowShapeValues); @@ -143,14 +198,13 @@ namespace AMDiS else colLocalBasis.evaluateFunction(quadPos, colShapeValues); - for (size_t i = 0; i < elementMatrix.N(); ++i) { - for (size_t j = 0; j < elementMatrix.M(); ++j) { + for (size_t i = 0; i < num_rows(elementMatrix); ++i) { + for (size_t j = 0; j < num_cols(elementMatrix); ++j) { const int local_i = rowView.tree().localIndex(i); const int local_j = colView.tree().localIndex(j); for (auto* operatorTerm : zeroOrder) elementMatrix[local_i][local_j] - += operatorTerm->evalZot(iq, rowShapeValues[i], colShapeValues[j]) - * quad[iq].weight() * integrationElement; + += operatorTerm->evalZot(iq, rowShapeValues[i], colShapeValues[j]) * factor; } } } @@ -159,10 +213,9 @@ namespace AMDiS template <class MeshView> - template <class RowView, class ElementVector> + template <class RowView> void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView, - ElementVector& elementvector, - double factor) + ElementVector& elementvector) { AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementvector)"); @@ -171,41 +224,40 @@ namespace AMDiS const int dim = Element::dimension; auto geometry = element.geometry(); - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); 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) operatorTerm->init(element, quad); + + for (size_t iq = 0; iq < quad.size(); ++iq) { // Position of the current quadrature point in the reference element const Dune::FieldVector<double,dim>& quadPos = quad[iq].position(); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); std::vector<Dune::FieldVector<double,1> > rowShapeValues; rowLocalBasis.evaluateFunction(quadPos, rowShapeValues); - for (size_t i = 0; i < elementvector.size(); ++i) { + for (size_t i = 0; i < size(elementvector); ++i) { const int local_i = rowView.tree().localIndex(i); for (auto* operatorTerm : zeroOrder) - elementvector[local_i] - += operatorTerm->evalZot(iq, rowShapeValues[i]) - * quad[iq].weight() * integrationElement; + elementvector[local_i] += operatorTerm->evalZot(iq, rowShapeValues[i]) * factor; } } } template <class MeshView> - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void Operator<MeshView>::assembleFirstOrderTermsGrdPhi(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor) + ElementMatrix& elementMatrix) { AMDIS_FUNCNAME("Operator::assembleFirstOrderTermsGrdPhi(elementMatrix)"); @@ -214,15 +266,17 @@ namespace AMDiS auto geometry = element.geometry(); const int dim = Element::dimension; - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); - const auto& colLocalBasis = colView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); + auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); int order = getQuadratureDegree(2); - 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 : firstOrderGrdPhi) operatorTerm->init(element, quad); + + for (size_t iq = 0; iq < quad.size(); ++iq) { // Position of the current quadrature point in the reference element const Dune::FieldVector<double,dim>& quadPos = quad[iq].position(); @@ -231,7 +285,7 @@ namespace AMDiS const auto jacobian = geometry.jacobianInverseTransposed(quadPos); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); std::vector<Dune::FieldVector<double,1> > rowShapeValues; rowLocalBasis.evaluateFunction(quadPos, rowShapeValues); @@ -246,14 +300,13 @@ namespace AMDiS for (size_t i = 0; i < colGradients.size(); ++i) jacobian.mv(colReferenceGradients[i][0], colGradients[i]); - for (size_t i = 0; i < elementMatrix.N(); ++i) { - for (size_t j = 0; j < elementMatrix.M(); ++j) { + for (size_t i = 0; i < num_rows(elementMatrix); ++i) { + for (size_t j = 0; j < num_cols(elementMatrix); ++j) { const int local_i = rowView.tree().localIndex(i); const int local_j = colView.tree().localIndex(j); for (auto* operatorTerm : firstOrderGrdPhi) elementMatrix[local_i][local_j] - += operatorTerm->evalFot1(iq, rowShapeValues[i], colGradients[j]) - * quad[iq].weight() * integrationElement; + += operatorTerm->evalFot1(iq, rowShapeValues[i], colGradients[j]) * factor; } } } @@ -261,11 +314,10 @@ namespace AMDiS template <class MeshView> - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void Operator<MeshView>::assembleFirstOrderTermsGrdPsi(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor) + ElementMatrix& elementMatrix) { AMDIS_FUNCNAME("Operator::assembleFirstOrderTermsGrdPsi(elementMatrix)"); @@ -274,11 +326,11 @@ namespace AMDiS auto geometry = element.geometry(); const int dim = Element::dimension; - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); - const auto& colLocalBasis = colView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); + auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); int order = getQuadratureDegree(2); - 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 : firstOrderGrdPsi) operatorTerm->init(element, quad); @@ -291,7 +343,7 @@ namespace AMDiS const auto jacobian = geometry.jacobianInverseTransposed(quadPos); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); // The gradients of the shape functions on the reference element std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients; @@ -306,14 +358,13 @@ namespace AMDiS std::vector<Dune::FieldVector<double,1> > colShapeValues; colLocalBasis.evaluateFunction(quadPos, colShapeValues); - for (size_t i = 0; i < elementMatrix.N(); ++i) { - for (size_t j = 0; j < elementMatrix.M(); ++j) { + for (size_t i = 0; i < num_rows(elementMatrix); ++i) { + for (size_t j = 0; j < num_cols(elementMatrix); ++j) { const int local_i = rowView.tree().localIndex(i); const int local_j = colView.tree().localIndex(j); for (auto* operatorTerm : firstOrderGrdPsi) elementMatrix[local_i][local_j] - += operatorTerm->evalFot2(iq, rowGradients[i], colShapeValues[j]) - * quad[iq].weight() * integrationElement; + += operatorTerm->evalFot2(iq, rowGradients[i], colShapeValues[j]) * factor; } } } @@ -322,10 +373,9 @@ namespace AMDiS template <class MeshView> - template <class RowView, class ElementVector> + template <class RowView> void Operator<MeshView>::assembleFirstOrderTermsGrdPsi(RowView const& rowView, - ElementVector& elementvector, - double factor) + ElementVector& elementvector) { AMDIS_FUNCNAME("Operator::assembleFirstOrderTermsGrdPsi(elementvector)"); @@ -334,10 +384,10 @@ namespace AMDiS const int dim = Element::dimension; auto geometry = element.geometry(); - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); 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 : firstOrderGrdPsi) operatorTerm->init(element, quad); @@ -350,7 +400,7 @@ namespace AMDiS const auto jacobian = geometry.jacobianInverseTransposed(quadPos); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); // The gradients of the shape functions on the reference element std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients; @@ -362,23 +412,20 @@ namespace AMDiS for (size_t i = 0; i < rowGradients.size(); ++i) jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]); - for (size_t i = 0; i < elementvector.size(); ++i) { + for (size_t i = 0; i < size(elementvector); ++i) { const int local_i = rowView.tree().localIndex(i); for (auto* operatorTerm : firstOrderGrdPsi) - elementvector[local_i] - += operatorTerm->evalFot2(iq, rowGradients[i]) - * quad[iq].weight() * integrationElement; + elementvector[local_i] += operatorTerm->evalFot2(iq, rowGradients[i]) * factor; } } } template <class MeshView> - template <class RowView, class ColView, class ElementMatrix> + template <class RowView, class ColView> void Operator<MeshView>::assembleSecondOrderTerms(RowView const& rowView, ColView const& colView, - ElementMatrix& elementMatrix, - double factor) + ElementMatrix& elementMatrix) { AMDIS_FUNCNAME("Operator::assembleSecondOrderTerms(elementMatrix)"); @@ -387,11 +434,11 @@ namespace AMDiS const int dim = Element::dimension; auto geometry = element.geometry(); - const auto& rowLocalBasis = rowView.tree().finiteElement().localBasis(); -// const auto& colLocalBasis = colView.tree().finiteElement().localBasis(); + auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis(); +// auto const& colLocalBasis = colView.tree().finiteElement().localBasis(); int order = getQuadratureDegree(2); - 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 : secondOrder) operatorTerm->init(element, quad); @@ -407,7 +454,7 @@ namespace AMDiS const auto jacobian = geometry.jacobianInverseTransposed(quadPos); // The multiplicative factor in the integral transformation formula - const double integrationElement = geometry.integrationElement(quadPos) * factor; + const double factor = geometry.integrationElement(quadPos) * quad[iq].weight(); // The gradients of the shape functions on the reference element std::vector<Dune::FieldMatrix<double,1,dim> > referenceGradients; @@ -419,14 +466,13 @@ namespace AMDiS for (size_t i = 0; i < gradients.size(); ++i) jacobian.mv(referenceGradients[i][0], gradients[i]); - for (size_t i = 0; i < elementMatrix.N(); ++i) { - for (size_t j = 0; j < elementMatrix.M(); ++j) { + for (size_t i = 0; i < num_rows(elementMatrix); ++i) { + for (size_t j = 0; j < num_cols(elementMatrix); ++j) { const int local_i = rowView.tree().localIndex(i); const int local_j = colView.tree().localIndex(j); for (auto* operatorTerm : secondOrder) elementMatrix[local_i][local_j] - += operatorTerm->evalSot(iq, gradients[i], gradients[j]) - * quad[iq].weight() * integrationElement; + += operatorTerm->evalSot(iq, gradients[i], gradients[j]) * factor; } } } diff --git a/dune/amdis/OperatorTermBase.hpp b/dune/amdis/OperatorTermBase.hpp index e6c8b3a4d32c367e05b3af4ff64d1110238582ac..6d12a92ac1eefea1287501e0a893cd31f387ec6c 100644 --- a/dune/amdis/OperatorTermBase.hpp +++ b/dune/amdis/OperatorTermBase.hpp @@ -1,5 +1,9 @@ #pragma once +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <vector> #include <type_traits> @@ -11,6 +15,7 @@ namespace AMDiS { + /// Abstract base class of all operator terms template <class MeshView> class OperatorTerm { diff --git a/dune/amdis/ProblemStat.hpp b/dune/amdis/ProblemStat.hpp index 0bddf047dbf511fcf97c5e66e0926531ecaf08d2..a8147fcb99c3f949a9214c5584e81fcc6cef422b 100644 --- a/dune/amdis/ProblemStat.hpp +++ b/dune/amdis/ProblemStat.hpp @@ -1,5 +1,9 @@ #pragma once +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <tuple> #include <string> #include <memory> @@ -19,10 +23,12 @@ #include <dune/amdis/Mesh.hpp> #include <dune/amdis/Operator.hpp> #include <dune/amdis/ProblemStatBase.hpp> +#include <dune/amdis/ProblemStatTraits.hpp> #include <dune/amdis/StandardProblemIteration.hpp> #include <dune/amdis/common/Timer.hpp> #include <dune/amdis/common/TupleUtility.hpp> +#include <dune/amdis/common/TypeDefs.hpp> #include <dune/amdis/common/Utility.hpp> namespace AMDiS @@ -42,8 +48,8 @@ namespace AMDiS using Codim0 = typename MeshView::template Codim<0>; using Element = typename Codim0::Entity; - using ElementVector = Dune::BlockVector<Dune::FieldVector<double,1> >; - using ElementMatrix = Dune::Matrix<Dune::FieldMatrix<double,1,1> >; + using ElementVector = Impl::ElementVector; + using ElementMatrix = Impl::ElementMatrix; /// Dimension of the mesh @@ -53,7 +59,7 @@ namespace AMDiS static constexpr int dow = Traits::dimworld; /// Number of problem components - static constexpr size_t nComponents = Traits::nComponents; + static constexpr int nComponents = Traits::nComponents; template <size_t I> @@ -96,7 +102,8 @@ namespace AMDiS Flag adoptFlag = INIT_NOTHING); - /// Adds an operator to \ref A. + /// Adds an operator to \ref A. + /** @{ */ void addMatrixOperator(OperatorType& op, int i, int j, double* factor = NULL, @@ -107,9 +114,15 @@ namespace AMDiS double* factor = NULL, double* estFactor = NULL); - void addMatrixOperator(std::map< std::pair<int,int>, shared_ptr<OperatorType> > ops); + void addMatrixOperator(std::map< std::pair<int,int>, + shared_ptr<OperatorType> > ops); + void addMatrixOperator(std::map< std::pair<int,int>, + std::pair<shared_ptr<OperatorType>, bool> > ops); + /** @} */ - /// Adds an operator to \ref rhs. + + /// Adds an operator to \ref rhs. + /** @{ */ void addVectorOperator(OperatorType& op, int i, double* factor = NULL, @@ -120,8 +133,11 @@ namespace AMDiS double* factor = NULL, double* estFactor = NULL); - void addVectorOperator(std::map< int, shared_ptr<OperatorType> > ops); - + void addVectorOperator(std::map< int, + shared_ptr<OperatorType> > ops); + void addVectorOperator(std::map< int, + std::pair<shared_ptr<OperatorType>, bool> > ops); + /** @} */ /// Adds a Dirichlet boundary condition template <class Predicate, class Values> @@ -149,7 +165,7 @@ namespace AMDiS public: // get-methods /// Returns nr of components \ref nComponents - static constexpr size_t getNumComponents() + static constexpr int getNumComponents() { return nComponents; } @@ -264,8 +280,8 @@ namespace AMDiS template <class Matrix, class Vector> void assemble(std::pair<int, int> row_col, - Matrix* matrix, - Vector* rhs); + Matrix& matrix, bool asmMatrix, + Vector& rhs, bool asmVector); template <class RowView, class ColView> bool getElementMatrix(RowView const& rowView, @@ -357,11 +373,15 @@ namespace AMDiS /// each matrix block MatrixEntries<shared_ptr<OperatorType>> matrixOperators; MatrixEntries<double*> matrixFactors; + std::map< std::pair<int,int>, bool > matrixAssembled; // if false, do reassemble + std::map< std::pair<int,int>, bool > matrixChanging; // if true, or vectorAssembled false, do reassemble /// A map (i) -> list<OperatorType> string the differential operators for /// each rhs block VectorEntries<shared_ptr<OperatorType>> vectorOperators; VectorEntries<double*> vectorFactors; + std::map< int, bool > vectorAssembled; // if false, do reassemble + std::map< int, bool > vectorChanging; // if true, or vectorAssembled false, do reassemble }; diff --git a/dune/amdis/ProblemStat.inc.hpp b/dune/amdis/ProblemStat.inc.hpp index 339955c17e1b7bf5ff17a5a720c0b487588e4f47..73274b8e8d0045d685e5eb8023aec37fce46cbbe 100644 --- a/dune/amdis/ProblemStat.inc.hpp +++ b/dune/amdis/ProblemStat.inc.hpp @@ -117,6 +117,7 @@ namespace AMDiS matrixOperators[{i,j}].push_back(op); matrixFactors[{i,j}].push_back(factor); + matrixChanging[{i,j}] = true; } @@ -135,6 +136,17 @@ namespace AMDiS for (auto op : ops) addMatrixOperator(op.second, op.first.first, op.first.second); } + + template <class Traits> + void ProblemStatSeq<Traits>::addMatrixOperator(std::map< std::pair<int,int>, std::pair<shared_ptr<OperatorType>,bool> > ops) + { + for (auto op : ops) { + auto row_col = op.first; + matrixOperators[row_col].push_back(op.second.first); + matrixFactors[row_col].push_back(NULL); + matrixChanging[row_col] = matrixChanging[row_col] || op.second.second; + } + } template <class Traits> void ProblemStatSeq<Traits>::addVectorOperator(shared_ptr<OperatorType> op, @@ -147,6 +159,7 @@ namespace AMDiS vectorOperators[i].push_back(op); vectorFactors[i].push_back(factor); + vectorChanging[i] = true; } template <class Traits> @@ -157,7 +170,6 @@ namespace AMDiS { addVectorOperator(make_shared<OperatorType>(op), i, factor, estFactor); } - template <class Traits> void ProblemStatSeq<Traits>::addVectorOperator(std::map< int, shared_ptr<OperatorType> > ops) @@ -166,6 +178,16 @@ namespace AMDiS addVectorOperator(op.second, op.first); } + template <class Traits> + void ProblemStatSeq<Traits>::addVectorOperator(std::map< int, std::pair<shared_ptr<OperatorType>, bool> > ops) + { + for (auto op : ops) { + vectorOperators[op.first].push_back(op.second.first); + vectorFactors[op.first].push_back(NULL); + vectorChanging[op.first] = vectorChanging[op.first] || op.second.second; + } + } + /// Adds a Dirichlet boundary condition template <class Traits> template <class Predicate, class Values> @@ -173,10 +195,10 @@ namespace AMDiS int row, int col, Values const& values) { - static_assert(Dune::Functions::Concept::isCallable<Predicate, WorldVector>(), + static_assert( Concepts::Callable<Predicate, WorldVector>, "Function passed to addDirichletBC for predicate does not model the Callable<WorldVector> concept"); - static_assert(Dune::Functions::Concept::isCallable<Values, WorldVector>(), + static_assert( Concepts::Callable<Values, WorldVector>, "Function passed to addDirichletBC for values does not model the Callable<WorldVector> concept"); AMDIS_TEST_EXIT(row >= 0 && row < nComponents, "row number out of range: " << row); @@ -232,7 +254,7 @@ namespace AMDiS template <class Traits> void ProblemStatSeq<Traits>::buildAfterCoarsen(AdaptInfo& /*adaptInfo*/, Flag flag, - bool asmMatrix, bool asmVector) + bool asmMatrix_, bool asmVector_) { Timer t; @@ -242,25 +264,29 @@ namespace AMDiS size_t nnz = 0; - For<0, nComponents>::loop([this, &nnz, asmMatrix, asmVector](auto const _r) + For<0, nComponents>::loop([this, &nnz, asmMatrix_, asmVector_](auto const _r) { AMDIS_MSG(this->getFeSpace(_r).size() << " DOFs for FeSpace[" << _r << "]"); + bool asmVector = asmVector_ && (!vectorAssembled[int(_r)] || vectorChanging[int(_r)]); + if (asmVector) { rhs->compress(_r); rhs->getVector(_r) = 0.0; } - For<0, nComponents>::loop([this, &nnz, asmMatrix, asmVector, _r](auto const _c) + For<0, nComponents>::loop([this, &nnz, asmMatrix_, asmVector, _r](auto const _c) { // The DOFMatrix which should be assembled auto& dofmatrix = (*systemMatrix)(_r, _c); auto& solution_vec = (*solution)[_c]; auto& rhs_vec = (*rhs)[_r]; + auto row_col = std::make_pair(int(_r), int(_c)); + bool asmMatrix = asmMatrix_ && (!matrixAssembled[row_col] || matrixChanging[row_col]); + int r = 0, c = 0; if (asmMatrix) { - // init boundary condition for (auto bc_list : dirichletBc) { std::tie(r, c) = bc_list.first; @@ -269,10 +295,12 @@ namespace AMDiS bc->init(c == int(_c), dofmatrix, solution_vec, rhs_vec); } } + } - // assemble the DOFMatrix block and the corresponding rhs vector, of r==c - this->assemble({int(_r), int(_c)}, &dofmatrix, (_r == _c && asmVector ? &rhs_vec : NULL)); + // assemble the DOFMatrix block and the corresponding rhs vector, of r==c + this->assemble(row_col, dofmatrix, asmMatrix, rhs_vec, (_r == _c && asmVector)); + if (asmMatrix) { // finish boundary condition for (auto bc_list : dirichletBc) { std::tie(r, c) = bc_list.first; @@ -305,53 +333,69 @@ namespace AMDiS template <class Traits> template <class Matrix, class Vector> void ProblemStatSeq<Traits>::assemble(std::pair<int, int> row_col, - Matrix* dofmatrix, - Vector* rhs) - { - auto const& rowFeSpace = dofmatrix->getRowFeSpace(); - auto const& colFeSpace = dofmatrix->getColFeSpace(); + Matrix& dofmatrix, bool asmMatrix, + Vector& rhs, bool asmVector) + { + auto const& rowFeSpace = dofmatrix.getRowFeSpace(); + auto const& colFeSpace = dofmatrix.getColFeSpace(); - dofmatrix->init(); auto matrixOp = matrixOperators[row_col]; auto matrixOpFac = matrixFactors[row_col]; auto vectorOp = vectorOperators[row_col.first]; auto vectorOpFac = vectorFactors[row_col.first]; + dofmatrix.init(asmMatrix); + + // return if nothing to to. + if ((matrixOp.empty() || !asmMatrix) && + (vectorOp.empty() || !asmVector)) + { + dofmatrix.finish(); + return; + } + for (auto op : matrixOp) op->init(rowFeSpace, colFeSpace); for (auto op : vectorOp) op->init(rowFeSpace, colFeSpace); - + auto rowLocalView = rowFeSpace.localView(); auto rowIndexSet = rowFeSpace.localIndexSet(); auto colLocalView = colFeSpace.localView(); auto colIndexSet = colFeSpace.localIndexSet(); - for (const auto& element : elements(*meshView)) { + for (auto const& element : elements(*meshView)) { rowLocalView.bind(element); rowIndexSet.bind(rowLocalView); colLocalView.bind(element); colIndexSet.bind(colLocalView); - if (dofmatrix) { + if (asmMatrix) { ElementMatrix elementMatrix; bool add = getElementMatrix(rowLocalView, colLocalView, elementMatrix, matrixOp, matrixOpFac); if (add) - addElementMatrix(*dofmatrix, rowIndexSet, colIndexSet, elementMatrix); + addElementMatrix(dofmatrix, rowIndexSet, colIndexSet, elementMatrix); } - if (rhs) { + if (asmVector) { ElementVector elementVector; bool add = getElementVector(rowLocalView, elementVector, vectorOp, vectorOpFac); if (add) - addElementVector(*rhs, rowIndexSet, elementVector); + addElementVector(rhs, rowIndexSet, elementVector); } } - dofmatrix->finish(); + + if (asmMatrix) { + dofmatrix.finish(); + matrixAssembled[row_col] = true; + } + if (asmVector) { + vectorAssembled[row_col.first] = true; + } } @@ -363,15 +407,15 @@ namespace AMDiS std::list<shared_ptr<OperatorType>>& operators, std::list<double*> const& factors) { - const auto nRows = rowLocalView.tree().finiteElement().size(); - const auto nCols = colLocalView.tree().finiteElement().size(); + auto const nRows = rowLocalView.tree().finiteElement().size(); + auto const nCols = colLocalView.tree().finiteElement().size(); AMDIS_TEST_EXIT_DBG(operators.size() == factors.size(), "Nr. of operators and factors must be consistent!"); // fills the entire matrix with zeroes - elementMatrix.setSize(nRows, nCols); - elementMatrix = 0.0; + elementMatrix.change_dim(nRows, nCols); + set_to_zero(elementMatrix); bool add = false; @@ -393,14 +437,14 @@ namespace AMDiS std::list<shared_ptr<OperatorType>>& operators, std::list<double*> const& factors) { - const auto nRows = rowLocalView.tree().finiteElement().size(); + auto const nRows = rowLocalView.tree().finiteElement().size(); AMDIS_TEST_EXIT_DBG(operators.size() == factors.size(), "Nr. of operators and factors must be consistent!"); // Set all entries to zero - elementVector.resize(nRows); - elementVector = 0.0; + elementVector.change_dim(nRows); + set_to_zero(elementVector); bool add = false; @@ -422,12 +466,12 @@ namespace AMDiS ColIndexSet const& colIndexSet, ElementMatrix const& elementMatrix) { - for (size_t i = 0; i < elementMatrix.N(); ++i) { + for (size_t i = 0; i < num_rows(elementMatrix); ++i) { // The global index of the i−th vertex of the element - const auto row = rowIndexSet.index(i); - for (size_t j = 0; j < elementMatrix.M(); ++j) { + auto const row = rowIndexSet.index(i); + for (size_t j = 0; j < num_cols(elementMatrix); ++j) { // The global index of the j−th vertex of the element - const auto col = colIndexSet.index(j); + auto const col = colIndexSet.index(j); dofmatrix(row, col) += elementMatrix[i][j]; } } @@ -440,9 +484,9 @@ namespace AMDiS IndexSet const& indexSet, ElementVector const& elementVector) { - for (size_t i = 0; i < elementVector.size(); ++i) { + for (size_t i = 0; i < size(elementVector); ++i) { // The global index of the i-th vertex - const auto row = indexSet.index(i); + auto const row = indexSet.index(i); dofvector[row] += elementVector[i]; } } diff --git a/dune/amdis/ProblemStatBase.hpp b/dune/amdis/ProblemStatBase.hpp index 29b8ce1a01ac1c1b7ee39a3201c87c676d48af37..82f43269838041c8fa779aaffba26d390a303897 100644 --- a/dune/amdis/ProblemStatBase.hpp +++ b/dune/amdis/ProblemStatBase.hpp @@ -6,14 +6,6 @@ #pragma once #include <string> -#include <tuple> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <dune/grid/albertagrid/agrid.hh> -#include <dune/functions/functionspacebases/pqknodalbasis.hh> #include "Flag.hpp" @@ -124,29 +116,5 @@ namespace AMDiS /// Returns the name of the problem. virtual std::string getName() const = 0; }; - - - - - template <int _dim, int _dimworld = _dim, int _degree0 = 1, int... _degrees> - class ProblemStatTraits - { - template <class... Bs> - using FeSpaceTuple = std::tuple<Bs...>; - - template <class Mesh, int deg> - using Lagrange = Dune::Functions::PQkNodalBasis<typename Mesh::LeafGridView, deg>; - - public: - static constexpr int dim = _dim; - static constexpr int dimworld = _dimworld; - static constexpr int nComponents = sizeof...(_degrees) + 1; - - // default values - using Mesh = Dune::AlbertaGrid<dim, dimworld>; - using FeSpaces = FeSpaceTuple<Lagrange<Mesh, _degree0>, - Lagrange<Mesh, _degrees>...>; - }; - } // end namespace AMDiS diff --git a/dune/amdis/ProblemStatTraits.hpp b/dune/amdis/ProblemStatTraits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ca1798fb3c138a5dd4678223acba02fa28fbcaca --- /dev/null +++ b/dune/amdis/ProblemStatTraits.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include <tuple> + +#include <dune/amdis/Mesh.hpp> +#include <dune/amdis/utility/GetDegree.hpp> + +namespace AMDiS +{ + namespace Impl + { + // by default use Lagrange basis + template <class Mesh, int deg> + struct DefaultFeSpaceFactory + { + using type = Dune::Functions::PQkNodalBasis<typename Mesh::LeafGridView, deg>; + }; + + template <class Mesh> + struct DefaultFeSpaceFactory<Mesh, 1> + { + using type = Dune::Functions::PQ1NodalBasis<typename Mesh::LeafGridView>; + }; + + template <class Mesh, int deg> + using DefaultFeSpaceFactory_t = typename DefaultFeSpaceFactory<Mesh, deg>::type; + } + + /// The default traits, that can be used with variable mesh-type. + /** The traits class specifies dim, dow and the polynomial degrees of + * Lagrange basis functions. Together with a Grid type the necessary parameters + * for the \ref ProblemStat class are set. + **/ + template <class MeshType, int _dim, int _dow = _dim, int... _degrees> + struct DefaultTraitsMesh + { + static constexpr int dim = _dim; + static constexpr int dimworld = _dow; + static constexpr int nComponents = sizeof...(_degrees); + + static_assert( nComponents > 0, "Number of components > 0 required!" ); + + using Mesh = MeshType; + using FeSpaces = std::tuple<Impl::DefaultFeSpaceFactory_t<Mesh, _degrees>...>; + }; + + + /// Specialization of \ref DefaultTraitsMesh for Grid type \ref Dune::YaspGrid. + template <int _dim, int _dow = _dim, int... _degrees> + using DefaultTraits = + DefaultTraitsMesh< Dune::YaspGrid<_dim>, _dim, _dow, _degrees...>; + + + // DEPRECATED! + template <int _dim, int _dimworld = _dim, int _degree0 = 1, int... _degrees> + using ProblemStatTraits = + DefaultTraits< _dim, _dimworld, _degree0, _degrees...>; + +} // end namespace AMDiS diff --git a/dune/amdis/TermGenerator.hpp b/dune/amdis/TermGenerator.hpp deleted file mode 100644 index 65a5fa25f216431360ba17657f1f36b7be442a6a..0000000000000000000000000000000000000000 --- a/dune/amdis/TermGenerator.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/** \file TermGenerator.hpp */ - -#pragma once - -// std c++ includes -#include <type_traits> - -// AMDiS includes -#include "OperatorTerm.hpp" - -// Dune includes -#include <dune/functions/common/functionconcepts.hh> - -namespace AMDiS -{ - namespace Impl - { - // named categories - struct _constant {}; - struct _functor {}; - struct _default {}; - - // TODO: generalize function concept to arbitrary dimensions! - // TODO: add concept for terms - // TODO: generalize constants, to accept also vectors - template <class T> - using TermCategory = - std::conditional_t< std::is_arithmetic<T>::value, - _constant, - std::conditional_t< Dune::Functions::Concept::isFunction<T, double(Dune::FieldVector<double, 1>)>(), - _functor, - std::conditional_t< Dune::Functions::Concept::isFunction<T, double(Dune::FieldVector<double, 2>)>(), - _functor, - std::conditional_t< Dune::Functions::Concept::isFunction<T, double(Dune::FieldVector<double, 3>)>(), - _functor, - _default > > > >; - - - /// Generator class that takes a type as argument - /// and returns the corresponding term-type. - /// By default all arguments are interpreted as constants. - template <class T, class Category> struct ToTerm; - - template <class T> - struct ToTerm<T, _constant> - { - using type = ConstantTerm<T>; - - static type get(T const& t) - { - return {t}; - } - }; - - // if the argument is a functor, that takes a WorldVector - // and returns a double, see concept \ref CoordsFunctor. - template <class F> - struct ToTerm<F, _functor> - { - using type = CoordsTerm<F>; - - template <class F_> - static type get(F_&& f) - { - return {std::forward<F_>(f)}; - } - }; - - // if the argument is already a term return it directly. - template <class T> - struct ToTerm<T, _default> - { - using type = T const&; - - static constexpr type get(T const& t) - { - return t; - } - }; - - } // end namespace Impl - - template <class T> - using ToTerm = Impl::ToTerm<std::decay_t<T>, Impl::TermCategory<std::decay_t<T>> >; - - template <class T> - using ToTerm_t = std::decay_t<typename ToTerm<T>::type>; - - template <class T> - inline typename ToTerm<T>::type toTerm(T&& t) { return ToTerm<T>::get(t); } - -} // end namespace AMDiS diff --git a/dune/amdis/Terms.hpp b/dune/amdis/Terms.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d109b264fbf8346e676183d3e96dac31240c8e2f --- /dev/null +++ b/dune/amdis/Terms.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include <dune/amdis/terms/ConstantTerm.hpp> +#include <dune/amdis/terms/CoordsTerm.hpp> +#include <dune/amdis/terms/DOFVectorTerm.hpp> diff --git a/dune/amdis/common/ConceptsBase.hpp b/dune/amdis/common/ConceptsBase.hpp index 315f18c4a972356a96c9955fe38dc274e00b98a8..12f283017c6bbd4b41c388cd9cf07b0e90a13c8f 100644 --- a/dune/amdis/common/ConceptsBase.hpp +++ b/dune/amdis/common/ConceptsBase.hpp @@ -27,6 +27,8 @@ #define HAS_MEMBER(name) has_member_ ## name +#include <dune/functions/common/functionconcepts.hh> + namespace AMDiS { namespace traits @@ -65,51 +67,7 @@ namespace AMDiS template <class T> using HasResultType = decltype( Impl::HasResultTypeImpl<T>(int{}) ); - - // Type traits to test whether a class is a functor, i.e. has a operator() - // ------------------------------------------------------------------------- - - namespace Impl - { - template <class F, class... Args> - inline auto invoke_functor(F&& f, Args&&... args) - { - return std::forward<F>(f)(std::forward<Args>(args)...); - } - - inline no_valid_type invoke_functor(...); - - } // end namespace Impl - template <class, class> - struct IsFunctor : std::false_type {}; - - template <class F, class Return, class... Args> - struct IsFunctor<F, Return(Args...)> - : std::is_same< decltype( Impl::invoke_functor(std::declval<F>(), std::declval<Args>()...) ), - Return > {}; - - template <class, class> - struct IsFunctorWeak : std::false_type {}; - - template <class F, class Return, class... Args> - struct IsFunctorWeak<F, Return(Args...)> - : std::is_convertible< decltype( Impl::invoke_functor(std::declval<F>(), std::declval<Args>()...) ), - Return > {}; - - - // ------------------------------------------------------------------------- - - - template <class> - struct IsCallable : std::false_type {}; - - template <class F, class... Args> - struct IsCallable<F(Args...)> - : not_< std::is_same< decltype( Impl::invoke_functor(std::declval<F>(), std::declval<Args>()...) ), - no_valid_type > > {}; - - // ------------------------------------------------------------------------- @@ -117,9 +75,7 @@ namespace AMDiS { template <class F, class Arg> inline auto invoke_vector(F&& f, Arg&& arg) - { - return std::forward<F>(f)[std::forward<Arg>(arg)]; - } + -> decltype( std::forward<F>(f)[std::forward<Arg>(arg)] ); inline no_valid_type invoke_vector(...); @@ -130,7 +86,7 @@ namespace AMDiS template <class F, class Return, class Arg> struct IsVector<F, Return(Arg)> - : std::is_same< decltype( Impl::invoke_vector(std::declval<F>(), std::declval<Arg>()) ), + : std::is_same< decltype( Impl::invoke_vector(std::declval<std::decay_t<F>>(), std::declval<Arg>()) ), Return > {}; template <class, class> @@ -138,7 +94,7 @@ namespace AMDiS template <class F, class Return, class Arg> struct IsVectorWeak<F, Return(Arg)> - : std::is_convertible< decltype( Impl::invoke_vector(std::declval<F>(), std::declval<Arg>()) ), + : std::is_convertible< decltype( Impl::invoke_vector(std::declval<std::decay_t<F>>(), std::declval<Arg>()) ), Return > {}; @@ -158,27 +114,61 @@ namespace AMDiS /// Namespace that implements basic concept checks - namespace concepts + namespace Concepts { - /// @defgroup concepts Concepts definitions, using decltype and other c++11 features. - - template <class F> // F(Arg) - constexpr bool Callable = traits::IsCallable<F>::value; + /** + * \defgroup Concepts Concepts definitions + * @{ + **/ + + /// A Collable is a function `F` that can be called with arguments of type `Args...`. + /** + * To be used as follows: `Concepts::Collable<F, Args...>`. Returns true, if + * an instance of `F` can be called by `operator()` with arguments of type + * `Args...`. + **/ + template <class F, class... Args> + constexpr bool Callable = Dune::Functions::Concept::isCallable<F, Args...>(); + - template <class F, class U> // F, U=Return(Arg) - constexpr bool Functor = traits::IsFunctor<F,U>::value; + /// A Functor is a function `F` with signature `Signature`. + /** + * To be used as follows: `Concepts::Functor<F, R(Args...)>`. Returns true, if + * an instance of `F` can be called by `operator()` with arguments of type + * `Args...` and returns a value of type `R`, i.e. `Signature := R(Args...)`. + **/ + template <class F, class Signature> // F, Signature=Return(Arg) + constexpr bool Functor = Dune::Functions::Concept::isFunction<F, Signature>(); + + /// A predicate is a function that returns a boolean. + template <class F, class... Args> + constexpr bool Predicate = Functor<F, bool(Args...)>; + + + /// Test whether a type `T` supports vector-access `vector[size_t]`. + /** + * To be used as follows: `Concepts::Vector<V>`. Returns true, if `V` has a + * value type, accessible by `Value_t<V>` and an instance of `V` can be called + * by square brackets `operator[]` with an index of type `size_t`. The return + * value of this element access should be convertible to `Value_t<V>`. + **/ template <class T> constexpr bool Vector = traits::IsVectorWeak<T, Value_t<T>(size_t)>::value; + + /// Test whether a type `T` supports matrix-access `matrix(size_t, size_t)`. + /** + * To be used as follows: `Concepts::Matrix<M>`. Returns true, if `M` has a + * value type, accessible by `Value_t<M>` and an instance of `M` can be called + * by round brackets `operator()` with two indices of type `size_t`. The return + * value of this element access should be convertible to `Value_t<V>`. + **/ template <class T> - constexpr bool Matrix = traits::IsFunctorWeak<T, Value_t<T>(size_t, size_t)>::value; - - } // end namespace concepts - + constexpr bool Matrix = Functor<T, Value_t<T>(size_t, size_t)>; + + /** @} **/ - /// Namespace that implements basic concepts-checks using enable_if and - /// type-traits from namespace \ref concepts - namespace requires {} + } // end namespace Concepts } // end namespace AMDiS diff --git a/dune/amdis/common/ScalarTypes.hpp b/dune/amdis/common/ScalarTypes.hpp index 039576530169a6c4c51f8b213efed2469b4e5a00..68b42393950cb7cc7224e8462d340163dc05ceda 100644 --- a/dune/amdis/common/ScalarTypes.hpp +++ b/dune/amdis/common/ScalarTypes.hpp @@ -15,14 +15,24 @@ namespace AMDiS } // end namespace traits - namespace concepts + namespace Concepts { + /** \addtogroup Concepts + * @{ + **/ + + /// \brief The types following the std type-trait \ref std::is_integral are + /// categorized as *integral types*. template <class T> constexpr bool Integral = traits::IsIntegral<T>::value; + /// \brief The types following the std type-trait \ref std::is_arithmetic are + /// categorized as *arithmetic types*. template <class T> constexpr bool Arithmetic = traits::IsArithmetic<T>::value; - } // end namespace concepts + /** @} **/ + + } // end namespace Concepts } // end namespace AMDiS diff --git a/dune/amdis/common/Traits.hpp b/dune/amdis/common/Traits.hpp index f2e2c8a87582eac808952ffae326831854f38e9b..0cefa62db8db4441d8ee2300551fc49b4f473cd8 100644 --- a/dune/amdis/common/Traits.hpp +++ b/dune/amdis/common/Traits.hpp @@ -32,10 +32,10 @@ namespace AMDiS } // end namespace Impl template <class T, class U = T> - using IsAddable = IsCallable<Impl::PlusOp(T, U)>; + using IsAddable = bool_<Concepts::Callable<Impl::PlusOp, T, U>>; template <class T, class U = T> - using IsMultiplicable = IsCallable<Impl::MultipliesOp(T, U)>; + using IsMultiplicable = bool_<Concepts::Callable<Impl::MultipliesOp, T, U>>; template <class T> @@ -96,13 +96,17 @@ namespace AMDiS } // end namespace traits - namespace concepts + namespace Concepts { - /// Types support A + B + /** \addtogroup Concepts + * @{ + **/ + + /// Types support \f$ A + B \f$ template <class A, class B> constexpr bool Addable = traits::IsAddable<A, B>::value; - /// Types support A * B + /// Types support \f$ A \cdot B \f$ template <class A, class B> constexpr bool Multiplicable = traits::IsMultiplicable<A, B>::value; @@ -110,6 +114,8 @@ namespace AMDiS template <class A, class B> constexpr bool Compatible = traits::IsCompatible<A, B>::value; - } // end namespace concepts + /** @} **/ + + } // end namespace Concepts } // end namespace AMDiS diff --git a/dune/amdis/common/TypeDefs.hpp b/dune/amdis/common/TypeDefs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b5077272314ee1f8f496015a1bd5dd6b067a3519 --- /dev/null +++ b/dune/amdis/common/TypeDefs.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include <boost/numeric/mtl/vector/dense_vector.hpp> +#include <boost/numeric/mtl/matrix/dense2D.hpp> + +namespace AMDiS +{ + namespace Impl + { + using ElementVector = mtl::dense_vector<double>; + using ElementMatrix = mtl::dense2D<double>; + + } // end namespace Impl +} // end namespace AMDiS diff --git a/dune/amdis/common/ValueCategory.hpp b/dune/amdis/common/ValueCategory.hpp index 357d2bb17c6156b4ebfd062df7f9ca6bbdfb7205..0aa8fe04efd205b0cf01043b1d4ba5f8bc8b0d7d 100644 --- a/dune/amdis/common/ValueCategory.hpp +++ b/dune/amdis/common/ValueCategory.hpp @@ -14,12 +14,16 @@ namespace AMDiS struct scalar {}; struct vector {}; struct matrix {}; + struct unknown {}; } // end namespace tag /// Category of type T, e.g. scalar, vector matrix, specified by a tag template <class T, class = void> - struct ValueCategory; + struct ValueCategory + { + using type = tag::unknown; + }; template <class T> using ValueCategory_t = typename ValueCategory<T>::type; @@ -53,5 +57,5 @@ namespace AMDiS { using type = tag::scalar; }; - + } // end namespace AMDiS diff --git a/dune/amdis/linear_algebra/istl/SystemMatrix.hpp b/dune/amdis/linear_algebra/istl/SystemMatrix.hpp index 91efbea345ca5ca000606b11aba2dde6022d7956..118cda2324ea2c8e7385451ef4c6d4f864bdb1e2 100644 --- a/dune/amdis/linear_algebra/istl/SystemMatrix.hpp +++ b/dune/amdis/linear_algebra/istl/SystemMatrix.hpp @@ -14,7 +14,7 @@ #include <dune/amdis/linear_algebra/istl/DOFMatrix.hpp> // for explicit instantiation -#include <dune/amdis/ProblemStatBase.hpp> +#include <dune/amdis/ProblemStatTraits.hpp> namespace AMDiS { diff --git a/dune/amdis/linear_algebra/istl/SystemVector.hpp b/dune/amdis/linear_algebra/istl/SystemVector.hpp index bccc91517cb1e248c46a1c84a90664db577139f0..9cb385b792faafa4994e7756eac0356814bd6c5a 100644 --- a/dune/amdis/linear_algebra/istl/SystemVector.hpp +++ b/dune/amdis/linear_algebra/istl/SystemVector.hpp @@ -15,7 +15,7 @@ #include <dune/amdis/linear_algebra/istl/DOFVector.hpp> // for explicit instantiation -#include <dune/amdis/ProblemStatBase.hpp> +#include <dune/amdis/ProblemStatTraits.hpp> namespace AMDiS { diff --git a/dune/amdis/linear_algebra/mtl/BITL_Solver.hpp b/dune/amdis/linear_algebra/mtl/BITL_Solver.hpp index b17d0d260dc52d5a325272464598e74f2b004995..6be71e292601261af458e13393218b4c49f75f56 100644 --- a/dune/amdis/linear_algebra/mtl/BITL_Solver.hpp +++ b/dune/amdis/linear_algebra/mtl/BITL_Solver.hpp @@ -5,9 +5,22 @@ namespace AMDiS { - + /// Adds default creators for linear solvers based on `BlockMTLMatrix`. + /** + * Adds creators for block matrix aware solvers. + * - *cg*: conjugate gradient method, \see cg_solver_type + * - *cgs*: stabilized conjugate gradient mtheod, \see cgs_solver_type + * - *bcgs*: stabilized bi-conjugate gradient method, \see bicgstab_type + * - *tfqmr*: Transposed-Free Quasi-Minimal Residual method, \see tfqmr_solver_type + * - *bcgsl*: stabilized BiCG(ell) method, \see bicgstab_ell_type + * - *gmres*: Generalized minimal residula method, \see gmres_type + * - *fgmres*: Flexible GMRES, \see fgmres_type + * - *minres*: Minimal residul method, \see minres_solver_type + * - *gcr*: Generalized conjugate residual method, \see gcr_type + * - *umfpack*: external UMFPACK solver, \see UmfpackRunner + **/ template <class SubMatrix, size_t _N, size_t _M, class Vector> - struct DefaultCreators<LinearSolverInterface<BlockMTLMatrix<SubMatrix, _N, _M>, Vector, Vector>> + class DefaultCreators<LinearSolverInterface<BlockMTLMatrix<SubMatrix, _N, _M>, Vector, Vector>> { using Matrix = BlockMTLMatrix<SubMatrix, _N, _M>; using SolverBase = LinearSolverInterface<Matrix, Vector, Vector>; @@ -23,7 +36,7 @@ namespace AMDiS using Map = CreatorMap<SolverBase>; - /// Instantiate a new linear solver + public: static void init() { auto cg = new SolverCreator<cg_solver_type>; diff --git a/dune/amdis/linear_algebra/mtl/BlockMTLVector.hpp b/dune/amdis/linear_algebra/mtl/BlockMTLVector.hpp index 77bd7040beaf4d84dd274ab5a5443245440326ae..10ab36a6c26c3c70aca56b6d8842d2be4cdbf033 100644 --- a/dune/amdis/linear_algebra/mtl/BlockMTLVector.hpp +++ b/dune/amdis/linear_algebra/mtl/BlockMTLVector.hpp @@ -44,7 +44,7 @@ namespace AMDiS inline size_t num_rows(BlockMTLVector<MTLVector, _N> const& vec) { size_t nRows = 0; - For<0, _N>::loop([&](const auto _i) { + for_<0, _N>([&](const auto _i) { nRows += num_rows(std::get<_i>(vec)); }); return nRows; @@ -68,7 +68,7 @@ namespace AMDiS template <class MTLVector, size_t _N> inline void set_to_zero(BlockMTLVector<MTLVector, _N>& vec) { - For<0, _N>::loop([&](const auto _i) { + for_<0, _N>([&](const auto _i) { set_to_zero(std::get<_i>(vec)); }); } @@ -80,7 +80,7 @@ namespace AMDiS template <class BlockVector, class Vector, class NonConstBlockVector> class BlockVectorWrapper; - + // specialization for BlockMTLVector template <class BlockVector, class Vector, class MTLVector, size_t _N> class BlockVectorWrapper<BlockVector, Vector, BlockMTLVector<MTLVector, _N>> { @@ -132,7 +132,6 @@ namespace AMDiS template <bool Copy> std::enable_if_t<Copy> assignFrom(bool_<Copy>) { - AMDIS_MSG("assignFrom..."); size_t start = 0; for (size_t r = 0; r < _N; ++r) { size_t finish = start + num_rows(blockVector[r]); diff --git a/dune/amdis/linear_algebra/mtl/DOFMatrix.hpp b/dune/amdis/linear_algebra/mtl/DOFMatrix.hpp index a545d9e605e940f1d492b65d0a5a716278c378b1..99f6134fc830f6eab9d62779f5f69a682237779b 100644 --- a/dune/amdis/linear_algebra/mtl/DOFMatrix.hpp +++ b/dune/amdis/linear_algebra/mtl/DOFMatrix.hpp @@ -14,7 +14,7 @@ namespace AMDiS { /// \brief The basic container that stores a base matrix and a corresponding - /// row/column feSpace + /// row/column feSpace. template <class RowFeSpaceType, class ColFeSpaceType, class ValueType = double> class DOFMatrix @@ -26,7 +26,7 @@ namespace AMDiS /// The type of the finite element space / basis of the column using ColFeSpace = ColFeSpaceType; - /// The vector type of the underlying base matrix + /// The matrix type of the underlying base matrix using BaseMatrix = mtl::compressed2D<ValueType>; /// The index/size - type @@ -117,15 +117,17 @@ namespace AMDiS } /// Create inserter. Assumes that no inserter is currently active on this matrix. - void init() + void init(bool prepareForInsertion) { AMDIS_TEST_EXIT(!initialized && !inserter, "Matrix already in insertion mode!"); calculateSlotSize(); matrix->change_dim(rowFeSpace.size(), colFeSpace.size()); - set_to_zero(*matrix); - inserter = new Inserter(*matrix, slot_size); - initialized = true; + if (prepareForInsertion) { + set_to_zero(*matrix); + inserter = new Inserter(*matrix, slot_size); + initialized = true; + } } /// Delete inserter -> finish insertion. Must be called in order to fill the diff --git a/dune/amdis/linear_algebra/mtl/DOFVector.hpp b/dune/amdis/linear_algebra/mtl/DOFVector.hpp index 2d8b02e19827ba8cbe9c530d60729f30c40a66d5..91ffdf4f35d76205850d01c71029d9da723aa9ec 100644 --- a/dune/amdis/linear_algebra/mtl/DOFVector.hpp +++ b/dune/amdis/linear_algebra/mtl/DOFVector.hpp @@ -1,5 +1,9 @@ #pragma once +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string> #include <memory> @@ -117,7 +121,7 @@ namespace AMDiS /// Scale each DOFVector by the factor \p s. template <class Scalar> - std::enable_if_t< concepts::Arithmetic<Scalar>, Self&> + std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&> operator*=(Scalar s) { (*vector) *= s; @@ -126,7 +130,7 @@ namespace AMDiS /// Sets each DOFVector to the scalar \p s. template <class Scalar> - std::enable_if_t< concepts::Arithmetic<Scalar>, Self&> + std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&> operator=(Scalar s) { (*vector) = s; diff --git a/dune/amdis/linear_algebra/mtl/ITL_Solver.hpp b/dune/amdis/linear_algebra/mtl/ITL_Solver.hpp index d4f59262a2c9484f66627871090fa50f8a58cd6f..755080b22511a74523bcd446da7ad783d5a90532 100644 --- a/dune/amdis/linear_algebra/mtl/ITL_Solver.hpp +++ b/dune/amdis/linear_algebra/mtl/ITL_Solver.hpp @@ -1,9 +1,6 @@ /** \file ITL_Solver.h */ #pragma once -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif // MTL4 includes #include <boost/numeric/itl/itl.hpp> @@ -37,32 +34,6 @@ namespace AMDiS { /** * \ingroup Solver - * - * \brief - * Creator for MTL4 itl-solvers. - * - * One of the following solvers can be chosen: - * - @ref CGSolver "cg" (conjugate gradient method) - * - @ref CGSSolver "cgs" (squared conjugate gradient method) - * - @ref BiCGSolver "bicg" (biconjugate gradient method) - * - @ref BiCGStabSolver "bicgstab" (stabilized BiCG method) - * - @ref BiCGStab2Solver "bicgstab2" (stabilized BiCG(l) method with l=2) - * - @ref QMRSolver "qmr" (Quasi-Minimal Residual method) - * - @ref TFQMRSolver "tfqmr" (Transposed-Free Quasi-Minimal Residual method) - * - @ref BiCGStabEllSolver "bicgstab_ell" (stabilized BiCG(l) method) - * - @ref GMResSolver "gmres" (generalized minimal residual method) - * - @ref IDRsSolver "idr_s" (Induced Dimension Reduction method) - * - @ref MinResSolver "minres" (minimal residual method) - * - @ref GcrSolver "gcr" (generalized conjugate residual method) - * - @ref FGMResSolver "fgmres" (flexible GMRes method) - * - @ref PreOnly "preonly" (solver that implements pure preconditioning applied to the rhs) - */ - - // =========================================================================== - - /** - * \ingroup Solver - * \class AMDiS::CGSolver * \brief ITL_Solver <\ref cg_solver_type> implementation of conjugate gradient * method \implements ITL_Solver * @@ -70,7 +41,6 @@ namespace AMDiS * and can be used for symmetric positive definite system matrices. * Right preconditioner is ignored. */ - class cg_solver_type { public: @@ -82,18 +52,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::CGSSolver * \brief ITL_Solver <\ref cgs_solver_type> implementation of squared conjugate * gradient method \implements ITL_Solver * * Solves a linear system \f$ Ax=b \f$ by the squared conjugate gradient method * (CGS). Right preconditioner is ignored. */ - class cgs_solver_type { public: @@ -105,18 +72,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::BiCGSolver * \brief ITL_Solver <\ref bicg_solver_type> implementation of bi-conjugate * gradient method \implements ITL_Solver * * Solves a linear system \f$ Ax=b \f$ by a BiCG method and can be used for * system matrices. */ - class bicg_solver_type { public: @@ -128,18 +92,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::BiCGStabSolver * \brief ITL_Solver <\ref bicgstab_type> implementation of stabilized * bi-conjugate gradient method \implements ITL_Solver * * Solves a linear system \f$ Ax=b \f$ by a stabilized BiCG method and can be * used for system matrices. */ - class bicgstab_type { public: @@ -151,18 +112,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::BiCGStab2Solver * \brief ITL_Solver <\ref bicgstab2_type> implementation of BiCGStab(l) method * with l=2 \implements ITL_Solver * * Solves a linear system \f$ Ax=b \f$ by a stabilized BiCG(2) method and can * be used for system matrices. */ - class bicgstab2_type { public: @@ -174,17 +132,14 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::QMRSolver * \brief ITL_Solver <\ref qmr_solver_type> implementation of Quasi-Minimal * Residual method \implements ITL_Solver * * Solves a linear system \f$ Ax=b \f$ by the Quasi-Minimal Residual method (QMR). */ - class qmr_solver_type { public: @@ -196,18 +151,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::TFQMRSolver * \brief ITL_Solver <\ref tfqmr_solver_type> implementation of Transposed-Free * Quasi-Minimal Residual method \implements ITL_Solver * * Solves a linear system by the Transposed-Free Quasi-Minimal Residual method * (TFQMR). Does not use preconditioning currently. */ - class tfqmr_solver_type { public: @@ -219,18 +171,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::BiCGStabEllSolver * \brief ITL_Solver <\ref bicgstab_ell_type> implementation of stabilized * BiCG(ell) method \implements ITL_Solver * * Solves a linear system by a stabilized BiCG(ell) method and can be used for * system matrices. The parameter ell [3] can be specified. */ - class bicgstab_ell_type { int ell; @@ -246,11 +195,9 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::GMResSolver * \brief ITL_Solver <\ref gmres_type> implementation of generalized minimal * residual method \implements ITL_Solver * @@ -258,7 +205,6 @@ namespace AMDiS * The parameter restart [30] is the maximal number of orthogonalized vectors. * The method is not preconditioned */ - class gmres_type { @@ -292,11 +238,8 @@ namespace AMDiS }; - // =========================================================================== - /** * \ingroup Solver - * \class AMDiS::IDRsSolver * \brief ITL_Solver <\ref idr_s_type> implementation of Induced Dimension * Reduction method \implements ITL_Solver * @@ -307,7 +250,6 @@ namespace AMDiS * algorithms for solving large nonsymmetric linear systems. * SIAM J. Sci. Comput. Vol. 31, No. 2, pp. 1035-1062 (2008). (copyright SIAM) */ - class idr_s_type { int s; @@ -323,18 +265,15 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::MinResSolver * \brief ITL_Solver <\ref minres_solver_type> implementation of minimal * residual method \implements ITL_Solver * * Solves a linear system by the Minres method. Can be used for symmetric * indefinite systems. */ - class minres_solver_type { public: @@ -346,11 +285,9 @@ namespace AMDiS } }; - // =========================================================================== /** * \ingroup Solver - * \class AMDiS::GcrSolver * \brief ITL_Solver <\ref gcr_type> implementation of generalized conjugate * residual method \implements ITL_Solver * @@ -358,7 +295,6 @@ namespace AMDiS * method. The parameter restart [30] is the maximal number of orthogonalized * vectors. */ - class gcr_type { int restart; @@ -374,12 +310,10 @@ namespace AMDiS return itl::gcr(A, x, b, l, r, iter, restart); } }; - - // =========================================================================== + /** * \ingroup Solver - * \class AMDiS::FGMResSolver * \brief ITL_Solver <\ref fgmres_type> implementation of flexible GMRes method * \implements ITL_Solver * @@ -388,7 +322,6 @@ namespace AMDiS * See reference "A Flexible Inner-Outer Preconditiones GMRES Algorithm", * Youcef Saad, (1993) */ - class fgmres_type { public: @@ -418,14 +351,11 @@ namespace AMDiS int restart; int orthogonalization; - }; - // =========================================================================== - + /** * \ingroup Solver - * \class AMDiS::PreOnly * \brief ITL_Solver <\ref preonly_type> implementation of preconditioner as * \implements ITL_Solver * @@ -442,12 +372,31 @@ namespace AMDiS } }; + // =========================================================================== - + /// Adds default creators for linear solvers based on `mtl::compressed2D`. + /** + * Adds creators for full-matrix aware solvers. + * - *cg*: conjugate gradient method, \see cg_solver_type + * - *cgs*: stabilized conjugate gradient mtheod, \see cgs_solver_type + * - *bicg*: BiCG mtheod, \see bicg_solver_type + * - *bcgs*: stabilized bi-conjugate gradient method, \see bicgstab_type + * - *bcgs2*: stabilized bi-conjugate gradient method, \see bicgstab2_type + * - *qmr*: Quasi-Minimal Residual method, \see qmr_solver_type + * - *tfqmr*: Transposed-Free Quasi-Minimal Residual method, \see tfqmr_solver_type + * - *bcgsl*: stabilized BiCG(ell) method, \see bicgstab_ell_type + * - *gmres*: Generalized minimal residula method, \see gmres_type + * - *fgmres*: Flexible GMRES, \see fgmres_type + * - *minres*: Minimal residul method, \see minres_solver_type + * - *idrs*: Induced Dimension Reduction method, \see idr_s_type + * - *gcr*: Generalized conjugate residual method, \see gcr_type + * - *preonly*: Just a pply a preconditioner, \see preonly_type + * - *umfpack*: external UMFPACK solver, \see UmfpackRunner + **/ template <class T, class Param, class Vector> - struct DefaultCreators<LinearSolverInterface<mtl::compressed2D<T, Param>, Vector, Vector>> + class DefaultCreators<LinearSolverInterface<mtl::compressed2D<T, Param>, Vector, Vector>> { using Matrix = mtl::compressed2D<T, Param>; using SolverBase = LinearSolverInterface<Matrix, Vector, Vector>; @@ -463,7 +412,7 @@ namespace AMDiS using Map = CreatorMap<SolverBase>; - /// Instantiate a new linear solver + public: static void init() { auto cg = new SolverCreator<cg_solver_type>; diff --git a/dune/amdis/linear_algebra/mtl/SystemMatrix.hpp b/dune/amdis/linear_algebra/mtl/SystemMatrix.hpp index f5f88bbd7aa360920030d6d9b415fd78c27446fb..cd70dc53c59616f27a3cb7328be38ba15b5082ea 100644 --- a/dune/amdis/linear_algebra/mtl/SystemMatrix.hpp +++ b/dune/amdis/linear_algebra/mtl/SystemMatrix.hpp @@ -15,7 +15,7 @@ #include <dune/amdis/linear_algebra/mtl/DOFMatrix.hpp> // for explicit instantiation -#include <dune/amdis/ProblemStatBase.hpp> +#include <dune/amdis/ProblemStatTraits.hpp> namespace AMDiS { diff --git a/dune/amdis/linear_algebra/mtl/SystemVector.hpp b/dune/amdis/linear_algebra/mtl/SystemVector.hpp index e5e91a159e026f59725886a7bba0860b7f6a4696..b7f616932f4b0ca6bafef016032f1b876024688f 100644 --- a/dune/amdis/linear_algebra/mtl/SystemVector.hpp +++ b/dune/amdis/linear_algebra/mtl/SystemVector.hpp @@ -15,11 +15,10 @@ #include <dune/amdis/linear_algebra/mtl/DOFVector.hpp> // for explicit instantiation -#include <dune/amdis/ProblemStatBase.hpp> +#include <dune/amdis/ProblemStatTraits.hpp> namespace AMDiS { - /// \cond HIDDEN_SYMBOLS namespace Impl { // DOFVectors = std::tuple< DOFVector<FeSpace, ValueType>... > @@ -57,7 +56,6 @@ namespace AMDiS } } // end namespace Impl - /// \endcond /// \brief Container that repesents multiple data-Vectors of different value types. @@ -200,7 +198,7 @@ namespace AMDiS /// Scale each DOFVector by the factor \p s. template <class Scalar> - std::enable_if_t< concepts::Arithmetic<Scalar>, Self&> + std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&> operator*=(Scalar s) { For<0, size()>::loop([this, s](const auto I) { @@ -211,7 +209,7 @@ namespace AMDiS /// Sets each DOFVector to the scalar \p s. template <class Scalar> - std::enable_if_t< concepts::Arithmetic<Scalar>, Self&> + std::enable_if_t< Concepts::Arithmetic<Scalar>, Self&> operator=(Scalar s) { For<0, size()>::loop([this, s](const auto I) { diff --git a/dune/amdis/linear_algebra/mtl/UmfpackRunner.hpp b/dune/amdis/linear_algebra/mtl/UmfpackRunner.hpp index 36ce56f4d79fa13c31d4bb11363ed86c5d94ba4f..83634a2c9221c7b6fc3e37ab570a6b1b6ab7737d 100644 --- a/dune/amdis/linear_algebra/mtl/UmfpackRunner.hpp +++ b/dune/amdis/linear_algebra/mtl/UmfpackRunner.hpp @@ -1,5 +1,9 @@ #pragma once +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef HAVE_UMFPACK #include <iostream> @@ -13,16 +17,19 @@ #include <dune/amdis/linear_algebra/mtl/Copy.hpp> namespace AMDiS -{ +{ /** * \ingroup Solver - * \class AMDiS::UmfPackSolver - * \brief \implements LinearSolver - * Wrapper for the external UMFPACK solver: - * http://www.cise.ufl.edu/research/sparse/umfpack/ + * \class AMDiS::UmfpackRunner + * \brief \implements RunnerInterface + * Wrapper for the external + * [UMFPACK solver](http://faculty.cse.tamu.edu/davis/suitesparse.html) * * This is a direct solver for large sparse matrices. */ + template <class Matrix, class Vector> + class UmfpackRunner; + template <class Matrix, class Vector> class UmfpackRunnerBase : public RunnerInterface<Matrix, Vector, Vector> { @@ -84,10 +91,6 @@ namespace AMDiS double alloc_init; }; - - template <class Matrix, class Vector> - class UmfpackRunner; - // specialization for block-matrices template <class SubMatrix, size_t _N, size_t _M, class Vector> class UmfpackRunner<BlockMTLMatrix<SubMatrix, _N, _M>, Vector> diff --git a/dune/amdis/terms/ConstantTerm.hpp b/dune/amdis/terms/ConstantTerm.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d43bfd6ba5234062855a2f6970fb627815b687b3 --- /dev/null +++ b/dune/amdis/terms/ConstantTerm.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include <type_traits> + +#include <dune/amdis/OperatorTermBase.hpp> +#include <dune/amdis/common/ScalarTypes.hpp> + +namespace AMDiS +{ + /** + * \defgroup OperatorTerms Expressions and terms to be used in GenericOperatorTerm. + * @{ + **/ + + /// An expression representing a constant (arithmetic) value, \see constant + template <class ValueType> + class ConstantTerm + { + public: + // TODO: possibly convert to plain type, in case of expression templates. + using value_type = ValueType; + + ConstantTerm(value_type value) + : value(value) + {} + + template <class Element, class PointList> + void init(Element const& element, + PointList const& points) { /* do nothing */ } + + value_type const& operator[](size_t iq) const + { + return value; + } + + int getDegree() const + { + return 0; + } + + private: + value_type value; + }; + + + /// generator function for \ref ConstantTerm expressions + template <class T> + ConstantTerm<T> constant(T value) { return {value}; } + + /** @} **/ + +} // end namespace AMDiS diff --git a/dune/amdis/terms/CoordsTerm.hpp b/dune/amdis/terms/CoordsTerm.hpp new file mode 100644 index 0000000000000000000000000000000000000000..50f30e9b3f117cbc4cb891dcafaaac85f3b29efe --- /dev/null +++ b/dune/amdis/terms/CoordsTerm.hpp @@ -0,0 +1,99 @@ +#pragma once + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <vector> +#include <type_traits> + +#include <dune/istl/bvector.hh> + +#include <dune/amdis/OperatorTermBase.hpp> +#include <dune/amdis/common/Traits.hpp> + +namespace AMDiS +{ + /** + * \addtogroup OperatorTerms + * @{ + **/ + + namespace Impl + { + template <class F, int dow> + using CoordsFunctorResult + = std::result_of<F(Dune::FieldVector<double, dow>)>; + + template <class F, int dow> + constexpr bool CallableDow = + Concepts::Callable<F, Dune::FieldVector<double, dow>>; + +#ifndef AMDIS_DOW + template <class F> + using CoordsFunctorResult_t = typename std::conditional_t< + CallableDow<F, 1>, CoordsFunctorResult<F, 1>, std::conditional_t< + CallableDow<F, 2>, CoordsFunctorResult<F, 2>, std::conditional_t< + CallableDow<F, 3>, CoordsFunctorResult<F, 3>, Id<void>> > >::type; +#else + template <class F> + using CoordsFunctorResult_t = typename std::conditional_t< + CallableDow<F, AMDIS_DOW>, CoordsFunctorResult<F, AMDIS_DOW>, Id<void>>::type; +#endif + } + + + /// \brief An expression that evaluates to the current coordinate of a dof or + /// quadrature point with given index. \see eval. + template <class Functor> + class CoordsTerm + { + public: + using value_type = Impl::CoordsFunctorResult_t<Functor>; + static_assert( !std::is_same<value_type, void>::value, + "Template `Functor` can not be used as a functor."); + + template <class F, + class = std::enable_if_t<Concepts::Compatible<Functor, F>> > + CoordsTerm(F&& f, int degree = 1) + : fct(std::forward<F>(f)) + , degree(degree) + {} + + /// \brief Evaluates the functor \ref fct at all quadrature points and + /// stores the result in a vector \ref values. + template <class Element, class PointList> + void init(Element const& element, + PointList const& points) + { + AMDIS_FUNCNAME("CoordsTerm::init()"); + values.resize(points.size()); + for (size_t iq = 0; iq < points.size(); ++iq) + values[iq] = fct(element.geometry().global(points[iq].position())); + } + + value_type const& operator[](size_t iq) const + { + return values[iq]; + } + + int getDegree() const + { + return degree; + } + + private: + Functor fct; + int degree; + + std::vector<value_type> values; + }; + + + /// Generator function for \ref CoordsTerm expressions + template <class F> + CoordsTerm< std::decay_t<F> > eval(F&& f) { return {std::forward<F>(f)}; } + + /** @} **/ + +} // end namespace AMDiS diff --git a/dune/amdis/OperatorTerm.hpp b/dune/amdis/terms/DOFVectorTerm.hpp similarity index 70% rename from dune/amdis/OperatorTerm.hpp rename to dune/amdis/terms/DOFVectorTerm.hpp index ef2bc3e30718ac7314d850ec021852b68b21274d..a0aabcbd980eceb841cd2b7f7dfdc8bc784bd925 100644 --- a/dune/amdis/OperatorTerm.hpp +++ b/dune/amdis/terms/DOFVectorTerm.hpp @@ -1,137 +1,29 @@ #pragma once +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <algorithm> #include <vector> #include <type_traits> #include <dune/istl/bvector.hh> -#include <dune/functions/common/functionconcepts.hh> -#include <dune/functions/functionspacebases/pqknodalbasis.hh> #include <dune/amdis/OperatorTermBase.hpp> #include <dune/amdis/common/Traits.hpp> +#include <dune/amdis/utility/GetDegree.hpp> namespace AMDiS { -// some example terms -// ----------------------------------------------------------------------------- + /** + * \addtogroup OperatorTerms + * @{ + **/ - /// An expression representing a constant (arithmetic) value - template <class ValueType> - class ConstantTerm - { - public: - using value_type = ValueType; - - ConstantTerm(value_type value) - : value(value) - {} - - template <class Element, class PointList> - void init(Element const& element, - PointList const& points) { /* do nothing */ } - - value_type operator[](size_t iq) const - { - return value; - } - - int getDegree() const - { - return 0; - } - - private: - value_type value; - }; - - - /// generator function for \ref ConstantTerm expressions - template <class T> - std::enable_if_t< concepts::Arithmetic<T>, ConstantTerm<T> > - constant(T value) { return {value}; } - -// ----------------------------------------------------------------------------- - - namespace Impl - { - template <class F, int dow> - using CoordsFunctorResult - = std::result_of<F(Dune::FieldVector<double, dow>)>; - - template <class F, int dow> - static constexpr bool isCallableDow() - { return concepts::Callable<F(Dune::FieldVector<double, dow>)>; } - - template <class F> - using CoordsFunctorResult_t = typename std::conditional_t< - isCallableDow<F, 1>(), CoordsFunctorResult<F, 1>, std::conditional_t< - isCallableDow<F, 2>(), CoordsFunctorResult<F, 2>, std::conditional_t< - isCallableDow<F, 3>(), CoordsFunctorResult<F, 3>, void> > >::type; - } - - - - /// An expression that evaluates to the current coordinate of a dof or - /// quadrature point with given index. - template <class Functor> - class CoordsTerm - { - public: - using value_type = Impl::CoordsFunctorResult_t<Functor>; - - template <class F, - class = std::enable_if_t<concepts::Compatible<Functor, F>> > - CoordsTerm(F&& f, int degree = 1) - : fct(std::forward<F>(f)) - , degree(degree) - {} - - template <class Element, class PointList> - void init(Element const& element, - PointList const& points) - { - AMDIS_FUNCNAME("CoordsTerm::init()"); - values.resize(points.size()); - for (size_t iq = 0; iq < points.size(); ++iq) - values[iq] = fct(element.geometry().global(points[iq].position())); - } - - value_type const& operator[](size_t iq) const - { - return values[iq]; - } - - int getDegree() const - { - return degree; - } - - private: - Functor fct; - int degree; - - std::vector<value_type> values; - }; - - - /// generator function for \ref CoordsTerm expressions - template <class F> - CoordsTerm< std::decay_t<F> > eval(F&& f) { return {std::forward<F>(f)}; } - - -// ----------------------------------------------------------------------------- - - - // helper class to extract the polynomial degree of a pqk nodal basis - template <class FeSpace> struct GetDegree : int_<1> {}; - template <class GV, int k, class ST> - struct GetDegree<Dune::Functions::PQkNodalBasis<GV, k, ST> > : int_<k> {}; - - - /// An expression that evalues a DOFVector at a given element, either on the - /// dofs or on the quadrature points + /// \brief An expression that evalues a DOFVector at a given element, either on the + /// dofs or on the quadrature points. \see valueOf. template <class DOFVectorType> class DOFVectorTerm { @@ -192,13 +84,17 @@ namespace AMDiS typename Basis::LocalView localView; typename Basis::LocalIndexSet localIndexSet; - int degree = GetDegree<Basis>::value; + int degree = getPolynomialDegree<Basis>; std::vector<value_type> values; }; - /// generator function for \ref DOFVector expressions + /// Generator function for \ref DOFVectorTerm expressions. + /** Generates a \ref DOFVectorTerm, that takes a \ref DOFVector \p vector, + * an optional factor \p factor the value of the DOFVector at the quadrature + * points are scaled with. + **/ template <class DOFVectorType> DOFVectorTerm<std::decay_t<DOFVectorType>> valueOf(DOFVectorType&& vector, double factor = 1.0) @@ -210,8 +106,9 @@ namespace AMDiS // ----------------------------------------------------------------------------- - /// An expression that evalues a DOFVector at a given element, either on the - /// dofs or on the quadrature points, and applies a functor to the value + /// \brief An expression that evalues a DOFVector at a given element, either on the + /// dofs or on the quadrature points, and applies a functor to the value. + /// \see valueOfFunc. template <class DOFVectorType, class Func> class DOFVectorFuncTerm { @@ -275,14 +172,19 @@ namespace AMDiS typename Basis::LocalView localView; typename Basis::LocalIndexSet localIndexSet; - int degree = GetDegree<Basis>::value; + int degree = getPolynomialDegree<Basis>; int f_deg; std::vector<value_type> values; }; - /// generator function for \ref DOFVectorFuncTerm expressions + /// Generator function for \ref DOFVectorFuncTerm expressions. + /** Generates a \ref DOFVectorFuncTerm, that takes a \ref DOFVector \p vector, + * a functor \p f that operators on the value type of the DOFVector, and + * optionally a degree argument \p deg that represents an (approximate) + * polynomial degree of the functor, for choosing the right quadrature degree. + **/ template <class DOFVectorType, class F> DOFVectorFuncTerm<std::decay_t<DOFVectorType>, std::decay_t<F>> valueOfFunc(DOFVectorType&& vector, F&& f, int deg = 1) @@ -294,8 +196,8 @@ namespace AMDiS // ----------------------------------------------------------------------------- - /// An expression that evalues a DOFVector at a given element, either on the - /// dofs or on the quadrature points + /// \brief An expression that evalues the gradient of a DOFVector at a given + /// element, either on the DOFs or on the quadrature points. \see gradientOf. template <class DOFVectorType> class GradientTerm { @@ -349,7 +251,7 @@ namespace AMDiS int getDegree() const { - return math::max(0, degree-1); + return Math::max(0, degree-1); } private: @@ -360,13 +262,17 @@ namespace AMDiS typename FeSpace::LocalView localView; typename FeSpace::LocalIndexSet localIndexSet; - int degree = GetDegree<FeSpace>::value; + int degree = getPolynomialDegree<FeSpace>; std::vector<value_type> values; }; - /// generator function for an expression of gradients of \ref DOFVectors + /// Generator function for an expression of gradients of \ref DOFVectors + /** Generates a \ref GradientTerm, that takes a \ref DOFVector \p vector, + * and an optional factor \p factor the value of the gradient of the + * DOFVector at the quadrature points are scaled with. + **/ template <class DOFVectorType> GradientTerm<std::decay_t<DOFVectorType>> gradientOf(DOFVectorType&& vector, double factor = 1.0) @@ -375,8 +281,8 @@ namespace AMDiS } - /// An expression that evalues a DOFVector at a given element, either on the - /// dofs or on the quadrature points + /// \brief An expression that evalues a partial derivative of a DOFVector + /// at a given element, either on the DOFs or on the quadrature points. \see derivativeOf. template <class DOFVectorType> class DerivativeTerm { @@ -436,7 +342,7 @@ namespace AMDiS int getDegree() const { - return math::max(0, degree-1); + return Math::max(0, degree-1); } private: @@ -450,13 +356,18 @@ namespace AMDiS typename FeSpace::LocalView localView; typename FeSpace::LocalIndexSet localIndexSet; - int degree = GetDegree<FeSpace>::value; + int degree = getPolynomialDegree<FeSpace>; std::vector<value_type> values; }; - /// generator function for an expression of partial derivatives of \ref DOFVectors + /// Generator function for an expression of partial derivatives of \ref DOFVectors + /** Generates a \ref DerivativeTerm, that takes a \ref DOFVector \p vector, + * a index representing the component of the gradient that should be returned, + * and an optional factor \p factor the value of the partial derivative of the + * DOFVector at the quadrature points are scaled with. + **/ template <class DOFVectorType> DerivativeTerm<std::decay_t<DOFVectorType>> derivativeOf(DOFVectorType&& vector, int component, double factor = 1.0) @@ -464,4 +375,6 @@ namespace AMDiS return {std::forward<DOFVectorType>(vector), component, factor}; } + /** @} **/ + } // end namespace AMDiS diff --git a/dune/amdis/terms/TermGenerator.hpp b/dune/amdis/terms/TermGenerator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..56169d29c9d9a1e9ea9fca74e385ecc062f41935 --- /dev/null +++ b/dune/amdis/terms/TermGenerator.hpp @@ -0,0 +1,120 @@ +/** \file TermGenerator.hpp */ + +#pragma once + +// std c++ includes +#include <type_traits> + +// AMDiS includes +#include <dune/amdis/terms/ConstantTerm.hpp> +#include <dune/amdis/terms/CoordsTerm.hpp> + +#include <dune/amdis/common/ConceptsBase.hpp> +#include <dune/amdis/common/ValueCategory.hpp> + +namespace AMDiS +{ + namespace Impl + { + // annonymous namespace to hide tags + namespace + { + struct _constant {}; + struct _functor {}; + struct _default {}; + } + + + template <class T> + constexpr bool ConstantCategory = + !std::is_same<ValueCategory_t<T>, tag::unknown>::value; + + + // TODO: generalize to functors with arbitrary return values +#ifndef AMDIS_DOW + template <class T> + constexpr bool FunctorCategory = + Concepts::Functor<T, double(Dune::FieldVector<double, 1>)> || + Concepts::Functor<T, double(Dune::FieldVector<double, 2>)> || + Concepts::Functor<T, double(Dune::FieldVector<double, 3>)>; +#else + template <class T> + constexpr bool FunctorCategory = + Concepts::Functor<T, double(Dune::FieldVector<double, AMDIS_DOW>)>; +#endif + + + // TODO: add concept for terms + template <class T> + using TermCategory = + std::conditional_t< ConstantCategory<T>, _constant, + std::conditional_t< FunctorCategory<T>, _functor, + /* OperatorTerms */ _default > >; + + + // forward declaration + template <class T, class Tag> struct ToTerm; + + template <class T> + struct ToTerm<T, _constant> + { + using type = ConstantTerm<T>; + + static type get(T const& t) + { + return {t}; + } + }; + + // if the argument is a functor, that takes a WorldVector + // and returns a double, see concept \ref CoordsFunctor. + template <class F> + struct ToTerm<F, _functor> + { + using type = CoordsTerm<F>; + + template <class F_> + static type get(F_&& f) + { + return {std::forward<F_>(f)}; + } + }; + + // if the argument is already a term return it directly. + template <class T> + struct ToTerm<T, _default> + { + using type = T const&; + + static constexpr type get(T const& t) + { + return t; + } + }; + + } // end namespace Impl + + + /// Generator class that takes a type as argument and returns the corresponding term-type. + /** The arguments are transformed into terms in the following way: + * - If type `T` is arithmetic or any small vector/matrix type, generate a + * constant term, see \ref ConstantTerm + * - If the type `T` models a Functor concepts, that maps a WorldVector to a + * double type, construct a \ref CoordsTerm + * - In all other cases, the argument is retured without modification. + **/ + template <class T> + using ToTerm = Impl::ToTerm<std::decay_t<T>, Impl::TermCategory<std::decay_t<T>> >; + + template <class T> + using ToTerm_t = std::decay_t<typename ToTerm<T>::type>; + + + /// Generator function for term transformation, \see ToTerm + template <class T> + inline typename ToTerm<T>::type toTerm(T&& t) + { + return ToTerm<T>::get(std::forward<T>(t)); + } + +} // end namespace AMDiS diff --git a/dune/amdis/utility/GetDegree.hpp b/dune/amdis/utility/GetDegree.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0f2b419b1ab3d0e33d133dbe8034842831fdf5bb --- /dev/null +++ b/dune/amdis/utility/GetDegree.hpp @@ -0,0 +1,40 @@ +#pragma once + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <dune/functions/functionspacebases/lagrangedgbasis.hh> +#include <dune/functions/functionspacebases/pqknodalbasis.hh> +#include <dune/functions/functionspacebases/pq1nodalbasis.hh> +#include <dune/functions/functionspacebases/taylorhoodbasis.hh> + +#include <dune/amdis/common/Mpl.hpp> + +namespace AMDiS +{ + namespace Impl + { + // helper class to extract the polynomial degree of a pqk nodal basis + template <class FeSpace> + struct GetDegree : int_<1> {}; + + template <class GV, int k, class ST> + struct GetDegree<Dune::Functions::PQkNodalBasis<GV, k, ST> > : int_<k> {}; + + template <class GV, int k, class ST> + struct GetDegree<Dune::Functions::LagrangeDGBasis<GV, k, ST> > : int_<k> {}; + + template <class GV, class ST> + struct GetDegree<Dune::Functions::PQ1NodalBasis<GV, ST> > : int_<1> {}; + + template <class GV, class ST> + struct GetDegree<Dune::Functions::TaylorHoodBasis<GV, ST> > : int_<2> {}; + + } // end namespace Impl + + /// \brief Return the polynomial degree of a given FESpace. Falls back to 1 if unknown. + template <class FeSpace> + constexpr int getPolynomialDegree = Impl::GetDegree<FeSpace>::value; + +} // end namespace AMDiS diff --git a/init/pfc.json.2d b/init/pfc.json.2d index 7591b4ea0fe1018b27ca7a6f6d3f952d0c363f77..2d38d18e96d8accb86e3acd2c6ad45fcfbe5a8c3 100644 --- a/init/pfc.json.2d +++ b/init/pfc.json.2d @@ -3,12 +3,12 @@ "pfcMesh": { "macro file name": "./macro/macro.stand.2d", - "global refinements": 4, + "global refinements": 5, "min corner": "0,0", "max corner": "1,1", "num cells": "2,2", - "dimension": "10,10" + "dimension": "50,50" }, "pfc": { @@ -20,6 +20,7 @@ "relative tolerance": 1e-6, "info": 10, "ell": 3, + "print cycle": 10, "right precon": "pfc" }, diff --git a/src/BlockPreconditioner.hpp b/src/BlockPreconditioner.hpp index f0539df185be49baf837e127c04c46e7e22daaa5..19dac416b354d49a41b9bc34c5af453b4b746b0e 100644 --- a/src/BlockPreconditioner.hpp +++ b/src/BlockPreconditioner.hpp @@ -23,6 +23,7 @@ namespace AMDiS A = &A_; A_.getRanges(rows, cols); + initialized = true; } virtual void solve(Vector const& b, Vector& x) const override @@ -35,18 +36,25 @@ namespace AMDiS AMDIS_ERROR_EXIT("Must be implemented in derived classes!\n"); } - mtl::irange const& getRowRange(size_t i) const + template <size_t I> + mtl::irange const& getRowRange(const index_<I> i = {}) const { - return rows[i]; + AMDIS_TEST_EXIT_DBG(initialized, + "BlockPreconditioner not initialized. Call init() before."); + return std::get<I>(rows); } - mtl::irange const& getColRange(size_t i) const + template <size_t I> + mtl::irange const& getColRange(const index_<I> i = {}) const { - return cols[i]; + AMDIS_TEST_EXIT_DBG(initialized, + "BlockPreconditioner not initialized. Call init() before."); + return std::get<I>(cols); } protected: Matrix const* A = NULL; + bool initialized = false; std::array<mtl::irange, Matrix::N()> rows; std::array<mtl::irange, Matrix::M()> cols; diff --git a/src/MTLPfcPrecon.hpp b/src/MTLPfcPrecon.hpp index 16d9db3063e99032aacac387d6770b5081b1e0cb..d86c667249f5c7305c17734ab01d9c6f3254a688 100644 --- a/src/MTLPfcPrecon.hpp +++ b/src/MTLPfcPrecon.hpp @@ -42,13 +42,13 @@ namespace AMDiS CreatorInterfaceName<LinearSolverType>* creator; - creator = named(CreatorMap<LinearSolverType>::getCreator(solverNameM, "precon_pfc->M->solver")); + creator = named( CreatorMap<LinearSolverType>::getCreator(solverNameM, "precon_pfc->M->solver") ); solverM = creator->create("precon_pfc->M"); - creator = named(CreatorMap<LinearSolverType>::getCreator(solverNameMpL, "precon_pfc->MpL->solver")); + creator = named( CreatorMap<LinearSolverType>::getCreator(solverNameMpL, "precon_pfc->MpL->solver") ); solverMpL = creator->create("precon_pfc->MpL"); - creator = named(CreatorMap<LinearSolverType>::getCreator(solverNameMpL2, "precon_pfc->MpL2->solver")); + creator = named( CreatorMap<LinearSolverType>::getCreator(solverNameMpL2, "precon_pfc->MpL2->solver") ); solverMpL2 = creator->create("precon_pfc->MpL2"); } @@ -83,19 +83,19 @@ namespace AMDiS void solveMpL(VectorX& x, const VectorB& b) const { SolverInfo solverInfo("precon_pfc->MpL"); - solverM->solve(MpL, x, b, solverInfo); + solverMpL->solve(MpL, x, b, solverInfo); } template <typename VectorX, typename VectorB> void solveMpL2(VectorX& x, const VectorB& b) const { SolverInfo solverInfo("precon_pfc->MpL2"); - solverM->solve(MpL2, x, b, solverInfo); + solverMpL2->solve(MpL2, x, b, solverInfo); } - MTLMatrix const& getM() const { return matM ? *matM : (*Super::A)(2_c,2_c); } // < u, v > - MTLMatrix const& getL0() const { return matL0 ? *matL0 : (*Super::A)(1_c,0_c); } // < M0*tau*grad(u), grad(v) > - MTLMatrix const& getL() const { return matL ? *matL : (*Super::A)(2_c,1_c); } // < grad(u), grad(v) > + MTLMatrix const& getM() const { return matM ? *matM : (*Super::A)(2_c, 2_c); } // < u, v > + MTLMatrix const& getL0() const { return matL0 ? *matL0 : (*Super::A)(1_c, 0_c); } // < M0*tau*grad(u), grad(v) > + MTLMatrix const& getL() const { return matL ? *matL : (*Super::A)(2_c, 1_c); } // < grad(u), grad(v) > double getTau() const { return *tau; } diff --git a/src/MTLPfcPrecon.inc.hpp b/src/MTLPfcPrecon.inc.hpp index 775553f94d66c8d1dd128b9c503ad5e48962b725..68cbdc7e9fe81848c3d8fefa9b097b0fb29ee4fc 100644 --- a/src/MTLPfcPrecon.inc.hpp +++ b/src/MTLPfcPrecon.inc.hpp @@ -4,17 +4,18 @@ namespace AMDiS template <class Matrix, class Vector> void MTLPfcPrecon<Matrix, Vector>::init(Matrix const& A) { - AMDIS_TEST_EXIT(tau != NULL, "Preconditioner not initialized!"); + AMDIS_TEST_EXIT(tau, "Preconditioner not initialized!"); Super::init(A); using size_type = typename MTLMatrix::size_type; size_type n = num_rows(getM()); double delta = std::sqrt(M0 * getTau()); + AMDIS_MSG("delta = " << delta); // helper-matrix MpL = M + delta*L MpL.change_dim(n, n); - MpL = getM() + (1.0/delta)*getL0(); + MpL = getM() + (1.0/delta) * getL0(); // helper-matrix MpL = M + sqrt(delta)*L MpL2.change_dim(n, n); @@ -32,13 +33,13 @@ namespace AMDiS { x.change_dim(num_rows(b)); - Vector x0(x[Super::getColRange(0)]); - Vector x1(x[Super::getColRange(1)]); - Vector x2(x[Super::getColRange(2)]); + Vector x0(x[Super::getColRange(0_c)]); + Vector x1(x[Super::getColRange(1_c)]); + Vector x2(x[Super::getColRange(2_c)]); - const Vector b0(b[Super::getRowRange(0)]); - const Vector b1(b[Super::getRowRange(1)]); - const Vector b2(b[Super::getRowRange(2)]); + const Vector b0(b[Super::getRowRange(0_c)]); + const Vector b1(b[Super::getRowRange(1_c)]); + const Vector b2(b[Super::getRowRange(2_c)]); double delta = std::sqrt(M0 * getTau()); @@ -54,7 +55,7 @@ namespace AMDiS tmp = getM() * y1; // tmp := M*y1 solveMpL2(x1, tmp); // (M+eps*sqrt(delta)K) * x1 = tmp - x0-= (1.0/delta)*x1; // x0 = x0 - (1/delta)*x1 = y0 + (1/delta)*(y1 - x1) + x0-= (1.0/delta)*x1; // x0 = x0 - (1/delta)*x1 = y0 + (1/delta)*(y1 - x1) tmp = b2 - getL() * x1; // tmp := b2 - K*x1 solveM(x2, tmp); diff --git a/src/amdis.cc b/src/amdis.cc index bb002d7ee188cf731fa04d2779d2ee9df925f45d..a231300dd68b173fff60737b68b06c61aa9e2d96 100644 --- a/src/amdis.cc +++ b/src/amdis.cc @@ -5,6 +5,7 @@ #include <dune/amdis/AMDiS.hpp> #include <dune/amdis/ProblemStat.hpp> +#include <dune/amdis/Terms.hpp> using namespace AMDiS; diff --git a/src/ellipt.cc b/src/ellipt.cc index 5019e89afb33b186add119114c5ef6c357407860..4260dc27f870efff043ed8b5e5e34bf3e1af1c1a 100644 --- a/src/ellipt.cc +++ b/src/ellipt.cc @@ -7,6 +7,7 @@ #include <dune/amdis/AdaptInstationary.hpp> #include <dune/amdis/ProblemInstat.hpp> #include <dune/amdis/ProblemStat.hpp> +#include <dune/amdis/Terms.hpp> #include <dune/amdis/common/Literals.hpp> using namespace AMDiS; diff --git a/src/heat.cc b/src/heat.cc index e7af6ef07901ff9ffe58c7fdda043fdf19d26861..5f251aca474b791fd2c5fbbb5a29a0b357391e98 100644 --- a/src/heat.cc +++ b/src/heat.cc @@ -7,6 +7,7 @@ #include <dune/amdis/AdaptInstationary.hpp> #include <dune/amdis/ProblemInstat.hpp> #include <dune/amdis/ProblemStat.hpp> +#include <dune/amdis/Terms.hpp> #include <dune/amdis/common/Literals.hpp> using namespace AMDiS; diff --git a/src/navier_stokes.cc b/src/navier_stokes.cc index aa4d01ac2c74ff117012b3d7e5aa34c20accbe39..32097eef327aa4192c77acb389e40289d349672f 100644 --- a/src/navier_stokes.cc +++ b/src/navier_stokes.cc @@ -6,6 +6,7 @@ #include <dune/amdis/AdaptInstationary.hpp> #include <dune/amdis/ProblemStat.hpp> #include <dune/amdis/ProblemInstat.hpp> +#include <dune/amdis/Terms.hpp> #ifdef DOW #undef DOW @@ -37,7 +38,7 @@ int main(int argc, char** argv) Parameters::get("stokes->boundary velocity", vel); using DOFVectorU = std::decay_t< decltype(prob.getSolution<0>()) >; - using DOFVectorP = std::decay_t< decltype(prob.getSolution<DOW>()) >; +// using DOFVectorP = std::decay_t< decltype(prob.getSolution<DOW>()) >; std::array<DOFVectorU*, DOW> velocity; For<0,DOW>::loop([&](auto const _i) { velocity[_i] = &prob.getSolution(_i); }); diff --git a/src/pfc.cc b/src/pfc.cc index 596b2939eabe78308e2a66e066c2e663663a1bf7..f0b2414d1bde787378c9fcec9dc30f728afcd8b9 100644 --- a/src/pfc.cc +++ b/src/pfc.cc @@ -9,32 +9,17 @@ #include <dune/amdis/AdaptInstationary.hpp> #include <dune/amdis/ProblemStat.hpp> #include <dune/amdis/ProblemInstat.hpp> +#include <dune/amdis/Terms.hpp> #include "MTLPfcPrecon.hpp" using namespace AMDiS; +using PfcParam = + DefaultTraitsMesh<Dune::YaspGrid<AMDIS_DIM>, AMDIS_DIM, AMDIS_DOW, 2, 2, 2>; -class PfcParam -{ - template <class Mesh, int deg> - using Lagrange = Dune::Functions::PQkNodalBasis<typename Mesh::LeafGridView, deg>; - - template <class Mesh, int... degs> - using FeSpaceTuple = std::tuple<Lagrange<Mesh, degs>...>; - -public: - static constexpr int dim = AMDIS_DIM; - static constexpr int dimworld = AMDIS_DOW; - static constexpr int nComponents = 3; - - // default values - using Mesh = Dune::YaspGrid<dim>; - using FeSpaces = FeSpaceTuple<Mesh, 2, 2, 2>; -}; // 3 component with polynomial degree 1 -// using PfcParam = ProblemStatTraits<AMDIS_DIM, AMDIS_DOW, 1, 1, 1>; using PfcProblem = ProblemStat<PfcParam>; using PfcProblemInstat = ProblemInstat<PfcParam>; @@ -67,19 +52,31 @@ int main(int argc, char** argv) auto& Nu = prob.getSolution<2>(); using Op = PfcProblem::OperatorType; - auto opLhs01 = std::make_shared<Op>(); // < [-(1+r) + 3*psi^2]*u, v > + < 2*grad(u), grad(v) > - opLhs01->addZOT( -(1.0 + r) ); - opLhs01->addZOT( valueOfFunc(Psi, [](auto psi) { return 3.0 * std::pow(psi,2); }, 2) ); - opLhs01->addSOT( 2.0 ); + + // < [-(1+r) - 3*psi^2]*u, v > + < 2*grad(u), grad(v) > + auto opLhs01_ = Op::create<0>( -(1.0 + r) ); + opLhs01_->addZOT( valueOfFunc(Psi, [](auto psi) { return -3.0 * Math::pow<2>(psi); }, 2) ); + opLhs01_->addSOT( 2.0 ); + auto opLhs01 = std::make_pair(opLhs01_, true); - auto opRhs0 = Op::create<0>(valueOfFunc(Psi, [](auto psi) { return -2.0 * std::pow(psi,3); }, 3)); // < -2*psi^3, v > + // < -2*psi^3, v > + auto opRhs0 = Op::create<0>(valueOfFunc(Psi, [](auto psi) { return -2.0 * Math::pow<3>(psi); }, 3)); + + // < psi, v > auto opRhs1 = Op::create<0>(valueOf(Psi)); - auto opM = Op::create<0>(1.0); // < u, v > - auto opL = Op::create<2>(1.0); // < grad(u), grad(v) > + // < u, v > + auto opM = std::make_pair(Op::create<0>(1.0), false); + // < grad(u), grad(v) > + auto opL = std::make_pair(Op::create<2>(1.0), false); + + // < M0*tau * grad(u), grad(v) > double* tauPtr = adaptInfo.getTimestepPtr(); - auto opL0= Op::create<2>([M0, tauPtr](auto) { return M0 * (*tauPtr); }); // < M0*tau * grad(u), grad(v) > + auto opL0= std::make_pair(Op::create<2>([M0, tauPtr](auto) { return M0 * (*tauPtr); }), false); + + + // === Define the linear system === prob.addMatrixOperator({{ {{0,0}, opM}, {{0,1}, opLhs01}, {{0,2}, opL}, {{1,0}, opL0}, {{1,1}, opM}, @@ -88,12 +85,13 @@ int main(int argc, char** argv) prob.addVectorOperator({{ {0, opRhs0}, {1, opRhs1} }}); - // initial solution + // === set the initial solution === Mu = 0.0; Nu = 0.0; std::srand( 12345 ); Psi.interpol([psi_mean](auto const& x) { return 0.5*(std::rand()/double(RAND_MAX) - 0.5) + psi_mean; }); + // === configure preconditioner, if necessary === if (creator->precon) { creator->precon->setData(adaptInfo.getTimestepPtr(), M0); } diff --git a/src/stokes.cc b/src/stokes.cc index ed842bd7d5926d66880164901555f6bbc369d479..f0359c192f77764d56b64311511bc51568ca8f94 100644 --- a/src/stokes.cc +++ b/src/stokes.cc @@ -4,6 +4,7 @@ #include <dune/amdis/AMDiS.hpp> #include <dune/amdis/ProblemStat.hpp> +#include <dune/amdis/Terms.hpp> #ifdef DOW #undef DOW