Liebe Gitlab-Nutzerin, lieber Gitlab-Nutzer,
es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Die Konten der externen Nutzer:innen sind über den Reiter "Standard" erreichbar.
Die Administratoren


Dear Gitlab user,
it is now possible to log in to our service using the ZIH login/LDAP. The accounts of external users can be accessed via the "Standard" tab.
The administrators

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

expression and DirichletBC with lambda functions

parent 7bd09e85
......@@ -97,7 +97,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/DOFMatrix.cc
${SOURCE_DIR}/DOFVector.cc
${SOURCE_DIR}/Debug.cc
${SOURCE_DIR}/DirichletBC.cc
# ${SOURCE_DIR}/DirichletBC.cc
${SOURCE_DIR}/DualTraverse.cc
${SOURCE_DIR}/ElInfo.cc
${SOURCE_DIR}/ElInfo1d.cc
......
......@@ -28,6 +28,7 @@
#include <boost/numeric/mtl/mtl.hpp>
#include "OpenMP.h"
#include "Config.h"
namespace AMDiS {
......@@ -133,8 +134,12 @@ namespace AMDiS {
struct BoundaryObject;
struct AtomicBoundary;
#if HAS_VARIADIC_TEMPLATES
template<typename ReturnType, typename... Args > class AbstractFunction;
#else
template<typename ReturnType, typename ArgumentType> class AbstractFunction;
#endif
template<typename ReturnType,
typename ArgumentType1,
typename ArgumentType2> class BinaryAbstractFunction;
......@@ -153,6 +158,7 @@ namespace AMDiS {
template<typename T> class DOFVector;
template<typename T> class DimVec;
template<typename T> class DimMat;
template<typename T> class DirichletBC;
// template<typename ITLSolver> class ITL_LinearSolverInterface;
template<typename T, typename MatT, typename VecT > class ITL_Preconditioner;
template<typename T> class Matrix;
......
......@@ -32,43 +32,6 @@
#include <boost/preprocessor/repetition/repeat.hpp>
namespace AMDiS {
/**
* \ingroup Common
*
* \brief
* An AbstractFunction object represents a function
* f : ArgumentType -> ReturnType.
*
* AbstractFunction is a pure virtual class interface class.
* To create your own function you have to derive AbstractFunction and
* overload operator().
*/
// #ifndef HAS_VARIADIC_TEMPLATES
template<typename ReturnType, typename ArgumentType>
class AbstractFunction
{
public:
/// Constructor.
AbstractFunction(int degree = 0) :
degree_(degree)
{}
virtual ~AbstractFunction() {}
/// Returns \ref degree_.
inline int getDegree() const
{
return degree_;
}
/// Deligates the evaluation to overriden method f.
virtual ReturnType operator()(const ArgumentType& x) const = 0;
protected:
int degree_;
};
// #endif
/**
* \ingroup Common
......@@ -175,7 +138,68 @@ namespace AMDiS {
int degree_;
};
// #ifndef HAS_VARIADIC_TEMPLATES
#if HAS_VARIADIC_TEMPLATES
// C++11 implementation of AbstractFunction with arbitrary nr of arguments using variadic templates
/**
* \ingroup Common
*
* \brief
* An AbstractFunction object represents a function
* f : ArgumentTypes... -> ReturnType.
*
* AbstractFunction is a pure virtual class interface class.
* To create your own function you have to derive AbstractFunction and
* overload operator().
*/
template< typename ReturnType, typename... Args >
class AbstractFunction
{
public:
AbstractFunction(int degree = 0)
: degree_(degree)
{}
virtual ~AbstractFunction() {}
/// Returns \ref degree_.
inline int getDegree() const
{
return degree_;
}
/// function evaluation.
virtual ReturnType operator()(Args const&... args) const = 0;
protected:
int degree_;
};
#else
template<typename ReturnType, typename ArgumentType>
class AbstractFunction
{
public:
/// Constructor.
AbstractFunction(int degree = 0) :
degree_(degree)
{}
virtual ~AbstractFunction() {}
/// Returns \ref degree_.
inline int getDegree() const
{
return degree_;
}
/// Deligates the evaluation to overriden method f.
virtual ReturnType operator()(const ArgumentType& x) const = 0;
protected:
int degree_;
};
///////////////////////////////////////////////////////////////
// test of AbstractFunction with arbitrary number of arguments
......@@ -225,34 +249,8 @@ namespace AMDiS {
#endif
BOOST_PP_REPEAT_FROM_TO(1, 11, ABSTRACT_FUNCTION_MACRO, nil)
// #else
//
// /// C++11 implementation of abstract functions with arbitrary nr of arguments using variadic templates
// template< typename ReturnType, typename... Ts >
// class AbstractFunction
// {
// public:
// AbstractFunction(int degree = 0)
// : degree_(degree)
// {}
//
// virtual ~AbstractFunction() {}
//
// /// Returns \ref degree_.
// inline int getDegree() const
// {
// return degree_;
// }
//
// /// function evaluation.
// virtual ReturnType operator()(Ts const&... args) const = 0;
//
// protected:
// int degree_;
// };
//
// #endif
#endif
}
#endif // AMDIS_ABSTRACTFUNCTION_H
......@@ -72,21 +72,23 @@ namespace AMDiS {
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
for (int i = 0; i < nBasFcts; i++) {
if (localBound[i] == boundaryType) {
double value = 0.0;
if (f) {
if (f) {
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
value = (*f)(worldCoords);
} else {
if (dofVec)
value = (*dofVec)[dofIndices[i]];
else
ERROR_EXIT("There is something wrong!\n");
double value = (*f)(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
} else if (dofVec) {
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
double value = value = (*dofVec)[dofIndices[i]];
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
} else {
ERROR_EXIT("No data provided to assemble DirichletBC!\n");
}
}
......
......@@ -30,8 +30,49 @@
#include "AbstractFunction.h"
#include "FixVec.h"
namespace AMDiS {
namespace AMDiS
{
// some tags used for tag-dispatching
struct _value_by_abstractfunction {};
struct _value_by_dofvector {};
struct _value_by_function {};
namespace detail
{
template <class Tag>
struct ValueContainer {};
template <>
struct ValueContainer<_value_by_abstractfunction>
{
ValueContainer(AbstractFunction<double, WorldVector<double> > *fct) : value(*fct) {};
ValueContainer(AbstractFunction<double, WorldVector<double> > &fct) : value(fct) {};
AbstractFunction<double, WorldVector<double> > &value;
};
template <>
struct ValueContainer<_value_by_dofvector>
{
ValueContainer(DOFVectorBase<double> *vec) : value(vec) {};
ValueContainer(DOFVectorBase<double> &vec) : value(&vec) {};
DOFVectorBase<double> *value;
};
#if __cplusplus > 199711L
template <>
struct ValueContainer<_value_by_function>
{
ValueContainer(std::function<double(WorldVector<double>)> fct) : value(fct) {};
std::function<double(WorldVector<double>)> value;
};
#endif
} // end namespace detail
/**
* \ingroup Assembler
*
......@@ -41,6 +82,7 @@ namespace AMDiS {
* the row corresponding to a Dirichlet dof is replaced by a row containing
* only a 1.0 in the diagonal.
*/
template <class ValueTag>
class DirichletBC : public BoundaryCondition
{
public:
......@@ -50,6 +92,15 @@ namespace AMDiS {
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true);
#if __cplusplus > 199711L
/// Constructor.
DirichletBC(BoundaryType type,
std::function<double(WorldVector<double>)> fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true);
#endif
/// Constructor.
DirichletBC(BoundaryType type,
......@@ -57,18 +108,18 @@ namespace AMDiS {
bool apply = true);
/// Implementation of BoundaryCondition::fillBoundaryCondition().
void fillBoundaryCondition(DOFMatrix* matrix,
virtual void fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
int nBasFcts) override;
/// Implementation of BoundaryCondition::fillBoundaryCondition().
void fillBoundaryCondition(DOFVectorBase<double>* vector,
virtual void fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
int nBasFcts) override;
///
void initVector(DOFVectorBase<double>*);
......@@ -92,26 +143,31 @@ namespace AMDiS {
{
return applyBC;
}
inline AbstractFunction<double, WorldVector<double> > *getF()
{
return f;
}
inline DOFVectorBase<double> *getDOFVector()
{
return dofVec;
}
protected:
/// Function which is evaluated at world coords of Dirichlet dofs.
AbstractFunction<double, WorldVector<double> > *f;
///
WorldVector<double> worldCoords;
void fillBC(_value_by_abstractfunction,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
void fillBC(_value_by_function,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
void fillBC(_value_by_dofvector,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
/// DOFVector containing the boundary values
DOFVectorBase<double> *dofVec;
protected:
detail::ValueContainer<ValueTag> container;
/// Defines, if the boundary condition must be applied to the matrix. See
/// comment of \ref BoundaryCondition::applyBoundaryCondition.
......@@ -120,4 +176,6 @@ namespace AMDiS {
}
#include "DirichletBC.hh"
#endif
......@@ -36,8 +36,6 @@ namespace AMDiS {
#define MAX_DIM 3
#define MAX_DEGREE 4
template<typename ReturnType, typename ArgumentType> class AbstractFunction;
/** \ingroup FEMSpace
* \brief
* Lagrange basis functions. Sub class of BasisFunction
......
......@@ -1383,10 +1383,10 @@ namespace AMDiS {
boundaryConditionSet = true;
DirichletBC *dirichletApply =
new DirichletBC(type, b, componentSpaces[row], componentSpaces[col], true);
DirichletBC *dirichletNotApply =
new DirichletBC(type, b, componentSpaces[row], componentSpaces[col], false);
DirichletBC<_value_by_abstractfunction> *dirichletApply =
new DirichletBC<_value_by_abstractfunction>(type, b, componentSpaces[row], componentSpaces[col], true);
DirichletBC<_value_by_abstractfunction> *dirichletNotApply =
new DirichletBC<_value_by_abstractfunction>(type, b, componentSpaces[row], componentSpaces[col], false);
for (int i = 0; i < nComponents; i++)
if (systemMatrix && (*systemMatrix)[row][i]) {
......@@ -1402,6 +1402,38 @@ namespace AMDiS {
solution->getDOFVector(col)->getBoundaryManager()->addBoundaryCondition(dirichletApply);
}
#if __cplusplus > 199711L
void ProblemStatSeq::addDirichletBC(BoundaryType type, int row, int col,
std::function<double(WorldVector<double>)> b)
{
FUNCNAME("ProblemStat::addDirichletBC()");
TEST_EXIT(row >= 0 && row < nComponents)("Wrong row number: %d\n", row);
TEST_EXIT(col >= 0 && col < nComponents)("Wrong col number: %d\n", col);
boundaryConditionSet = true;
DirichletBC<_value_by_function> *dirichletApply =
new DirichletBC<_value_by_function>(type, b, componentSpaces[row], componentSpaces[col], true);
DirichletBC<_value_by_function> *dirichletNotApply =
new DirichletBC<_value_by_function>(type, b, componentSpaces[row], componentSpaces[col], false);
for (int i = 0; i < nComponents; i++)
if (systemMatrix && (*systemMatrix)[row][i]) {
if (i == col)
(*systemMatrix)[row][i]->getBoundaryManager()->addBoundaryCondition(dirichletApply);
else
(*systemMatrix)[row][i]->getBoundaryManager()->addBoundaryCondition(dirichletNotApply);
}
if (rhs)
rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(dirichletApply);
if (solution)
solution->getDOFVector(col)->getBoundaryManager()->addBoundaryCondition(dirichletApply);
}
#endif
void ProblemStatSeq::addDirichletBC(BoundaryType type, int row, int col,
DOFVector<double> *vec)
......@@ -1413,8 +1445,8 @@ namespace AMDiS {
boundaryConditionSet = true;
DirichletBC *dirichletApply = new DirichletBC(type, vec, true);
DirichletBC *dirichletNotApply = new DirichletBC(type, vec, false);
DirichletBC<_value_by_dofvector> *dirichletApply = new DirichletBC<_value_by_dofvector>(type, vec, true);
DirichletBC<_value_by_dofvector> *dirichletNotApply = new DirichletBC<_value_by_dofvector>(type, vec, false);
for (int i = 0; i < nComponents; i++)
if (systemMatrix && (*systemMatrix)[row][i]) {
......
......@@ -27,6 +27,9 @@
#include <vector>
#include <list>
#if __cplusplus > 199711L
#include <functional>
#endif
#include "AMDiS_fwd.h"
#include "ProblemStatBase.h"
#include "Initfile.h"
......@@ -188,6 +191,14 @@ namespace AMDiS {
/// abstract function.
virtual void addDirichletBC(BoundaryType type, int row, int col,
AbstractFunction<double, WorldVector<double> > *b);
#if __cplusplus > 199711L
/// Adds a Dirichlet boundary condition, where the rhs is given by an
/// lambda function or a std::function object
virtual void addDirichletBC(BoundaryType type, int row, int col,
std::function<double(WorldVector<double>)> b);
#endif
/// Adds a Dirichlet boundary condition, where the rhs is given by a DOF
/// vector.
......
......@@ -34,11 +34,7 @@
#include "add_expr.hpp" // add two expressions
#include "mult_expr.hpp" // multiply two expressions
#if HAS_VARIADIC_TEMPLATES && HAS_ALIAS_TEMPLATES
#include "functorN_expr.hpp" // apply a functor with arbitrary nr. of arguments to expressions
#else
#include "functor_expr.hpp" // apply a functor with 1/2/3 arguments to expressions
#endif
#include "functor_expr.hpp" // apply a functor with 1/2/3 arguments to expressions
#include "cmath_expr.hpp" // apply a cmath function to expressions
#include "vec_functors.hpp" // apply a vector function to expressions
......
......@@ -28,13 +28,14 @@
#include "AMDiS_fwd.h"
#include "LazyOperatorTerm.h"
#include "Functors.h"
#include "expressions/functor_expr.hpp"
// #include "expressions/functor_expr.hpp"
#include "operations/functors.hpp"
#include <boost/static_assert.hpp>
#include <tuple>
#include <utility>
#include <functional>
namespace AMDiS
{
......@@ -71,7 +72,66 @@ namespace AMDiS
template<typename... Int>
static int eval(F f, Int... d) { return f.getDegree(d...); }
};
}
// specialization for abstract-functions
template<typename R, typename... Args>
struct functor_degree<AbstractFunction<R, Args...> >
{
template<typename... Int>
static int eval(AbstractFunction<R, Args...> const& fct, Int... d) { return fct.getDegree(); }
};
template<typename R, typename Arg0, typename Arg1>
struct functor_degree<BinaryAbstractFunction<R, Arg0, Arg1> >
{
template<typename... Int>
static int eval(BinaryAbstractFunction<R, Arg0, Arg1> const& fct, Int... d) { return fct.getDegree(); }
};
template<typename R, typename Arg0, typename Arg1, typename Arg2>
struct functor_degree<TertiaryAbstractFunction<R, Arg0, Arg1, Arg2> >
{
template<typename... Int>
static int eval(TertiaryAbstractFunction<R, Arg0, Arg1, Arg2> const& fct, Int... d) { return fct.getDegree(); }
};
} // end namespace traits
namespace result_of
{
/// extract result type from function pointers
template <class FPtr>
struct Function;
template <class R, class C, class... As>
struct Function<R (C::*)(As...)>
{
typedef R result_type;
};
template<class R, class C, class... As>
struct Function<R (C::*)(As...) const>
{
typedef R type;
};
template<class T>
typename Function<T>::type function_helper(T);
/// extract result type from functors
template <class F>
struct Functor
{
typedef decltype(function_helper(&F::operator())) type;
};
template <class R, class... As>
struct Functor<std::function<R(As...)> >
{
typedef R type;
};
} // end namespace result_of
namespace detail
......@@ -167,7 +227,7 @@ namespace AMDiS
typedef LazyOperatorTerms<Terms...> super;
static const int N = sizeof...(Terms);
typedef typename traits::functor_result_type<F>::type value_type;
typedef typename result_of::Functor<F>::type value_type;
BOOST_STATIC_ASSERT_MSG( (!boost::is_same<value_type, traits::no_valid_type>::value), "********** ERROR: You have to define a result_type for your Functor **********" );
F f; ///< the functor
......@@ -210,50 +270,93 @@ namespace AMDiS
inline value_type operator()(const int& iq) const { return eval(iq, int_<N>()); }
};
template<typename F, typename Term>
using Function1 = FunctionN<F, Term>;
template<typename F, typename Term1, typename Term2>
using Function2 = FunctionN<F, Term1, Term2>;
template<typename F, typename Term1, typename Term2, typename Term3>
using Function3 = FunctionN<F, Term1, Term2, Term3>;
template<typename F, typename Term1, typename Term2, typename Term3, typename Term4>
using Function4 = FunctionN<F, Term1, Term2, Term3, Term4>;
/// A wrapper functor for AMDiS::AbstractFunctions
template<typename TOut, typename TIn>
struct Wrapper : public FunctorBase
{
typedef TOut result_type;
Wrapper(AbstractFunction<TOut, TIn>* fct_) : fct(fct_) {}
int getDegree(int degree) const { return fct->getDegree(); }
TOut operator()(const TIn& x) const
{
return (*fct)(x);
}
protected: