- Parameters vs. properties
- Parameters vs. properties
- Template parameters
- Template parameters
- Template parameters
- Template specializations
- Too many template parameters
- Traits classes
- Inheriting from traits classes
- Type traits
- Type traits
- The DuMuX Property System
- Property System Design
- Property System Design
- Property System Design
- Property System Design
- Actual Design
- Actual Design
- Actual Design
- Using type tags as traits classes
- The DuMux property system
- The DuMux property system
- How to use I
- How to use II
- How to use III
- How to use III (alternative)
- How to use IV
- How to use IV (alternative)
- How to use V
- Summary
title: The DuMuX property system
subtitle: Flexible compile-time parameters
Parameters vs. properties
Parameters vs. properties
-
Parameters are set at run-time
A default value may be used if the user does not provide one at run-time
-
Properties are known and set at compile-time
Can be used e.g. as template parameters (__types__ or values with `constexpr` specifier); No run-time penalty, enable compiler to optimize
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
// 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 parameters
An example - std::vector

Template specializations
Template implementations can be specialized for concrete types
template<typename T>
class MyVector
{
// Generic implementation for any T
};
template<>
class MyVector<int>
{
// specialized implementation for `int`
};
Too many template parameters
For some classes, providing all template parameters can be very cumbersome and error-prone.
// 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
struct MyGridOperatorTraits
{
using FromGFS = ...;
// ...
};
using GOF0 = Dune::PDELab::GridOperator<MyGridOperatorTraits>;
Inheriting from traits classes
Inheritance may lead to unexpected results
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
// Type trait 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; };
Type traits
A usage example
// expecting Container to export value_type
template<typename Container>
void someFunction(const Container& c) {
using V = typename Container::value_type;
// do something with V
// ...
}
// using type traits
template<typename Container>
void someFunction(const Container& c) {
using V = typename ValueType<Container>::type;
// do something with V
// ...
}
The DuMuX Property System
Property System Design
- Based on C++ template specialization (type traits)
- From a type tag, one can extract properties defined for it
- A property tag is a type trait declaration (or default implementation)
- A property is exported from a property tag specialization for a type tag
- (The property system also supports definitions of traits classes - see later)
Property System Design
A simplified example to illustrate the idea
// myproperties.hh
namespace Dumux::Properties {
namespace TTag { struct MyTypeTag {}; }
// some property tag
template<typename TypeTag> struct PropTagA;
// property definition for MyTypeTag
template<>
struct PropTagA<MyTypeTag>
{ using type = /*the actual property*/; };
} // namespace Dumux::Properties
Property System Design
A simplified example to illustrate the idea
template<class TypeTag>
class GenericClass
{
using PropA = typename Properties::PropTagA<TypeTag>::type;
using PropB = typename Properties::PropTagB<TypeTag>::type;
// ...
// A property could be, for instance, a fluid system
using FS = typename Properties::FluidSystem<TypeTag>::type;
};
Property System Design
Issue: Inheritance not (easily) possible. All type traits need to be specialized for MyTypeTag
.
Goal: We would like type tags to be composable via inheritance, while providing a mechanism for customizing any property defined in the hierarchy.
Actual Design
- A hierarchy of nodes -- called type tags -- is defined (via inheritance)
- Properties are defined for the appropriate nodes in this hierarchy.
- The definition of properties may depend on arbitrary other properties, which may be overwritten at any higher node of the hierarchy
- The only requirement for properties is that they may not exhibit cyclic dependencies
Actual Design
Let's implement the Vector
example using the property system
namespace Properties {
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> {
private: using Scalar = GetPropType<TypeTag, Properties::Scalar>;
public: using type = std::vector<Scalar>;
};
Actual Design
Let's implement the Vector
example using the property system
namespace Properties {
namespace TTag {
struct DoubleTag { using InheritsFrom = std::tuple<BaseTag>; };
} // namespace TTag
// Specialization of the Scalar property for DoubleTag
template<class TypeTag>
struct Scalar<TypeTag, TTag::DoubleTag>
{ using type = double; };
// 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
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>
>;
};
The DuMux property system
- Extension \leftrightarrow tree of so called TypeTag nodes
- Each TypeTag is associated with Properties
The DuMux property system
- Hierarchy / Inheritance
How to use I
Creating new TypeTag nodes
namespace Dumux::Properties::TTag {
struct MyTypeTag {};
struct MyOtherTypeTag
{ using InheritsFrom = std::tuple<MyTypeTag>; }
} // end namespace Dumux::Properties::TTag
How to use II
Creating new property tags (empty, unset properties) \leftrightarrow Property names are unique!
namespace Dumux::Properties {
DUMUX_DEFINE_PROPERTY(Problem)
} // end namespace Dumux::Properties
Usually not needed in user code because all necessary properties are already defined in dumux/common/properties.hh.
How to use III
Setting type properties for a specific type tag MyTypeTag
namespace Properties {
template<class TypeTag>
struct Problem<TypeTag, TTag::MyTypeTag>
{ using type = Dumux::MyProblem<TypeTag>; };
} // end namespace Properties
How to use III (alternative)
Alternatively, using type alias properties for a specific type tag MyTypeTag
namespace Properties::TTag {
struct MyTypeTag {
...
template<class TypeTag>
using Problem = Dumux::MyProblem<TypeTag>;
...
};
} // end namespace Properties
How to use IV
Setting value properties for a specific type tag MyTypeTag
namespace Properties{
template<class TypeTag>
struct EnableBoxInterfaceSolver<TypeTag, TTag::MyTypeTag>
{ static constexpr bool value = true; }
} // end namespace Properties
How to use IV (alternative)
Setting value for a alias property for a specific type tag MyTypeTag
namespace Properties {
struct MyTypeTag {
...
using EnableBoxInterfaceSolver = std::true_type;
...
};
} // end namespace Properties
How to use V
Getting the property type set for a TypeTag
namespace Dumux{
template <class TypeTag>
class Problem
{
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
constexpr auto useIFS = getPropValue<
TypeTag, Properties::EnableBoxInterfaceSolver
>();
};
} // end namespace Dumux
Summary
- "Top-level" classes in DuMux 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 properties grouped in a type tag
- e.g. TwoP, TwoPTwoC, TwoPNI
- 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