Commit 6fa4facf authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

added some more documentation of Gridfunctions

parent 52d5d039
Pipeline #1359 passed with stage
in 21 minutes and 7 seconds
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
#include <iostream> #include <iostream>
#include <amdis/AMDiS.hpp> #include <amdis/AMDiS.hpp>
#include <amdis/Integrate.hpp>
#include <amdis/ProblemStat.hpp> #include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp> #include <amdis/Operators.hpp>
#include <amdis/common/Literals.hpp> #include <amdis/common/Literals.hpp>
#include <amdis/gridfunctions/Integrate.hpp>
using namespace AMDiS; using namespace AMDiS;
using namespace Dune::Indices; using namespace Dune::Indices;
......
#pragma once #pragma once
#include "config.h"
#include <dune/geometry/quadraturerules.hh>
#include <type_traits>
#include <dune/geometry/quadraturerules.hh>
#include <amdis/GridFunctions.hpp> #include <amdis/GridFunctions.hpp>
#include <amdis/common/Mpl.hpp>
namespace AMDiS namespace AMDiS
{ {
...@@ -31,6 +32,15 @@ namespace AMDiS ...@@ -31,6 +32,15 @@ namespace AMDiS
return result; return result;
} }
template <class GF, class GridView, class QuadProvider>
auto integrateImpl(GF&& gf, GridView const& gv, QuadProvider makeQuad, std::true_type)
{
return integrateImpl(std::forward<GF>(gf), gv, makeQuad);
}
template <class GF, class GV, class QP>
auto integrateImpl(GF&&, GV&&, QP&&, std::false_type) { return 0.0; }
} // end namespace Impl } // end namespace Impl
...@@ -47,26 +57,22 @@ namespace AMDiS ...@@ -47,26 +57,22 @@ namespace AMDiS
auto integrate(Expr&& expr, GridView const& gridView) auto integrate(Expr&& expr, GridView const& gridView)
{ {
auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView); auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView);
static const bool expr_has_order = Concepts::HasLocalFunctionOrder<std::decay_t<decltype(gridFct)>>;
// test whether the gridFct model `Concepts::HasLocalFunctionOrder`
using GF = std::decay_t<decltype(gridFct)>;
static const bool expr_has_order = Concepts::HasLocalFunctionOrder<GF>;
static_assert(expr_has_order, static_assert(expr_has_order,
"Polynomial degree of expression can not be deduced. You need to provide an explicit value for the quadrature degree or a quadrature rule in `integrate()`."); "Polynomial degree of expression can not be deduced. You need to provide an explicit value for the quadrature degree or a quadrature rule in `integrate()`.");
using QuadratureRules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>; using Rules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>;
auto makeQuad = [](auto&& type, auto&& localFct) { return QuadratureRules::rule(type, order(localFct)); }; auto makeQuad = [](auto&& t, auto&& lf) { return Rules::rule(t, order(lf)); };
#if AMDIS_HAS_CXX_CONSTEXPR_IF return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView, makeQuad,
if constexpr(expr_has_order) bool_<expr_has_order>);
return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView, makeQuad);
else
return 0.0;
#else
return Dune::Hybrid::ifElse(bool_<expr_has_order>,
[&](auto) { return Impl::integrateImpl(gridFct, gridView, makeQuad); },
[ ](auto) { return 0.0; });
#endif
} }
/// Integrate expression with quadrature rule provided
/// \brief Integrate expression with quadrature rule provided
/** /**
* **Example:** * **Example:**
* ``` * ```
...@@ -83,7 +89,8 @@ namespace AMDiS ...@@ -83,7 +89,8 @@ namespace AMDiS
[&](auto&&, auto&&) { return quad; }); [&](auto&&, auto&&) { return quad; });
} }
/// Integrate expression with quadrature rule determined by provided polynomial `degree`
/// \brief Integrate expression with quadrature rule determined by provided polynomial `degree`
/** /**
* **Example:** * **Example:**
* ``` * ```
...@@ -94,11 +101,11 @@ namespace AMDiS ...@@ -94,11 +101,11 @@ namespace AMDiS
auto integrate(Expr&& expr, GridView const& gridView, int degree, auto integrate(Expr&& expr, GridView const& gridView, int degree,
Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre) Dune::QuadratureType::Enum qt = Dune::QuadratureType::GaussLegendre)
{ {
using QuadratureRules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>; using Rules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>;
auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView); auto&& gridFct = makeGridFunction(std::forward<Expr>(expr), gridView);
return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView, return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView,
[&](auto const& type, auto&&) { return QuadratureRules::rule(type, degree, qt); }); [&](auto const& type, auto&&) { return Rules::rule(type, degree, qt); });
} }
} // end namespace AMDiS } // end namespace AMDiS
...@@ -20,28 +20,38 @@ namespace AMDiS ...@@ -20,28 +20,38 @@ namespace AMDiS
class AnalyticLocalFunction<R(D), LocalContext, Function> class AnalyticLocalFunction<R(D), LocalContext, Function>
{ {
public: public:
using Range = R; /// The LocalDomain this LocalFunction can be evaluated in
using Domain = D; // LocalDomain using Domain = D;
using Geometry = typename LocalContext::Geometry; /// The range type of the LocalFunction
using Range = R;
/// This LocalFunction has its own \ref derivative() function
enum { hasDerivative = true }; enum { hasDerivative = true };
private:
using Geometry = typename LocalContext::Geometry;
public: public:
/// \brief Constructor. stores the function `fct`.
AnalyticLocalFunction(Function const& fct) AnalyticLocalFunction(Function const& fct)
: fct_{fct} : fct_{fct}
{} {}
/// \brief Create a geometry object from the element
void bind(LocalContext const& element) void bind(LocalContext const& element)
{ {
geometry_.emplace(element.geometry()); geometry_.emplace(element.geometry());
} }
/// \brief Releases the geometry object
void unbind() void unbind()
{ {
geometry_.reset(); geometry_.reset();
} }
/// \brief Evaluate the function in global coordinate by a local-to-global
/// mapping of the local coordinates using the bound geometry object.
Range operator()(Domain const& local) const Range operator()(Domain const& local) const
{ {
assert( bool(geometry_) ); assert( bool(geometry_) );
...@@ -58,8 +68,17 @@ namespace AMDiS ...@@ -58,8 +68,17 @@ namespace AMDiS
Dune::Std::optional<Geometry> geometry_; Dune::Std::optional<Geometry> geometry_;
}; };
/// \brief Return the polynomial order of the function f, if a free function
/// order(f) exists, otherwise return a default value. \relates AnalyticLocalFunction /// \fn order
/// \brief Return the polynomial order of the LocalFunction.
/**
* \relates AnalyticLocalFunction
* The order is defined as the polynomial order of the functor `fct` and
* requires a free function `order(fct,1)` to exists.
*
* **Requirements:**
* - The functor `F` must fulfill the concept \ref Concepts::HasOrder
**/
template <class Sig, class LocalContext, class F, template <class Sig, class LocalContext, class F,
REQUIRES(Concepts::HasOrder<F>)> REQUIRES(Concepts::HasOrder<F>)>
int order(AnalyticLocalFunction<Sig,LocalContext,F> const& lf) int order(AnalyticLocalFunction<Sig,LocalContext,F> const& lf)
...@@ -68,11 +87,21 @@ namespace AMDiS ...@@ -68,11 +87,21 @@ namespace AMDiS
} }
/// \fn derivative
/// \brief Create an \ref AnalyticLocalFunction representing the derivative
/// of the given AnalyticLocalFunction.
/**
* In order to differentiate the local function, the functor must be
* differentiable, i.e. a free function `partial(fct,_0)` must exist.
*
* **Requirements:**
* - The functor `F` must fulfill the concept \ref Concepts::HasPartial
**/
template <class R, class D, class LocalContext, class F> template <class R, class D, class LocalContext, class F>
auto derivative(AnalyticLocalFunction<R(D),LocalContext,F> const& lf) auto derivative(AnalyticLocalFunction<R(D),LocalContext,F> const& lf)
{ {
static_assert(Concepts::HasPartial<F>, static_assert(Concepts::HasPartial<F>,
"No partial(_0,...) defined for Functor F of AnalyticLocalFunction."); "No partial(...,_0) defined for Functor F of AnalyticLocalFunction.");
auto df = partial(lf.fct(), index_<0>); auto df = partial(lf.fct(), index_<0>);
...@@ -137,19 +166,38 @@ namespace AMDiS ...@@ -137,19 +166,38 @@ namespace AMDiS
private: private:
Function fct_; Function fct_;
EntitySet entitySet_; EntitySet entitySet_;
}; };
// Creator for the AnalyticGridFunction
template <class Function>
struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>>
{
template <class GridView>
static auto create(Function const& fct, GridView const& gridView)
{
return AnalyticGridFunction<Function, GridView>{fct, gridView};
}
};
/// \fn localFunction
/// \brief Return the LocalFunction of the AnalyticGridFunction.
/// \relates AnalyticGridfunction
template <class F, class GV> template <class F, class GV>
auto localFunction(AnalyticGridFunction<F,GV> const& gf) auto localFunction(AnalyticGridFunction<F,GV> const& gf)
{ {
return gf.localFunction(); return gf.localFunction();
} }
/// \fn derivative
/// \brief Return a GridFunction representing the derivative of a functor. /// \brief Return a GridFunction representing the derivative of a functor.
// [expects: Functor f has free function derivative(f)] /**
* \relates AnalyticGridfunction
*
* **Requirements:**
* - Functor `F` must fulfill the concept \ref Concepts::HasPartial
**/
template <class F, class GV> template <class F, class GV>
auto derivative(AnalyticGridFunction<F,GV> const& gf) auto derivative(AnalyticGridFunction<F,GV> const& gf)
{ {
...@@ -189,8 +237,10 @@ namespace AMDiS ...@@ -189,8 +237,10 @@ namespace AMDiS
#endif #endif
/// \fn evalAtQP \brief Generator function for AnalyticGridFunction. \relates AnalyticGridfunction /// \fn evalAtQP
/// \brief Generator function for AnalyticGridFunction.
/** /**
* \relates AnalyticGridfunction
* \ingroup GridFunctions * \ingroup GridFunctions
* Evaluate a functor at global coordinates. See \ref AnalyticGridFunction. * Evaluate a functor at global coordinates. See \ref AnalyticGridFunction.
* *
...@@ -205,15 +255,4 @@ namespace AMDiS ...@@ -205,15 +255,4 @@ namespace AMDiS
return AnalyticPreGridFunction<Function>{f}; return AnalyticPreGridFunction<Function>{f};
} }
template <class Function>
struct GridFunctionCreator<Function, std::enable_if_t<Concepts::CallableDomain<Function>>>
{
template <class GridView>
static auto create(Function const& fct, GridView const& gridView)
{
return AnalyticGridFunction<Function, GridView>{fct, gridView};
}
};
} // end namespace AMDiS } // end namespace AMDiS
...@@ -14,35 +14,45 @@ ...@@ -14,35 +14,45 @@
namespace AMDiS namespace AMDiS
{ {
/// \brief LocalFunction of a Gridfunction returning a constant value. #ifndef DOXYGEN
template <class Signature, class LocalContext, class Function> template <class Signature, class LocalContext, class Function>
class ConstantLocalFunction; class ConstantLocalFunction;
#endif
/// \brief LocalFunction of a Gridfunction returning a constant value.
template <class R, class D, class LocalContext, class T> template <class R, class D, class LocalContext, class T>
class ConstantLocalFunction<R(D), LocalContext, T> class ConstantLocalFunction<R(D), LocalContext, T>
{ {
public: public:
using Range = R; /// The LocalDomain this LocalFunction can be evaluated in
using Domain = D; // LocalDomain using Domain = D;
using Geometry = typename LocalContext::Geometry; /// The range type of the LocalFunction
using Range = R;
/// This LocalFunction has its own \ref derivative() function
enum { hasDerivative = true }; enum { hasDerivative = true };
private:
using Geometry = typename LocalContext::Geometry;
public: public:
/// \brief Constructor. Stores the constant value.
ConstantLocalFunction(T const& value) ConstantLocalFunction(T const& value)
: value_(value) : value_(value)
{} {}
void bind(LocalContext const& /*element*/) {} void bind(LocalContext const& /*element*/) { /* do nothing */ }
void unbind() { /* do nothing */ }
void unbind() {}
/// Return the constant `value_`.
Range const& operator()(Domain const& /*local*/) const Range const& operator()(Domain const& /*local*/) const
{ {
return value_; return value_;
} }
/// \brief Create a \ref ConstantLocalFunction representing the derivative
/// of a constant function, that ist, the value 0.
auto derivative() const auto derivative() const
{ {
using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature; using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
...@@ -51,6 +61,7 @@ namespace AMDiS ...@@ -51,6 +61,7 @@ namespace AMDiS
return ConstantLocalFunction<DerivativeRange(D),LocalContext,DerivativeRange>{diff}; return ConstantLocalFunction<DerivativeRange(D),LocalContext,DerivativeRange>{diff};
} }
/// Return the constant polynomial order 0.
int order() const int order() const
{ {
return 0; return 0;
...@@ -75,16 +86,12 @@ namespace AMDiS ...@@ -75,16 +86,12 @@ namespace AMDiS
} }
/**
* \addtogroup GridFunctions
* @{
**/
/// \brief Gridfunction returning a constant value. /// \brief Gridfunction returning a constant value.
/** /**
* \ingroup GridFunctions
*
* A stored constant is return in global and local evaluation of this functor. * A stored constant is return in global and local evaluation of this functor.
* May be used with arithmetic types and vectors/matrices of arithmetic types. * Maybe used with arithmetic types and vectors/matrices of arithmetic types.
* It is also allowed to pass a \ref std::reference_wrapper to allow to * It is also allowed to pass a \ref std::reference_wrapper to allow to
* modify the value after construction. * modify the value after construction.
**/ **/
...@@ -93,15 +100,14 @@ namespace AMDiS ...@@ -93,15 +100,14 @@ namespace AMDiS
{ {
public: public:
using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>; using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;
using Element = typename EntitySet::Element;
using Domain = typename EntitySet::GlobalCoordinate; using Domain = typename EntitySet::GlobalCoordinate;
using LocalDomain = typename EntitySet::LocalCoordinate;
using Range = Underlying_t<T>; using Range = Underlying_t<T>;
enum { hasDerivative = false }; enum { hasDerivative = false };
public: private:
using Element = typename EntitySet::Element;
using LocalDomain = typename EntitySet::LocalCoordinate;
using LocalFunction = ConstantLocalFunction<Range(LocalDomain), Element, T>; using LocalFunction = ConstantLocalFunction<Range(LocalDomain), Element, T>;
public: public:
...@@ -111,7 +117,7 @@ namespace AMDiS ...@@ -111,7 +117,7 @@ namespace AMDiS
, entitySet_(gridView) , entitySet_(gridView)
{} {}
/// Return the evaluated functor at global coordinates /// Return the constant `value_`
Range const& operator()(Domain const& /*x*/) const Range const& operator()(Domain const& /*x*/) const
{ {
return value_; return value_;
...@@ -122,6 +128,7 @@ namespace AMDiS ...@@ -122,6 +128,7 @@ namespace AMDiS
return entitySet_; return entitySet_;
} }
/// \brief Create an \ref ConstantLocalFunction with the stores `value_`.
LocalFunction localFunction() const LocalFunction localFunction() const
{ {
return {value_}; return {value_};
...@@ -132,14 +139,14 @@ namespace AMDiS ...@@ -132,14 +139,14 @@ namespace AMDiS
EntitySet entitySet_; EntitySet entitySet_;
}; };
/// Return the LocalFunction of the \ref ConstantGridFunction. \relates ConstantGridFunction
/// \relates ConstantGridFunction
template <class T, class GV> template <class T, class GV>
auto localFunction(ConstantGridFunction<T,GV> const& gf) auto localFunction(ConstantGridFunction<T,GV> const& gf)
{ {
return gf.localFunction(); return gf.localFunction();
} }
/** @} **/
namespace Concepts namespace Concepts
......
...@@ -14,6 +14,7 @@ namespace AMDiS ...@@ -14,6 +14,7 @@ namespace AMDiS
* @{ * @{
**/ **/
/// \class DerivativeGridFunction
/// \brief A Gridfunction that returns the derivative when calling localFunction. /// \brief A Gridfunction that returns the derivative when calling localFunction.
/** /**
* Wrapps the GridFunction so that \ref localFunction returns a LocalFunction * Wrapps the GridFunction so that \ref localFunction returns a LocalFunction
...@@ -22,7 +23,8 @@ namespace AMDiS ...@@ -22,7 +23,8 @@ namespace AMDiS
* \tparam GridFunction The GridFunction that is wrapped. * \tparam GridFunction The GridFunction that is wrapped.
* *
* **Requirements:** * **Requirements:**
* - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction has a derivative. * - `GridFunction` models \ref Concepts::GridFunction and the LocalFunction
* has a derivative.
**/ **/
template <class GridFunction> template <class GridFunction>
class DerivativeGridFunction class DerivativeGridFunction
...@@ -50,7 +52,8 @@ namespace AMDiS ...@@ -50,7 +52,8 @@ namespace AMDiS
explicit DerivativeGridFunction(GridFunction const& gridFct) explicit DerivativeGridFunction(GridFunction const& gridFct)
: gridFct_{gridFct} : gridFct_{gridFct}
{ {
static_assert(isValidRange<DerivativeTraits>(), "Derivative of GridFunction not defined"); static_assert(isValidRange<DerivativeTraits>(),
"Derivative of GridFunction not defined");
} }
/// Evaluate derivative in global coordinates. NOTE: expensive /// Evaluate derivative in global coordinates. NOTE: expensive
...@@ -88,17 +91,31 @@ namespace AMDiS ...@@ -88,17 +91,31 @@ namespace AMDiS
}; };
#ifndef DOXYGEN /// \fn derivative
/// \brief Create a GridFunction representing the derivative of the given
/// Gridfunction.
/**
* A GridFunction can be differentiated if the corresponding LocalFunction
* provides a free function `derivative()`
*
* **Requirements:**
* - The type `GridFct` models the concept of a GridFunction
* - The `GridFct` has no own `derivative()` function, i.e. it holds
* `GridFct::hasDerivative == false`.
* - The localFunction of the `GridFct` models `Concepts::HasDerivative`.
**/
template <class GridFct, template <class GridFct,
class LocalFct = decltype(localFunction(std::declval<GridFct>())), class LocalFct = decltype(localFunction(std::declval<GridFct>())),
REQUIRES(not GridFct::hasDerivative)> REQUIRES(not GridFct::hasDerivative)>