diff --git a/doc/handbook/5_propertysystem.tex b/doc/handbook/5_propertysystem.tex index e66b20aae04d9a004962bdee90234a1e4820235c..a77759dcc7ed3bf08b15c09def3215ec4af567ba 100644 --- a/doc/handbook/5_propertysystem.tex +++ b/doc/handbook/5_propertysystem.tex @@ -37,9 +37,12 @@ namespace \texttt{Dumux::Properties}. \subsubsection{Defining Type Tags} New nodes in the type tag hierarchy can be defined using \begin{lstlisting}[style=DumuxCode] -NEW_TYPE_TAG(NewTypeTagName, INHERITS_FROM(BaseTagName1, BaseTagName2, ...)); +// Create new type tags +namespace TTag { +struct NewTypeTagName { using InheritsFrom = std::tuple<..., BaseTagName2, BaseTagName1>; }; +} // end namespace TTag \end{lstlisting} -where the \texttt{INHERITS\_FROM} part is optional. To avoid +where the \texttt{InheritsFrom} part is optional. To avoid inconsistencies in the hierarchy, each type tag may be defined only once for a program. @@ -48,29 +51,30 @@ Example: \begin{lstlisting}[style=DumuxCode] namespace Dumux { namespace Properties { -NEW_TYPE_TAG(MyBaseTypeTag1); -NEW_TYPE_TAG(MyBaseTypeTag2); +namespace TTag { +struct MyBaseTypeTag1 {}; +struct MyBaseTypeTag2 {}; -NEW_TYPE_TAG(MyDerivedTypeTag, INHERITS_FROM(MyBaseTypeTag1, MyBaseTypeTag2)); +struct MyDerivedTypeTag { using InheritsFrom = std::tuple<MyBaseTypeTag2, MyBaseTypeTag1>; }; +} // end namespace TTag }} \end{lstlisting} \subsubsection{Declaring Property Tags} -New property tags, i.e. labels for properties, are declared +New property tags are defined using: using \begin{lstlisting}[style=DumuxCode] -NEW_PROP_TAG(NewPropTagName); +template<class TypeTag> +struct NewPropTagName<TypeTag, TTag::MyTypeTag> { using type = UndefinedProperty; }; \end{lstlisting} -A property tag can be declared arbitrarily often, in fact it is -recommended that all properties are declared in each file where they -are used. \vskip1ex\noindent Example: \begin{lstlisting}[style=DumuxCode] namespace Dumux { namespace Properties { -NEW_PROP_TAG(MyPropertyTag); +template<class TypeTag> +struct MyPropertyTag<TypeTag, TTag::MyTypeTag> { using type = UndefinedProperty; }; }} \end{lstlisting} @@ -78,7 +82,8 @@ NEW_PROP_TAG(MyPropertyTag); The value of a property on a given node of the type tag hierarchy is defined using \begin{lstlisting}[style=DumuxCode] -SET_PROP(TypeTagName, PropertyTagName) +template<class TypeTag> +struct PropertyTagName<TypeTag, TTag::TypeTagName> { // arbitrary body of a struct }; @@ -86,13 +91,15 @@ SET_PROP(TypeTagName, PropertyTagName) For each program, a property itself can be declared at most once, although properties may be overwritten for derived type tags. -Also, the following convenience macros are available to define simple -properties: \begin{lstlisting}[style=DumuxCode] -SET_TYPE_PROP(TypeTagName, PropertyTagName, type); -SET_BOOL_PROP(TypeTagName, PropertyTagName, booleanValue); -SET_INT_PROP(TypeTagName, PropertyTagName, integerValue); -SET_SCALAR_PROP(TypeTagName, PropertyTagName, floatingPointValue); +template<class TypeTag> +struct PropertyTagName<TypeTag, TTag::TypeTagName> { using type = type; }; + +template<class TypeTag> +struct PropertyTagName<TypeTag, TTag::TypeTagName> { static constexpr bool value = booleanValue; }; + +template<class TypeTag> +struct PropertyTagName<TypeTag, TTag::TypeTagName> { static constexpr int value = integerValue; }; \end{lstlisting} \vskip1ex\noindent @@ -100,100 +107,63 @@ Example: \begin{lstlisting}[style=DumuxCode] namespace Dumux { namespace Properties { -NEW_TYPE_TAG(MyTypeTag); -NEW_PROP_TAG(MyCustomProperty); -NEW_PROP_TAG(MyType); +// Create new type tag +namespace TTag { +struct MyTypeTag {}; +} -NEW_PROP_TAG(MyBoolValue); -NEW_PROP_TAG(MyIntValue); -NEW_PROP_TAG(MyScalarValue); +// Declare the properties +template<class TypeTag, class MyTypeTag> struct MyCustomProperty; -SET_PROP(MyTypeTag, MyCustomProperty) -{ - static void print() { std::cout << "Hello, World!\n"; } -}; -SET_TYPE_PROP(MyTypeTag, MyType, unsigned int); +template<class TypeTag, class MyTypeTag> struct MyType; -SET_BOOL_PROP(MyTypeTag, MyBoolValue, true); -SET_INT_PROP(MyTypeTag, MyIntValue, 12345); -SET_SCALAR_PROP(MyTypeTag, MyScalarValue, 12345.67890); -}} -\end{lstlisting} +template<class TypeTag, class MyTypeTag> struct MyBoolValue; -\subsubsection{Un-setting Properties} -Sometimes an inherited properties do not make sense for a certain -node in the type tag hierarchy. These properties can be explicitly -un-set using -\begin{lstlisting}[style=DumuxCode] -UNSET_PROP(TypeTagName, PropertyTagName); -\end{lstlisting} -The un-set property can not be set for the same type tag, but of -course derived type tags may set it again. +template<class TypeTag, class MyTypeTag> struct MyIntValue; -\vskip1ex\noindent -Example: -\begin{lstlisting}[style=DumuxCode] -namespace Dumux { -namespace Properties { -NEW_TYPE_TAG(BaseTypeTag); -NEW_TYPE_TAG(DerivedTypeTag, INHERITS_FROM(BaseTypeTag)); +template<class TypeTag, class MyTypeTag> struct MyScalarValue; + +// Set the properties +template<class TypeTag> +struct MyCustomProperty<TypeTag, TTag::MyTypeTag> +{static void print() { std::cout << "Hello, World!\n"; }}; -NEW_PROP_TAG(TestProp); +template<class TypeTag> +struct MyType<TypeTag, TTag::MyTypeTag> { using type = unsigned int; }; -SET_TYPE_PROP(BaseTypeTag, TestProp, int); -UNSET_PROP(DerivedTypeTag, TestProp); -// trying to access the 'TestProp' property for 'DerivedTypeTag' -// will trigger a compiler error! +template<class TypeTag> +struct MyBoolValue<TypeTag, TTag::MyTypeTag> { static constexpr bool value = true; }; + +template<class TypeTag> +struct MyIntValue<TypeTag, TTag::MyTypeTag> { static constexpr int value = 12345; }; + +template<class TypeTag> +struct MyScalarValue<TypeTag, TTag::MyTypeTag> { static constexpr double value = 12345.67890; }; }} \end{lstlisting} -\subsubsection{Converting Tag Names to Tag Types} -For the \Cplusplus compiler, property and type tags are like ordinary -types. Both can thus be used as template arguments. To convert a -property tag name or a type tag name into the corresponding type, the -macros \texttt{TTAG(TypeTagName)} and \texttt{PTAG(PropertyTagName)} -ought to be used. - \subsubsection{Retrieving Property Values} -The value of a property can be retrieved using -\begin{lstlisting}[style=DumuxCode] -GET_PROP(TypeTag, PropertyTag) -\end{lstlisting} -or using the convenience macros +The type or the value of a property can be retrieved using \begin{lstlisting}[style=DumuxCode] -GET_PROP_TYPE(TypeTag, PropertyTag) -GET_PROP_VALUE(TypeTag, PropertyTag) +using MyType = GetPropType<TypeTag, Properties::PropertyTag> +auto myValue = getPropValue<TypeTag, Properties::PropertyTag>() \end{lstlisting} -\vskip1ex -\noindent -The first convenience macro retrieves the type defined using -\texttt{SET\_TYPE\_PROP} and is equivalent to -\begin{lstlisting}[style=DumuxCode] -GET_PROP(TypeTag, PropertyTag)::type -\end{lstlisting} -while the second convenience macro retrieves the value of any property -defined using one of the macros \texttt{SET\_}$\{$\texttt{INT,BOOL,SCALAR}$\}$\texttt{\_PROP} and is -equivalent to -\begin{lstlisting}[style=DumuxCode] -GET_PROP(TypeTag, PropertyTag)::value -\end{lstlisting} \vskip1ex\noindent Example:\nolinebreak \begin{lstlisting}[style=DumuxCode] template <TypeTag> class MyClass { - // retrieve the ::value attribute of the 'NumEq' property - enum { numEq = GET_PROP(TypeTag, NumEq)::value }; - // retrieve the ::value attribute of the 'NumPhases' property using the convenience macro - enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) }; + // retrieve the ::type attribute of the 'NumEq' property + enum { numEq = GetPropType<Properties::ModelTraits>::numEq() }; + + // retrieve the ::value attribute of the 'UseMoles' property + static constexpr bool useMoles = getPropValue<TypeTag, Properties::UseMoles>(); // retrieve the ::type attribute of the 'Scalar' property - typedef typename GET_PROP(TypeTag, Scalar)::type Scalar; - // retrieve the ::type attribute of the 'Vector' property using the convenience macro - typedef typename GET_PROP_TYPE(TypeTag, Vector) Vector; + using Scalar = GetPropType<TypeTag, Properties::Scalar>; }; \end{lstlisting} @@ -201,16 +171,17 @@ class MyClass { Inside property definitions there is access to all other properties which are defined somewhere on the type tag hierarchy. The node for which the current property is requested is available via the keyword -\texttt{TypeTag}. Inside property class bodies this can be used to -retrieve other properties using the \texttt{GET\_PROP} macros. +\texttt{TypeTag}. Inside property class bodies \texttt{GetPropType} can be used to +retrieve other properties and create aliases. \vskip1ex\noindent Example: \begin{lstlisting}[style=DumuxCode] -SET_PROP(MyModelTypeTag, Vector) +template<class TypeTag> +struct Vector<TypeTag, TTag::MyModelTypeTag> { -private: typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; -public: typedef std::vector<Scalar> type; +using Scalar = GetPropType<TypeTag, Properties::Scalar>; +using type = std::vector<Scalar>; }; \end{lstlisting} @@ -272,12 +243,15 @@ defined by: namespace Dumux { namespace Properties { -NEW_TYPE_TAG(CompactCar); -NEW_TYPE_TAG(Truck); -NEW_TYPE_TAG(Tank); -NEW_TYPE_TAG(Sedan, INHERITS_FROM(CompactCar)); -NEW_TYPE_TAG(Pickup, INHERITS_FROM(Sedan, Truck)); -NEW_TYPE_TAG(HummerH1, INHERITS_FROM(Pickup, Tank)); +namespace TTag{ +struct CompactCar {}; +struct Truck {}; +struct Tank {}; + +struct Sedan { using InheritsFrom = std::tuple<CompactCar>; }; +struct Pickup { using InheritsFrom = std::tuple<Truck, Sedan>; }; +struct HummerH1 { using InheritsFrom = std::tuple<Tank, Pickup>; }; +}}} // end namespace TTag \end{lstlisting} Figure \ref{fig:car-propertynames} lists a few property names which @@ -285,12 +259,18 @@ make sense for at least one of the nodes of Figure \ref{fig:car-hierarchy}. These property names can be declared as follows: \begin{lstlisting}[name=propsyscars,style=DumuxCode] -NEW_PROP_TAG(TopSpeed); // [km/h] -NEW_PROP_TAG(NumSeats); // [] -NEW_PROP_TAG(CanonCaliber); // [mm] -NEW_PROP_TAG(GasUsage); // [l/100km] -NEW_PROP_TAG(AutomaticTransmission); // true/false -NEW_PROP_TAG(Payload); // [t] +template<class TypeTag, class MyTypeTag> +struct TopSpeed { using type = UndefinedProperty; }; // [km/h] +template<class TypeTag, class MyTypeTag> +struct NumSeats { using type = UndefinedProperty; }; // [] +template<class TypeTag, class MyTypeTag> +struct CanonCaliber { using type = UndefinedProperty; }; // [mm] +template<class TypeTag, class MyTypeTag> +struct GasUsage { using type = UndefinedProperty; }; // [l/100km] +template<class TypeTag, class MyTypeTag> +struct AutomaticTransmission { using type = UndefinedProperty; }; // true/false +template<class TypeTag, class MyTypeTag> +struct Payload { using type = UndefinedProperty; }; // [t] \end{lstlisting} \noindent @@ -321,35 +301,52 @@ the following: Using the \Dumux property system, these assumptions are formulated using \begin{lstlisting}[name=propsyscars,style=DumuxCode] -SET_INT_PROP(CompactCar, TopSpeed, GET_PROP_VALUE(TypeTag, GasUsage) * 30); -SET_INT_PROP(CompactCar, NumSeats, 5); -SET_INT_PROP(CompactCar, GasUsage, 4); +template<class TypeTag> +struct TopSpeed<TypeTag, TTag::CompactCar> +{static constexpr int value = getPropValue<TypeTag, Properties::GasUsage>() * 30}; -SET_INT_PROP(Truck, TopSpeed, 100); -SET_INT_PROP(Truck, NumSeats, 2); -SET_INT_PROP(Truck, GasUsage, 18); -SET_INT_PROP(Truck, Payload, 35); +template<class TypeTag> +struct NumSeats<TypeTag, TTag::CompactCar> { static constexpr int value = 5; }; -SET_INT_PROP(Tank, TopSpeed, 60); -SET_INT_PROP(Tank, GasUsage, 65); -SET_INT_PROP(Tank, CanonCaliber, 120); +template<class TypeTag> +struct GasUsage<TypeTag, TTag::CompactCar> { static constexpr int value = 4; }; -SET_INT_PROP(Sedan, GasUsage, 7); -SET_BOOL_PROP(Sedan, AutomaticTransmission, true); +template<class TypeTag> +struct TopSpeed<TypeTag, TTag::Truck> { static constexpr int value = 100; }; -SET_INT_PROP(Pickup, TopSpeed, 120); -SET_INT_PROP(Pickup, Payload, 5); +template<class TypeTag> +struct NumSeats<TypeTag, TTag::Truck> { static constexpr int value = 2; }; -SET_INT_PROP(HummerH1, TopSpeed, GET_PROP_VALUE(TTAG(Pickup), TopSpeed)); -\end{lstlisting} +template<class TypeTag> +struct GasUsage<TypeTag, TTag::Truck> { static constexpr int value = 18; }; -\noindent -At this point, the Hummer-H1 has a $\unit[120]{mm}$ canon which it inherited -from its military ancestor. It can be removed by -\begin{lstlisting}[name=propsyscars,style=DumuxCode] -UNSET_PROP(HummerH1, CanonCaliber); +template<class TypeTag> +struct Payload<TypeTag, TTag::Truck> { static constexpr int value = 35; }; -}} // close namespaces +template<class TypeTag> +struct TopSpeed<TypeTag, TTag::Tank> { static constexpr int value = 60; }; + +template<class TypeTag> +struct GasUsage<TypeTag, TTag::Tank> { static constexpr int value = 65; }; + +template<class TypeTag> +struct CanonCaliber<TypeTag, TTag::Tank> { static constexpr int value = 120; }; + +template<class TypeTag> +struct GasUsage<TypeTag, TTag::Sedan> { static constexpr int value = 7; }; + +template<class TypeTag> +struct AutomaticTransmission<TypeTag, TTag::Sedan> { static constexpr bool value = true; }; + +template<class TypeTag> +struct TopSpeed<TypeTag, TTag::Pickup> { static constexpr int value = 120; }; + +template<class TypeTag> +struct Payload<TypeTag, TTag::Pickup> { static constexpr int value = 5; }; + +template<class TypeTag> +struct TopSpeed<TypeTag, TTag::HummerH1> +{static constexpr int value = getPropValue<TypeTag, TTag::Pickup::TopSpeed<TypeTag>>();}; \end{lstlisting} \noindent @@ -358,30 +355,19 @@ be generated. For example \begin{lstlisting}[name=propsyscars,style=DumuxCode] int main() { - std::cout << "top speed of sedan: " << GET_PROP_VALUE(TTAG(Sedan), TopSpeed) << "\n"; - std::cout << "top speed of truck: " << GET_PROP_VALUE(TTAG(Truck), TopSpeed) << "\n"; - - std::cout << PROP_DIAGNOSTIC(TTAG(Sedan), TopSpeed); - std::cout << PROP_DIAGNOSTIC(TTAG(HummerH1), CanonCaliber); - - Dumux::Properties::print<TTAG(Sedan)>(); + std::cout << "top speed of sedan: " << getPropValue<Properties::TTag::Sedan, Properties::TopSpeed>() << "\n"; + std::cout << "top speed of truck: " << getPropValue<Properties::TTag::Truck, Properties::TopSpeed>() << "\n"; } \end{lstlisting} will yield the following output: \begin{lstlisting}[style=Bash, basicstyle=\ttfamily\scriptsize\let\textcolor\textcolordummy] $ top speed of sedan: 210 $ top speed of truck: 100 -$ Properties for Sedan: -$ bool AutomaticTransmission = 'true' defined at test_propertysystem.cc:68 -$ int GasUsage = '7' defined at test_propertysystem.cc:67 -$ Inherited from CompactCar: -$ int NumSeats = '5' defined at test_propertysystem.cc:55 -$ int TopSpeed = '::Dumux::Properties::GetProperty<TypeTag, ::Dumux::Properties::PTag::GasUsage>::p::value * 30' defined at test_propertysystem.cc:54 \end{lstlisting} \subsection{Property Values} To get the value of a property use: \begin{description} -\item[\texttt{{\small GET\_PROP\_VALUE:}}] +\item[\texttt{{\small getPropValue:}}] Always returns the \emph{compile-time} specified value of the property. \end{description}