Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist ü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. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

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 @@
#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)`