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 @@ ...@@ -10,7 +10,7 @@
#include <amdis/common/ConceptsBase.hpp> #include <amdis/common/ConceptsBase.hpp>
#include <amdis/common/TypeTraits.hpp> #include <amdis/common/TypeTraits.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp> #include <amdis/gridfunctions/GridFunction.hpp>
#include <amdis/AdaptInfo.hpp> #include <amdis/AdaptInfo.hpp>
#include <amdis/Flag.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 @@ ...@@ -7,7 +7,9 @@
#include <dune/functions/gridfunctions/gridviewentityset.hh> #include <dune/functions/gridfunctions/gridviewentityset.hh>
#include <amdis/Operations.hpp> #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 namespace AMDiS
{ {
...@@ -97,20 +99,19 @@ namespace AMDiS ...@@ -97,20 +99,19 @@ namespace AMDiS
* **Requirements:** * **Requirements:**
* - The functor `F` must fulfill the concept \ref Concepts::HasPartial * - The functor `F` must fulfill the concept \ref Concepts::HasPartial
**/ **/
template <class R, class D, class LC, class F> template <class R, class D, class LC, class F, class Type>
auto derivative(AnalyticLocalFunction<R(D),LC,F> const& lf) auto derivative(AnalyticLocalFunction<R(D),LC,F> const& lf, Type const& type)
{ {
static_assert(Concepts::HasPartial<F>, static_assert(Concepts::HasDerivative<F,Type>,
"No partial(...,_0) defined for Functor F of AnalyticLocalFunction."); "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 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}; return AnalyticLocalFunction<DerivativeSignature,LC,decltype(df)>{df};
} }
/// \class AnalyticGridFunction /// \class AnalyticGridFunction
/// \brief A Gridfunction that evaluates a function with global coordinates. /// \brief A Gridfunction that evaluates a function with global coordinates.
/** /**
...@@ -152,7 +153,7 @@ namespace AMDiS ...@@ -152,7 +153,7 @@ namespace AMDiS
} }
/// Return the \ref AnalyticLocalFunction of the AnalyticGridFunction. /// Return the \ref AnalyticLocalFunction of the AnalyticGridFunction.
LocalFunction localFunction() const LocalFunction makeLocalFunction() const
{ {
return {fct_}; return {fct_};
} }
...@@ -171,6 +172,30 @@ namespace AMDiS ...@@ -171,6 +172,30 @@ namespace AMDiS
EntitySet entitySet_; 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 // Creator for the AnalyticGridFunction
template <class Function> template <class Function>
struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>> struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>>
...@@ -183,30 +208,21 @@ namespace AMDiS ...@@ -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 /// \fn derivative
/// \brief Return a GridFunction representing the derivative of a functor. /// \brief Return a GridFunction representing the derivative of a functor.
/** /**
* \relates AnalyticGridfunction * \relates AnalyticGridfunction
* *
* **Requirements:** * **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> template <class F, class GV, class Type>
auto derivative(AnalyticGridFunction<F,GV> const& gf) auto derivative(AnalyticGridFunction<F,GV> const& gf, Type const& type)
{ {
static_assert(Concepts::HasPartial<F>, static_assert(Concepts::HasDerivative<F,Type>,
"No partial(...,_0) defined for Functor of AnalyticLocalFunction."); "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()}; return AnalyticGridFunction<decltype(df), GV>{df, gf.entitySet().gridView()};
} }
......
...@@ -4,11 +4,14 @@ install(FILES ...@@ -4,11 +4,14 @@ install(FILES
AnalyticGridFunction.hpp AnalyticGridFunction.hpp
ConstantGridFunction.hpp ConstantGridFunction.hpp
CoordsGridFunction.hpp CoordsGridFunction.hpp
Derivative.hpp
DerivativeGridFunction.hpp DerivativeGridFunction.hpp
DerivativeTraits.hpp
DiscreteFunction.hpp DiscreteFunction.hpp
DiscreteFunction.inc.hpp DiscreteFunction.inc.hpp
DOFVectorView.hpp DOFVectorView.hpp
FunctorGridFunction.hpp FunctorGridFunction.hpp
GridFunctionConcepts.hpp GridFunction.hpp
OperationsGridFunction.hpp OperationsGridFunction.hpp
Order.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/gridfunctions) DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/gridfunctions)
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
#include <dune/common/diagonalmatrix.hh> #include <dune/common/diagonalmatrix.hh>
#include <dune/common/fmatrix.hh> #include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh> #include <dune/common/fvector.hh>
#include <dune/functions/common/defaultderivativetraits.hh>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/common/TypeTraits.hpp> #include <amdis/common/TypeTraits.hpp>
#include <amdis/gridfunctions/AnalyticGridFunction.hpp> #include <amdis/gridfunctions/AnalyticGridFunction.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp> #include <amdis/gridfunctions/GridFunction.hpp>
namespace AMDiS namespace AMDiS
{ {
...@@ -53,10 +53,11 @@ namespace AMDiS ...@@ -53,10 +53,11 @@ namespace AMDiS
/// \brief Create a \ref ConstantLocalFunction representing the derivative /// \brief Create a \ref ConstantLocalFunction representing the derivative
/// of a constant function, that ist, the value 0. /// 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 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); DerivativeRange diff(0);
return ConstantLocalFunction<DerivativeRange(D),LC,DerivativeRange>{diff}; return ConstantLocalFunction<DerivativeRange(D),LC,DerivativeRange>{diff};
} }
...@@ -71,13 +72,6 @@ namespace AMDiS ...@@ -71,13 +72,6 @@ namespace AMDiS
T value_; 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. /// \brief Gridfunction returning a constant value.
/** /**
...@@ -122,7 +116,7 @@ namespace AMDiS ...@@ -122,7 +116,7 @@ namespace AMDiS
} }
/// \brief Create an \ref ConstantLocalFunction with the stores `value_`. /// \brief Create an \ref ConstantLocalFunction with the stores `value_`.
LocalFunction localFunction() const LocalFunction makeLocalFunction() const
{ {
return {value_}; return {value_};
} }
...@@ -133,14 +127,6 @@ namespace AMDiS ...@@ -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 namespace Concepts
{ {
/** \addtogroup Concepts /** \addtogroup Concepts
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <dune/common/diagonalmatrix.hh> #include <dune/common/diagonalmatrix.hh>
#include <dune/common/typeutilities.hh> #include <dune/common/typeutilities.hh>
#include <amdis/common/DerivativeTraits.hpp>
#include <amdis/gridfunctions/AnalyticGridFunction.hpp> #include <amdis/gridfunctions/AnalyticGridFunction.hpp>
namespace AMDiS namespace AMDiS
...@@ -48,7 +49,7 @@ namespace AMDiS ...@@ -48,7 +49,7 @@ namespace AMDiS
return Dune::DiagonalMatrix<T,N>{T(1)}; 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{}; return Derivative{};
} }
...@@ -105,7 +106,7 @@ namespace AMDiS ...@@ -105,7 +106,7 @@ namespace AMDiS
int comp_; int comp_;
}; };
friend Derivative partial(Self const& f, index_t<0>) friend Derivative derivative(Self const& f, tag::gradient)
{ {
return Derivative{f.comp_}; return Derivative{f.comp_};
} }
......
#pragma once #pragma once
#include <amdis/GridFunctions.hpp>
#include <amdis/functions/Interpolate.hpp> #include <amdis/functions/Interpolate.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp> #include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/gridfunctions/GridFunction.hpp>
namespace AMDiS 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 @@ ...@@ -2,40 +2,65 @@
#include <type_traits> #include <type_traits>
#include <dune/functions/common/defaultderivativetraits.hh>
#include <dune/grid/utility/hierarchicsearch.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 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 /// \class DerivativeGridFunction
/// \brief A Gridfunction that returns the derivative when calling localFunction. /// \brief A Gridfunction that returns the derivative when calling localFunction.
/** /**
* \ingroup GridFunctions * \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. * representing the derivative of the LocalFunction of the GridFunction.
* *
* \tparam GridFunction The GridFunction that is wrapped. * \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:** * **Requirements:**
* - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction * - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction
* has a derivative. * has a derivative.
**/ **/
template <class GridFunction> template <class GridFunction, class Type>
class DerivativeGridFunction class DerivativeGridFunction
{ {
using GridFctRange = typename GridFunction::Range; using GridFctRange = typename GridFunction::Range;
using GridFctDomain = typename GridFunction::Domain; using GridFctDomain = typename GridFunction::Domain;
using RawSignature = typename Dune::Functions::SignatureTraits<GridFctRange(GridFctDomain)>::RawSignature; 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 }; enum { hasDerivative = false };
public: public:
/// The Range of the derivative of the GridFunction /// The Range of the derivative of the GridFunction
using Range = typename DerivativeTraits::Range; using Range = typename Traits::Range;
/// The domain of the GridFunction /// The domain of the GridFunction
using Domain = GridFctDomain; using Domain = GridFctDomain;
...@@ -45,12 +70,10 @@ namespace AMDiS ...@@ -45,12 +70,10 @@ namespace AMDiS
public: public:
/// Constructor. Stores a copy of gridFct. /// Constructor. Stores a copy of gridFct.
explicit DerivativeGridFunction(GridFunction const& gridFct) explicit DerivativeGridFunction(GridFunction const& gridFct, Type const& type)
: gridFct_{gridFct} : gridFct_{gridFct}
{ , type_{type}
static_assert(isValidRange<DerivativeTraits>(), {}
"Derivative of GridFunction not defined");
}
/// Evaluate derivative in global coordinates. NOTE: expensive /// Evaluate derivative in global coordinates. NOTE: expensive
Range operator()(Domain const& x) const Range operator()(Domain const& x) const
...@@ -65,15 +88,15 @@ namespace AMDiS ...@@ -65,15 +88,15 @@ namespace AMDiS
auto element = hsearch.findEntity(x); auto element = hsearch.findEntity(x);
auto geometry = element.geometry(); auto geometry = element.geometry();
auto localFct = derivative(localFunction(gridFct_)); auto localFct = makeLocalFunction();
localFct.bind(element); localFct.bind(element);
return localFct(geometry.local(x)); return localFct(geometry.local(x));
} }
/// Return the derivative-localFunction of the GridFunction. /// 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. /// Return the \ref EntitySet of the \ref GridFunction.
...@@ -84,6 +107,7 @@ namespace AMDiS ...@@ -84,6 +107,7 @@ namespace AMDiS
private: