Commit 78ab6415 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Add generalized derivative and local-to-global adapter to handle the global derivatives uniformly

parent ae94a0e6
......@@ -10,7 +10,7 @@
#include <amdis/common/ConceptsBase.hpp>
#include <amdis/common/TypeTraits.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/AdaptInfo.hpp>
#include <amdis/Flag.hpp>
......
#pragma once
#include <dune/functions/common/defaultderivativetraits.hh>
namespace Dune
{
template <class K, int n>
class FieldVector;
template <class K, int n, int m>
class FieldMatrix;
}
namespace AMDiS
{
namespace tag
{
struct gradient {};
struct divergence {};
struct partial { std::size_t comp = 0; };
// register possible types for derivative traits
struct derivative_type : gradient, divergence, partial {};
}
template <class Sig, class Type>
struct DerivativeTraits;
template <class R, class D>
struct DerivativeTraits<R(D), tag::gradient>
: public Dune::Functions::DefaultDerivativeTraits<R(D)>
{};
template <class R, class D>
struct DerivativeTraits<R(D), tag::partial>
{
using Range = R;
};
template <class K, class D>
struct DerivativeTraits<K(D), tag::divergence>
{
// error
};
template <class K, int n, class D>
struct DerivativeTraits<Dune::FieldVector<K,n>(D), tag::divergence>
{
using Range = K;
};
template <class K, int n, int m, class D>
struct DerivativeTraits<Dune::FieldMatrix<K,n,m>(D), tag::divergence>
{
using Range = Dune::FieldVector<K,m>;
};
} // end namespace AMDiS
\ No newline at end of file
......@@ -7,7 +7,9 @@
#include <dune/functions/gridfunctions/gridviewentityset.hh>
#include <amdis/Operations.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/gridfunctions/Order.hpp>
namespace AMDiS
{
......@@ -97,20 +99,19 @@ namespace AMDiS
* **Requirements:**
* - The functor `F` must fulfill the concept \ref Concepts::HasPartial
**/
template <class R, class D, class LC, class F>
auto derivative(AnalyticLocalFunction<R(D),LC,F> const& lf)
template <class R, class D, class LC, class F, class Type>
auto derivative(AnalyticLocalFunction<R(D),LC,F> const& lf, Type const& type)
{
static_assert(Concepts::HasPartial<F>,
"No partial(...,_0) defined for Functor F of AnalyticLocalFunction.");
static_assert(Concepts::HasDerivative<F,Type>,
"No derivative(F,DerivativeType) defined for Functor F of AnalyticLocalFunction.");
auto df = partial(lf.fct(), index_<0>);
auto df = derivative(lf.fct(), type);
using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
using DerivativeSignature = typename Dune::Functions::DefaultDerivativeTraits<RawSignature>::Range(D);
using DerivativeSignature = typename DerivativeTraits<RawSignature,Type>::Range(D);
return AnalyticLocalFunction<DerivativeSignature,LC,decltype(df)>{df};
}
/// \class AnalyticGridFunction
/// \brief A Gridfunction that evaluates a function with global coordinates.
/**
......@@ -152,7 +153,7 @@ namespace AMDiS
}
/// Return the \ref AnalyticLocalFunction of the AnalyticGridFunction.
LocalFunction localFunction() const
LocalFunction makeLocalFunction() const
{
return {fct_};
}
......@@ -171,6 +172,30 @@ namespace AMDiS
EntitySet entitySet_;
};
namespace Concepts
{
namespace Definition
{
template <class F, int dow>
constexpr bool CallableDow =
Concepts::Callable<F, Dune::FieldVector<double, dow>>;
}
/// \brief Functor F is collable with GlobalCoordinates `F(Dune::FieldVector<double,DOW>)`
#ifndef WORLDDIM
template <class F>
constexpr bool CallableDomain =
Definition::CallableDow<F, 1> || Definition::CallableDow<F, 2> || Definition::CallableDow<F, 3>;
#else
template <class F>
constexpr bool CallableDomain =
Definition::CallableDow<F, WORLDDIM>;
#endif
} // end namespace Concepts
// Creator for the AnalyticGridFunction
template <class Function>
struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>>
......@@ -183,30 +208,21 @@ namespace AMDiS
};
/// \fn localFunction
/// \brief Return the LocalFunction of the AnalyticGridFunction.
/// \relates AnalyticGridfunction
template <class F, class GV>
auto localFunction(AnalyticGridFunction<F,GV> const& gf)
{
return gf.localFunction();
}
/// \fn derivative
/// \brief Return a GridFunction representing the derivative of a functor.
/**
* \relates AnalyticGridfunction
*
* **Requirements:**
* - Functor `F` must fulfill the concept \ref Concepts::HasPartial
* - Functor `F` must fulfill the concept \ref Concepts::HasDerivative<Type>
**/
template <class F, class GV>
auto derivative(AnalyticGridFunction<F,GV> const& gf)
template <class F, class GV, class Type>
auto derivative(AnalyticGridFunction<F,GV> const& gf, Type const& type)
{
static_assert(Concepts::HasPartial<F>,
"No partial(...,_0) defined for Functor of AnalyticLocalFunction.");
static_assert(Concepts::HasDerivative<F,Type>,
"No derivative(F,DerivativeType) defined for Functor of AnalyticLocalFunction.");
auto df = partial(gf.fct(), index_<0>);
auto df = derivative(gf.fct(), type);
return AnalyticGridFunction<decltype(df), GV>{df, gf.entitySet().gridView()};
}
......
......@@ -4,11 +4,14 @@ install(FILES
AnalyticGridFunction.hpp
ConstantGridFunction.hpp
CoordsGridFunction.hpp
Derivative.hpp
DerivativeGridFunction.hpp
DerivativeTraits.hpp
DiscreteFunction.hpp
DiscreteFunction.inc.hpp
DOFVectorView.hpp
FunctorGridFunction.hpp
GridFunctionConcepts.hpp
GridFunction.hpp
OperationsGridFunction.hpp
Order.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/gridfunctions)
......@@ -6,11 +6,11 @@
#include <dune/common/diagonalmatrix.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>
#include <dune/functions/common/defaultderivativetraits.hh>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/common/TypeTraits.hpp>
#include <amdis/gridfunctions/AnalyticGridFunction.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
namespace AMDiS
{
......@@ -53,10 +53,11 @@ namespace AMDiS
/// \brief Create a \ref ConstantLocalFunction representing the derivative
/// of a constant function, that ist, the value 0.
auto derivative() const
template <class Type>
auto makeDerivative(Type const& type) const
{
using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
using DerivativeRange = typename Dune::Functions::DefaultDerivativeTraits<RawSignature>::Range;
using DerivativeRange = typename DerivativeTraits<RawSignature,Type>::Range;
DerivativeRange diff(0);
return ConstantLocalFunction<DerivativeRange(D),LC,DerivativeRange>{diff};
}
......@@ -71,13 +72,6 @@ namespace AMDiS
T value_;
};
/// \relates ConstantLocalFunction
template <class R, class D, class LC, class T>
auto derivative(ConstantLocalFunction<R(D), LC, T> const& lf)
{
return lf.derivative();
}
/// \brief Gridfunction returning a constant value.
/**
......@@ -122,7 +116,7 @@ namespace AMDiS
}
/// \brief Create an \ref ConstantLocalFunction with the stores `value_`.
LocalFunction localFunction() const
LocalFunction makeLocalFunction() const
{
return {value_};
}
......@@ -133,14 +127,6 @@ namespace AMDiS
};
/// \relates ConstantGridFunction
template <class T, class GV>
auto localFunction(ConstantGridFunction<T,GV> const& gf)
{
return gf.localFunction();
}
namespace Concepts
{
/** \addtogroup Concepts
......
......@@ -5,6 +5,7 @@
#include <dune/common/diagonalmatrix.hh>
#include <dune/common/typeutilities.hh>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/AnalyticGridFunction.hpp>
namespace AMDiS
......@@ -48,7 +49,7 @@ namespace AMDiS
return Dune::DiagonalMatrix<T,N>{T(1)};
}
};
friend Derivative partial(CoordsFunction const& /*f*/, index_t<0>)
friend Derivative derivative(CoordsFunction const& /*f*/, tag::gradient)
{
return Derivative{};
}
......@@ -105,7 +106,7 @@ namespace AMDiS
int comp_;
};
friend Derivative partial(Self const& f, index_t<0>)
friend Derivative derivative(Self const& f, tag::gradient)
{
return Derivative{f.comp_};
}
......
#pragma once
#include <amdis/GridFunctions.hpp>
#include <amdis/functions/Interpolate.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
namespace AMDiS
{
......
#pragma once
#include <type_traits>
#include <amdis/common/Concepts.hpp>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/common/Index.hpp>
namespace AMDiS
{
/// The derivative of a localfunction as localfunction itself
template <class LocalFunction, class Type,
REQUIRES(std::is_convertible<tag::derivative_type, Type>::value),
class = void_t<decltype(std::declval<LocalFunction>().makeDerivative(std::declval<Type>()))> >
auto derivative(LocalFunction const& lf, Type const& type)
{
return lf.makeDerivative(type);
}
namespace Concepts
{
/** \addtogroup Concepts
* @{
**/
namespace Definition
{
struct HasDerivative
{
template <class F, class T>
auto requires_(F&& f, T&& t) -> decltype( derivative(f,t) );
};
struct HasLocalFunctionDerivative
{
template <class F, class T>
auto requires_(F&& f, T&& t) -> decltype( derivative(localFunction(f),t) );
};
struct HasPartial
{
template <class F, class I>
auto requires_(F&& f, I&& i) -> decltype( partial(f, i) );
};
} // end namespace Definition
/// \brief GridFunction GF has free function `derivative(F)`
template <class GF, class Type>
constexpr bool HasDerivative = models<Definition::HasDerivative(GF,Type)>;
/// \brief GridFunction GF has free function `derivative(localFunction(F))`
template <class GF, class Type>
constexpr bool HasLocalFunctionDerivative = models<Definition::HasLocalFunctionDerivative(GF,Type)>;
/// \brief Functor F has free function `partial(F,_0)`
template <class F>
constexpr bool HasPartial = models<Definition::HasPartial(F,index_t<0>)>;
/** @} **/
} // end namespace Concepts
} // end namespace AMDiS
......@@ -2,40 +2,65 @@
#include <type_traits>
#include <dune/functions/common/defaultderivativetraits.hh>
#include <dune/grid/utility/hierarchicsearch.hh>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
#include <amdis/common/Concepts.hpp>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/Derivative.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
namespace AMDiS
{
namespace Impl
{
template <class LF, class Sig>
struct CheckFunctorConcept
{
static_assert(Concepts::Functor<LF, Sig>, "Derivative of LocalFunction can not be called as a functor.");
};
template <class Traits>
struct CheckValidRange
{
static_assert(!std::is_same<typename Traits::Range, Dune::Functions::InvalidRange>::value, "Invalid Range.");
};
}
/// \class DerivativeGridFunction
/// \brief A Gridfunction that returns the derivative when calling localFunction.
/**
* \ingroup GridFunctions
* Wrapps the GridFunction so that \ref localFunction returns a LocalFunction
* Wraps the GridFunction so that \ref localFunction returns a LocalFunction
* representing the derivative of the LocalFunction of the GridFunction.
*
* \tparam GridFunction The GridFunction that is wrapped.
* \tparam The type of derivative, i.e. one of tag::gradient, tag::partial{i}, or tag::divergence
*
* **Requirements:**
* - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction
* has a derivative.
**/
template <class GridFunction>
template <class GridFunction, class Type>
class DerivativeGridFunction
{
using GridFctRange = typename GridFunction::Range;
using GridFctDomain = typename GridFunction::Domain;
using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature;
using DerivativeTraits = Dune::Functions::DefaultDerivativeTraits<RawSignature>;
using LocalFunction = TYPEOF( derivative(localFunction(std::declval<GridFunction>())) ) ;
using Traits = DerivativeTraits<RawSignature, Type>;
using LocalFunction = TYPEOF( derivative(localFunction(std::declval<GridFunction>()), std::declval<Type>()) ) ;
using LocalFctRange = typename Traits::Range;
using LocalFctDomain = typename GridFunction::EntitySet::LocalCoordinate;
using _CHECK1_ = Impl::CheckValidRange<Traits>;
using _CHECK2_ = Impl::CheckFunctorConcept<LocalFunction, LocalFctRange(LocalFctDomain)>;
enum { hasDerivative = false };
public:
/// The Range of the derivative of the GridFunction
using Range = typename DerivativeTraits::Range;
using Range = typename Traits::Range;
/// The domain of the GridFunction
using Domain = GridFctDomain;
......@@ -45,12 +70,10 @@ namespace AMDiS
public:
/// Constructor. Stores a copy of gridFct.
explicit DerivativeGridFunction(GridFunction const& gridFct)
explicit DerivativeGridFunction(GridFunction const& gridFct, Type const& type)
: gridFct_{gridFct}
{
static_assert(isValidRange<DerivativeTraits>(),
"Derivative of GridFunction not defined");
}
, type_{type}
{}
/// Evaluate derivative in global coordinates. NOTE: expensive
Range operator()(Domain const& x) const
......@@ -65,15 +88,15 @@ namespace AMDiS
auto element = hsearch.findEntity(x);
auto geometry = element.geometry();
auto localFct = derivative(localFunction(gridFct_));
auto localFct = makeLocalFunction();
localFct.bind(element);
return localFct(geometry.local(x));
}
/// Return the derivative-localFunction of the GridFunction.
friend LocalFunction localFunction(DerivativeGridFunction const& gf)
LocalFunction makeLocalFunction() const
{
return derivative(localFunction(gf.gridFct_));
return derivative(localFunction(gridFct_), type_);
}
/// Return the \ref EntitySet of the \ref GridFunction.
......@@ -84,6 +107,7 @@ namespace AMDiS
private:
GridFunction gridFct_;
Type type_;
};
......@@ -100,19 +124,19 @@ namespace AMDiS
* `GridFct::hasDerivative == false`.
* - The localFunction of the `GridFct` models `Concepts::HasDerivative`.
**/
template <class GridFct,
class LocalFct = decltype(localFunction(std::declval<GridFct>())),
template <class GridFct, class Type,
class LocalFct = decltype( localFunction(std::declval<GridFct>()) ),
REQUIRES(not GridFct::hasDerivative)>
auto derivative(GridFct const& gridFct)
auto derivative(GridFct const& gridFct, Type const& type)
{
static_assert(Concepts::HasDerivative<LocalFct>,
"derivative(LocalFunction) not defined!");
return DerivativeGridFunction<GridFct>{gridFct};
static_assert(Concepts::HasDerivative<LocalFct,Type>,
"derivative(LocalFunction,type) not defined!");
return DerivativeGridFunction<GridFct,Type>{gridFct, type};
}
#ifndef DOXYGEN
template <class Expr>
template <class Expr, class Type>
struct DerivativePreGridFunction
{
using Self = DerivativePreGridFunction;
......@@ -122,17 +146,18 @@ namespace AMDiS
template <class GridView>
static auto create(Self const& self, GridView const& gridView)
{
return derivative(makeGridFunction(self.expr_, gridView));
return derivative(makeGridFunction(self.expr_, gridView), self.type_);
}
};
Expr expr_;
Type type_ = {};
};
namespace Traits
{
template <class Expr>
struct IsPreGridFunction<DerivativePreGridFunction<Expr>>
template <class Expr,class Type>
struct IsPreGridFunction<DerivativePreGridFunction<Expr,Type>>
: std::true_type {};
}
#endif
......@@ -143,7 +168,7 @@ namespace AMDiS
/// \relates DerivativeGridFunction
/**
* \ingroup GridFunctions
* Generates a Gridfunction representing the derivative of a GridFunction.
* Generates a Gridfunction representing the gradient of a GridFunction.
* See \ref DerivativeGridFunction.
*
* **Examples:**
......@@ -153,7 +178,21 @@ namespace AMDiS
template <class Expr>
auto gradientAtQP(Expr const& expr)
{
return DerivativePreGridFunction<Expr>{expr};
return DerivativePreGridFunction<Expr, tag::gradient>{expr};
}
/// Generates a Gridfunction representing the divergence of a vector-valued GridFunction.
template <class Expr>
auto divergenceAtQP(Expr const& expr)
{
return DerivativePreGridFunction<Expr, tag::divergence>{expr};
}
/// Generates a Gridfunction representing the partial derivative of a GridFunction.
template <class Expr>
auto partialAtQP(Expr const& expr, std::size_t i)
{
return DerivativePreGridFunction<Expr, tag::partial>{expr, tag::partial{i}};
}
/** @} **/
......
......@@ -9,7 +9,6 @@
#include <dune/functions/gridfunctions/gridviewentityset.hh>
#include <dune/typetree/childextraction.hh>
#include <amdis/GridFunctions.hpp>
#include <amdis/LinearAlgebra.hpp>
#include <amdis/typetree/FiniteElementType.hpp>
#include <amdis/typetree/RangeType.hpp>
......@@ -60,7 +59,12 @@ namespace AMDiS
public:
/// A LocalFunction representing the derivative of the DOFVector on a bound element
template <class Type>
class DerivativeLocalFunctionBase;
class GradientLocalFunction;
class PartialLocalFunction;
class DivergenceLocalFunction;
/// A LocalFunction representing the value the DOFVector on a bound element
class LocalFunction;
......@@ -83,9 +87,9 @@ namespace AMDiS
Range operator()(Domain const& x) const;
/// \brief Create a local function for this view on the DOFVector. \relates LocalFunction
friend LocalFunction localFunction(DiscreteFunction const& self)
LocalFunction makeLocalFunction() const
{
return LocalFunction{self};
return LocalFunction{*this};
}
/// \brief Return a \ref Dune::Functions::GridViewEntitySet
......
#pragma once
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/common/FieldMatVec.hpp>
#include <amdis/utility/LocalBasisCache.hpp>
#include <amdis/utility/LocalToGlobalAdapter.hpp>
#include <dune/common/ftraits.hh>