diff --git a/slides/img/example_compile_parameters.png b/slides/img/example_compile_parameters.png new file mode 100644 index 0000000000000000000000000000000000000000..03862548bed99983352da7689f04587b596c633a Binary files /dev/null and b/slides/img/example_compile_parameters.png differ diff --git a/slides/img/typetag_hierarchy.png b/slides/img/typetag_hierarchy.png new file mode 100644 index 0000000000000000000000000000000000000000..c6680c0490f74515051d8ad19a7ec7ef2ac77900 Binary files /dev/null and b/slides/img/typetag_hierarchy.png differ diff --git a/slides/img/typetag_hierarchy_2p_incompressible.png b/slides/img/typetag_hierarchy_2p_incompressible.png new file mode 100644 index 0000000000000000000000000000000000000000..5544ac6d5d4ff345e8281454bd54d5b0ba4b24cf Binary files /dev/null and b/slides/img/typetag_hierarchy_2p_incompressible.png differ diff --git a/slides/img/typetag_nodes.png b/slides/img/typetag_nodes.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1239c9f277b8833ce402139cf49a15409e8b5c Binary files /dev/null and b/slides/img/typetag_nodes.png differ diff --git a/slides/img/typetag_nodes_example.png b/slides/img/typetag_nodes_example.png new file mode 100644 index 0000000000000000000000000000000000000000..a7c025b5a8d84dbd95de596592cbd35e8515db6e Binary files /dev/null and b/slides/img/typetag_nodes_example.png differ diff --git a/slides/properties.md b/slides/properties.md new file mode 100644 index 0000000000000000000000000000000000000000..2933763a825348e34dd6b17a759d2ae2fba30ad1 --- /dev/null +++ b/slides/properties.md @@ -0,0 +1,315 @@ +--- +title: The DuMuX property system +subtitle: Flexible compile-time parameters +--- + +# Parameters vs. properties + +## Parameters vs. properties + +- <span style="color:#3498DB">Parameters</span> are set at __run-time__ + <p>A default value may be used if the user does not provide one run-time</p> +- <span style="color:#3498DB">Properties</span> are known and set at __compile-time__ + <p> + Can be used e.g. as template parameters (__types__ or values with `constexpr` specifier); + No run-time penalty, enable compiler to optimize + </p> + +## Template parameters + +- C++ supports _generic programming_ via __templates__ + - e.g. classes defined in terms of other types + - concrete versions of templates are stamped out upon compilation +- __Flexible__: implementation not restricted to _concrete types_ +- __Efficient__: decisions made at compile-time + +## Template parameters + +An example - `std::vector` + +```cpp +// Declaration of the class template, usable with any +// `T` that fulfills the requirements that `vector` poses on it. +template<typename T, typename A = std::allocator<T>> +class vector; + + +// Instantiation of a concrete vector - a vector of ints. +// The compiler will define this concrete type for us, +// using the definition of the class template. +std::vector<int> v; +``` + +## Template specializations + +Template implementations can be specialized for concrete types + +```cpp +template<typename T> +class MyVector +{ + // Generic implementation for any T +}; + +template<> +class MyClass<int> +{ + // specialized implementation for `int` +}; +``` + +## Too many template parameters + +For some classes, providing all template parameters can be very cumbersome and error-prone. + +```cpp +// Example from dune-pdelab. 9 template parameters! +using GOF0 = Dune::GridOperator< + GFS, GFS, LOP, MBE, + RF, RF, RF, + CF, CF +>; + +DGGO2 dggo2(gfs, cd, gfs, cf, lop, mbe); +``` + +## Traits classes + +A usual way to group template parameters + +```cpp +struct MyGridOperatorTraits{ + using FromGFS = ...; + // ... +}; + +using GOF0 = Dune::PDELab::GridOperator<MyGridOperatorTraits>; +``` + +## Inheriting from traits classes + +Inheritance may lead to unexpected results + +```cpp +struct MyBaseTraits +{ + using Scalar = int; + using Vector = std::vector<Scalar>; +}; + +struct MyDoubleTraits : public MyBaseTraits +{ + using Scalar = double; +}; + +// this is a vector of ints! +typename MyDoubleTraits::vector v{1.14142, 1.73205}; +``` + +## Type traits + +Based on template specialization + +```cpp +// Trait class template declaration +template<typename T> struct ValueType; + +// Specialization for vectors of T +template<typename T, typename Allocator> +struct ValueType<std::vector<T, Allocator>> { using type = T; }; + +// Specialization for Dune::FieldVector +template<typename T, int size> +struct ValueType<Dune::FieldVector<T, size>> { using type = T; }; +``` + +# The DuMuX Property System + +## Property System Design + +- Based on __C++ template specialization__ (_type traits_) +- A hierarchy of nodes -- called __type tags__ -- is defined. All parameters are labeled and attached to the appropriate nodes in this acyclic graph. +- The labels are called **property tags**, whereas the parameters actually attached are called **properties**. +- The definition of properties may **depend on** arbitrary other properties, which may be **overwritten** at any higher node of acyclic graph. +- The only requirement for properties is that they may not exhibit **cyclic dependencies**. + + +## Better than traits classes? + +Let's implement the previous example using the property system. +Step I: define a `BaseTag` + +```cpp +namespace TTag{ struct BaseTag; } + +// specialization of the Scalar property for BaseTag +template<class TypeTag> +struct Scalar<TypeTag, TTag::BaseTag> { using type = int; }; + +// specialization of the Vector property for BaseTag +template<class TypeTag> +struct Vector<TypeTag, TTag::BaseTag> +{ + using type = std::vector< + GetPropType<TypeTag, Properties::Scalar> + >; +}; +``` + +## Better than traits classes? + +Step II: derive from `BaseTag` and overwrite the `Scalar` property + +```cpp +struct DoubleTag { using InheritsFrom = std::tuple<BaseTag>; }; + +// Specialization of the Scalar property for DoubleTag +template<class TypeTag> +struct Scalar<TypeTag, TTag::DoubleTag> +{ using type = double; }; +``` + +```cpp +// using the property +using Vector = GetPropType<DoubleTag, Properties::Vector>; +Vector v{1.41421, 1.73205}; // v is a std::vector<double>! +``` + +## Using __type tags__ as traits classes + +```cpp +struct BaseTag +{ + using Scalar = double; + + // Important: do not directly use Scalar here as it would + // break the possibility to overwrite it in a child node + template<typename TypeTag> + using Vector = std::vector< + GetPropType<TypeTag, Properties::Scalar> + >; +}; +``` + + +## Configure a model at compile time + +- The DuMu<sup>x</sup> way $\leftrightarrow$ <span style="color:blue">Properties</span> + - A so-called <span style="color:blue">TypeTag</span> bundles all necessary information $\leftrightarrow$ only ONE template parameter + - <span style="color:blue">Properties</span> (data types and values) can be retrieved via the property system. + +```cpp +template <class TypeTag> +class InjectionProblemTwoP +{ + using VolumeVariables = GetPropType< + TypeTag, Properties::VolumeVariables + >; + + constexpr auto useIFS = getPropValue< + TypeTag, Properties::EnableBoxInterfaceSolver + >(); +}; +``` + +## The DuMu<sup>x</sup> property system + +- Extension $\leftrightarrow$ tree of so called TypeTag nodes +- Each TypeTag is associated with Properties + + + +## The DuMu<sup>x</sup> property system + + + + +## The DuMu<sup>x</sup> property system + +- Hierarchy / Inheritance + - TypeTags can inherit properties from other TypeTags + - Properties with the same name are overwriiten + + + +## How to use I + +Creating new <span style="color:blue">TypeTag</span> nodes + +```cpp +namespace Properties::TTag { + +struct MyTypeTag; + +struct MyOtherTypeTag +{ using InheritsFrom = std::tuple<MyTypeTag>; } + +} // end namespace Properties::TTag +``` + +## How to use II + +Creating new <span style="color:blue">property tags</span> (empty, unset properties) $\leftrightarrow$ Property names are unique! +```cpp +namespace Properties { + +template<class TypeTag, class MyTypeTag> +struct Problem { using type = UndefinedProperty; }; + +} // end namespace Properties +``` + +## How to use III + +Setting **type** properties for a specific TypeTag + +```cpp +namespace Properties { + +template<class TypeTag> +struct Problem<TypeTag, TTag::MyTypeTag> +{ using type = Dumux::MyProblem<TypeTag>; }; + +} // end namespace Properties +``` + +## How to use IV + +Setting **value** properties for a specific TypeTag + +```cpp +namespace Properties{ + +template<class TypeTag> +struct EnableBoxInterfaceSolver<TypeTag, TTag::MyTypeTag> +{ static constexpr bool value = true; } + +} // end namespace Properties +``` + + +## How to use V + +Getting the property type set for a specific TypeTag + +```cpp +namespace Dumux{ + +template <class TypeTag> +class Problem +{ + using Scalar = GetPropType<TypeTag, Properties::Scalar>; +}; + +} // end namespace Dumux +``` + + +## Summary + +- "Top-level" classes in DuMu<sup>x</sup> depend on a __type tag__ and use the property system to obtain other types +- Setting a property for your __type tag__ will affect all classes using the same __type tag__ +- Each model defines a set of proeprties grouped in a __type tag__ + * e.g. <span style="color:blue">TwoP, TwoPTwoC, TwoPNI</span> +- By deriving your __type tag__ from those, your problem inherits all type information needed to set up the model at compile time! +- Example: see Exercise