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

added some more documentation of Gridfunctions

parent 52d5d039
Pipeline #1359 passed with stage
in 21 minutes and 7 seconds
......@@ -4,10 +4,10 @@
#include <iostream>
#include <amdis/AMDiS.hpp>
#include <amdis/Integrate.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp>
#include <amdis/common/Literals.hpp>
#include <amdis/gridfunctions/Integrate.hpp>
using namespace AMDiS;
using namespace Dune::Indices;
......
#pragma once
#include "config.h"
#include <dune/geometry/quadraturerules.hh>
#include <type_traits>
#include <dune/geometry/quadraturerules.hh>
#include <amdis/GridFunctions.hpp>
#include <amdis/common/Mpl.hpp>
namespace AMDiS
{
......@@ -31,6 +32,15 @@ namespace AMDiS
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
......@@ -47,26 +57,22 @@ namespace AMDiS
auto integrate(Expr&& expr, GridView const& 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,
"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>;
auto makeQuad = [](auto&& type, auto&& localFct) { return QuadratureRules::rule(type, order(localFct)); };
#if AMDIS_HAS_CXX_CONSTEXPR_IF
if constexpr(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
using Rules = Dune::QuadratureRules<typename GridView::ctype, GridView::dimension>;
auto makeQuad = [](auto&& t, auto&& lf) { return Rules::rule(t, order(lf)); };
return Impl::integrateImpl(std::forward<decltype(gridFct)>(gridFct), gridView, makeQuad,
bool_<expr_has_order>);
}
/// Integrate expression with quadrature rule provided
/// \brief Integrate expression with quadrature rule provided
/**
* **Example:**
* ```
......@@ -83,7 +89,8 @@ namespace AMDiS
[&](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:**
* ```
......@@ -94,11 +101,11 @@ namespace AMDiS
auto integrate(Expr&& expr, GridView const& gridView, int degree,
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);
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
......@@ -20,28 +20,38 @@ namespace AMDiS
class AnalyticLocalFunction<R(D), LocalContext, Function>
{
public:
using Range = R;
using Domain = D; // LocalDomain
/// The LocalDomain this LocalFunction can be evaluated in
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 };
private:
using Geometry = typename LocalContext::Geometry;
public:
/// \brief Constructor. stores the function `fct`.
AnalyticLocalFunction(Function const& fct)
: fct_{fct}
{}
/// \brief Create a geometry object from the element
void bind(LocalContext const& element)
{
geometry_.emplace(element.geometry());
}
/// \brief Releases the geometry object
void unbind()
{
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
{
assert( bool(geometry_) );
......@@ -58,8 +68,17 @@ namespace AMDiS
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,
REQUIRES(Concepts::HasOrder<F>)>
int order(AnalyticLocalFunction<Sig,LocalContext,F> const& lf)
......@@ -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>
auto derivative(AnalyticLocalFunction<R(D),LocalContext,F> const& lf)
{
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>);
......@@ -137,19 +166,38 @@ namespace AMDiS
private:
Function fct_;
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>
auto localFunction(AnalyticGridFunction<F,GV> const& gf)
{
return gf.localFunction();
}
/// \fn derivative
/// \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>
auto derivative(AnalyticGridFunction<F,GV> const& gf)
{
......@@ -189,8 +237,10 @@ namespace AMDiS
#endif
/// \fn evalAtQP \brief Generator function for AnalyticGridFunction. \relates AnalyticGridfunction
/// \fn evalAtQP
/// \brief Generator function for AnalyticGridFunction.
/**
* \relates AnalyticGridfunction
* \ingroup GridFunctions
* Evaluate a functor at global coordinates. See \ref AnalyticGridFunction.
*
......@@ -205,15 +255,4 @@ namespace AMDiS
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
......@@ -14,35 +14,45 @@
namespace AMDiS
{
/// \brief LocalFunction of a Gridfunction returning a constant value.
#ifndef DOXYGEN
template <class Signature, class LocalContext, class Function>
class ConstantLocalFunction;
#endif
/// \brief LocalFunction of a Gridfunction returning a constant value.
template <class R, class D, class LocalContext, class T>
class ConstantLocalFunction<R(D), LocalContext, T>
{
public:
using Range = R;
using Domain = D; // LocalDomain
/// The LocalDomain this LocalFunction can be evaluated in
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 };
private:
using Geometry = typename LocalContext::Geometry;
public:
/// \brief Constructor. Stores the constant value.
ConstantLocalFunction(T const& value)
: value_(value)
{}
void bind(LocalContext const& /*element*/) {}
void unbind() {}
void bind(LocalContext const& /*element*/) { /* do nothing */ }
void unbind() { /* do nothing */ }
/// Return the constant `value_`.
Range const& operator()(Domain const& /*local*/) const
{
return value_;
}
/// \brief Create a \ref ConstantLocalFunction representing the derivative
/// of a constant function, that ist, the value 0.
auto derivative() const
{
using RawSignature = typename Dune::Functions::SignatureTraits<R(D)>::RawSignature;
......@@ -51,6 +61,7 @@ namespace AMDiS
return ConstantLocalFunction<DerivativeRange(D),LocalContext,DerivativeRange>{diff};
}
/// Return the constant polynomial order 0.
int order() const
{
return 0;
......@@ -75,16 +86,12 @@ namespace AMDiS
}
/**
* \addtogroup GridFunctions
* @{
**/
/// \brief Gridfunction returning a constant value.
/**
* \ingroup GridFunctions
*
* 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
* modify the value after construction.
**/
......@@ -93,15 +100,14 @@ namespace AMDiS
{
public:
using EntitySet = Dune::Functions::GridViewEntitySet<GridView, 0>;
using Element = typename EntitySet::Element;
using Domain = typename EntitySet::GlobalCoordinate;
using LocalDomain = typename EntitySet::LocalCoordinate;
using Range = Underlying_t<T>;
enum { hasDerivative = false };
public:
private:
using Element = typename EntitySet::Element;
using LocalDomain = typename EntitySet::LocalCoordinate;
using LocalFunction = ConstantLocalFunction<Range(LocalDomain), Element, T>;
public:
......@@ -111,7 +117,7 @@ namespace AMDiS
, entitySet_(gridView)
{}
/// Return the evaluated functor at global coordinates
/// Return the constant `value_`
Range const& operator()(Domain const& /*x*/) const
{
return value_;
......@@ -122,6 +128,7 @@ namespace AMDiS
return entitySet_;
}
/// \brief Create an \ref ConstantLocalFunction with the stores `value_`.
LocalFunction localFunction() const
{
return {value_};
......@@ -132,14 +139,14 @@ namespace AMDiS
EntitySet entitySet_;
};
/// Return the LocalFunction of the \ref ConstantGridFunction. \relates ConstantGridFunction
/// \relates ConstantGridFunction
template <class T, class GV>
auto localFunction(ConstantGridFunction<T,GV> const& gf)
{
return gf.localFunction();
}
/** @} **/
namespace Concepts
......
......@@ -14,6 +14,7 @@ namespace AMDiS
* @{
**/
/// \class DerivativeGridFunction
/// \brief A Gridfunction that returns the derivative when calling localFunction.
/**
* Wrapps the GridFunction so that \ref localFunction returns a LocalFunction
......@@ -22,7 +23,8 @@ namespace AMDiS
* \tparam GridFunction The GridFunction that is wrapped.
*
* **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>
class DerivativeGridFunction
......@@ -50,7 +52,8 @@ namespace AMDiS
explicit DerivativeGridFunction(GridFunction const& 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
......@@ -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,
class LocalFct = decltype(localFunction(std::declval<GridFct>())),
REQUIRES(not GridFct::hasDerivative)>
auto derivative(GridFct const& gridFct)
{
static_assert(Concepts::HasDerivative<LocalFct>, "derivative(LocalFunction) not defined!");
static_assert(Concepts::HasDerivative<LocalFct>,
"derivative(LocalFunction) not defined!");
return DerivativeGridFunction<GridFct>{gridFct};
}
#ifndef DOXYGEN
template <class Expr>
struct DerivativePreGridFunction
{
......@@ -125,9 +142,12 @@ namespace AMDiS
#endif
/// \brief Generator function for DerivativeGridFunction expressions. \relates DerivativeGridFunction
/// \fn gradientAtQP
/// \brief Generator function for DerivativeGridFunction expressions.
/// \relates DerivativeGridFunction
/**
* Generates a derivative of a GridFunction. See \ref DerivativeGridFunction.
* Generates a Gridfunction representing the derivative of a GridFunction.
* See \ref DerivativeGridFunction.
*
* **Examples:**
* - `gradientAtQP(prob.getSolution(_0))`
......
......@@ -14,13 +14,17 @@
namespace AMDiS
{
/// \class DiscreteFunction
/// \brief A view on a subspace of a \ref DOFVector
/**
* \ingroup GridFunctions
*
* \tparam GB GlobalBasis type that models \ref Dune::Functions::Concept::GlobalBasis
* \tparam GB Type of the global basis
* \tparam VT Coefficient type of the DOFVector
* \tparam TP TreePath type a realization of \ref Dune::TypeTree::HybridTreePath
* \tparam TP A realization of \ref Dune::TypeTree::HybridTreePath
*
* **Requirements:**
* - GB models \ref Dune::Functions::Concept::GlobalBasis
**/
template <class GB, class VT, class TP>
class DiscreteFunction
......
......@@ -34,9 +34,10 @@ namespace AMDiS
} // end namespace Impl
// forward declaration
#ifndef DOXYGEN
template <class Signatur, class Functor, class... LocalFunctions>
class FunctorLocalFunction;
#endif
// implementation
template <class R, class D, class Functor, class... LocalFunctions>
......@@ -111,11 +112,16 @@ namespace AMDiS
std::tuple<LocalFunctionWrapper<LocalFunctions>...> localFcts_;
};
// Derivative of the LocalFunction of a FunctorGridFunction, utilizing
// the chain-rule. Only available of the functor provides partial derivatives.
/*
/// \fn derivative
/// \brief Derivative of the LocalFunction of a FunctorGridFunction, utilizing
/// the chain-rule. Only available if the functor provides partial derivatives.
/**
* \f$ d_x(f(lf(x)...)) = \sum_i d_i(f)[lf(x)...] * derivative(lf[i]) \f$
*/
*
* **Requirements:**
* - The Functor `F` must model `Concepts::HasPartial`
**/
template <class Sig, class F, class... LFs,
REQUIRES(Concepts::HasPartial<F>)>
auto derivative(FunctorLocalFunction<Sig,F,LFs...> const& lf)
......@@ -146,8 +152,14 @@ namespace AMDiS
}
// Calculate the polynomial order for functors f providing a free functions
// order(f, degs...), where degs are the order of the LocalFunctions.
/// \fn order
/// \brief Calculate the polynomial order of a functor `F` that provides a free
/// function order(f, degs...), where degs are the orders of the LocalFunctions.
/**
* **Requirements:**
* - The functor `F` must model `Concepts::HasFunctorOrder`
* - All localFunctions `LFs...` must model `Concepts::HasOrder`
**/
template <class Sig, class F, class... LFs,
REQUIRES(Concepts::HasFunctorOrder<F,sizeof...(LFs)>
&& all_of_v<Concepts::HasOrder<LFs>...>)>
......@@ -159,14 +171,12 @@ namespace AMDiS
}
/**
* \addtogroup GridFunctions
* @{
**/
/// \class FunctorGridFunction
/// \brief A Gridfunction that applies a functor to the evaluated Gridfunctions
/**
* Composition of GridFunctions `g_i` by applying a functor `f` locally, i.e. locally it is evaluated
* \ingroup GridFunctions
* Composition of GridFunctions `g_i` by applying a functor `f` locally, i.e.
* locally it is evaluated
* \f$ f(g_0(x), g_1(x), ...) \f$
*
* \tparam Functor The type of the outer functor `f`
......@@ -183,8 +193,10 @@ namespace AMDiS
public:
/// The result type of the functor when applied to the grid-functions
using Range = decltype(std::declval<Functor>()(std::declval<typename GridFunctions::Range>()...));
/// The argument type that can be applied to the grid-functions
using Domain = typename Impl::DomainType<GridFunctions...>::type;
/// The set of entities this grid-function binds to
using EntitySet = typename Impl::EntitySetType<GridFunctions...>::type;
......@@ -200,7 +212,7 @@ namespace AMDiS
public:
using LocalFunction = FunctorLocalFunction<RawRange(LocalDomain), Functor, LocalFct<GridFunctions>...>;
/// Constructor. Stores copies of the functor and gridfunctions.
/// \brief Constructor. Stores copies of the functor and gridfunctions.
template <class... GridFcts>
explicit FunctorGridFunction(Functor const& fct, GridFcts&&... gridFcts)
: fct_{fct}
......@@ -233,7 +245,9 @@ namespace AMDiS
};
/// \brief Creates a LocalFunction from the LocalFunctions of the GridFunctions. \relates FunctorLocalFunction
/// \fn localFunction
/// \brief Creates a LocalFunction from the LocalFunctions of the GridFunctions.
/// \relates FunctorLocalFunction
template <class F, class... GFs>
auto localFunction(FunctorGridFunction<F,GFs...> const& gf)
{
......@@ -252,6 +266,8 @@ namespace AMDiS
return FunctorGridFunction<Functor, GridFcts...>{f, gridFcts...};
}
#ifndef DOXYGEN
// PreGridFunction related to FunctorGridFunction.
template <class Functor, class... PreGridFunctions>
struct FunctorPreGridFunction
......@@ -287,11 +303,15 @@ namespace AMDiS
struct IsPreGridFunction<FunctorPreGridFunction<Functor, PreGridFcts...>>
: std::true_type {};
}
#endif
/// \brief Generator function for FunctorGridFunction. \relates FunctorGridFunction
/// \brief Generator function for FunctorGridFunction.
/// \relates FunctorGridFunction
/**
* Applies the functor `f` to the grid-functions `gridFcts...`. See \ref FunctorGridFunction.
* \ingroup GridFunctions
* Applies the functor `f` to the grid-functions `gridFcts...`.
* See \ref FunctorGridFunction.
*
* **Examples:**
* - `invokeAtQP([](Dune::FieldVector<double, 2> const& x) { return two_norm(x); }, X());`
......
......@@ -75,29 +75,29 @@ namespace AMDiS
} // end namespace Definition
/// \brief GridFunction F has free function `localFunction(F)`
template <class F>
constexpr bool HasLocalFunction = models<Definition::HasLocalFunction(F)>;
/// \brief GridFunction GF has free function `localFunction(GF)`
template <class GF>
constexpr bool HasLocalFunction = models<Definition::HasLocalFunction(GF)>;
/// \brief GridFunction F has free function `derivative(F)`
template <class F>
constexpr bool HasDerivative = models<Definition::HasDerivative(F)>;
/// \brief GridFunction GF has free function `derivative(F)`
template <class GF>
constexpr bool HasDerivative = models<Definition::HasDerivative(GF)>;
/// \brief GridFunction F has free function `derivative(localFunction(F))`
template <class F>
constexpr bool HasLocalFunctionDerivative = models<Definition::HasLocalFunctionDerivative(F)>;
/// \brief GridFunction GF has free function `derivative(localFunction(F))`
template <class GF>
constexpr bool HasLocalFunctionDerivative = models<Definition::HasLocalFunctionDerivative(GF)>;
/// \brief GridFunction F has free function `order(localFunction(F))`
template <class F>
constexpr bool HasLocalFunctionOrder = models<Definition::HasLocalFunctionOrder(F)>;
/// \brief GridFunction GF has free function `order(localFunction(F))`
template <class GF>
constexpr bool HasLocalFunctionOrder = models<Definition::HasLocalFunctionOrder(GF)>;
/// \brief Functor F has free function `partial(F,_0)`
template <class F>
constexpr bool HasPartial = models<Definition::HasPartial(F)>;
/// \brief Functor F has free function `order(F)`
template <class F>
constexpr bool HasOrder = models<Definition::HasOrder(F)>;
/// \brief LocalFuncion LF has free function `order(F)`
template <class LF>
constexpr bool HasOrder = models<Definition::HasOrder(LF)>;
/// \brief Functor F is collable with GlobalCoordinates `F(Dune::FieldVector<double,DOW>)`
......
......@@ -6,10 +6,8 @@
#include <amdis/AMDiS.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp>
#include <amdis/common/Literals.hpp>
#include <amdis/common/FieldMatVec.hpp>
#include <amdis/gridfunctions/Integrate.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/gridfunctions/DOFVectorView.hpp>
#include "Tests.hpp"
......
......@@ -4,11 +4,11 @@
#include <iostream>
#include <amdis/AMDiS.hpp>
#include <amdis/Integrate.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp>
#include <amdis/common/Literals.hpp>
#include <amdis/common/FieldMatVec.hpp>
#include <amdis/gridfunctions/Integrate.hpp>
using namespace AMDiS;
......
......@@ -6,11 +6,8 @@
#include <dune/geometry/type.hh>
#include <amdis/AMDiS.hpp>
#include <amdis/Integrate.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp>
#include <amdis/common/Literals.hpp>
#include <amdis/common/FieldMatVec.hpp>
#include <amdis/gridfunctions/Integrate.hpp>
#include "Tests.hpp"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment