\chapter{The \Dumux Property System} \label{sec:propertysytem} This chapter tries to give high-level understanding of the motivation for the \Dumux property system and how to use it. First, an introduction to polymorphism is given. After this, the fundamental motivation and the ideas behind the \Dumux property system are highlighted and the implementation is outlined from a high-level perspective. The chapter concludes with a simple example of how to use the \Dumux property system. \section{Polymorphism} In object oriented programming, it often happens that some functionality make sense for all classes in a hierarchy, but what actually need to be \textit{done} can be quite different. This observation gives rise to \textit{polymorphism}. In polymorphism, a call to an object's method \textit{means} the same thing, but how this method is \textit{implemented} is case specific\footnote{This \textit{poly} of polymorphism: There are multiple ways to achieve the same goal.}. In C++, there are two common approaches to polymorphism: The traditional -- i.e. non-template programming -- dynamic polymorphism, and static polymorphism which is made possible by template programming. \subsection*{Dynamic Polymorphism} To utilize \textit{dynamic polymorphism} in C++, the polymorphic methods are marked with the \texttt{virtual} keyword in the base class. Internally, the compiler realizes dynamic polymorphism by storing a pointer to a so-called \texttt{vtable} within each object of polymorphic classes. The \texttt{vtable} itself stores the entry point of each method which is declared virtual. If such a method is called on an object, the compiler generates code which retrieves the method's address from the object's \texttt{vtable} and then calls it. This explains why this mechanism is called \textbf{dynamic} polymorphism: the methods which are actually called are dynamically determined at run time. \begin{example} \label{example:DynPoly} A class called \texttt{Car} could feature the methods \texttt{gasUsage} which by default corrosponds to the current $CO_2$ emission goal of the European Union but can be overwritten by the classes representing actual cars. Also, a method called \texttt{fuelTankSize} makes sense for all cars, but since there is no useful default, its \texttt{vtable} entry is set to $0$ in the base class which tells the compiler that this method must mandatorily be specified by all derived classes. Finally the method \texttt{range} may calculate the expected remaining kilometers the car can drive given a fill level of the fuel tank. Since the \texttt{range} method can retrieve information it needs, it does not need to be polymorphic. \begin{verbatim} // The base class class Car {public: virtual double gasUsage() { return 4.5; }; virtual double fuelTankSize() = 0; double range(double fuelTankFillLevel) { return 100*fuelTankFillLevel*fuelTankSize()/gasUsage(); } } \end{verbatim} Actual car models can now derived from the base class: \begin{verbatim} // A Mercedes S-class car class S : public Car {public: virtual double gasUsage() { return 9.0; }; virtual double fuelTankSize() { return 65.0; }; } // A VW Lupo class Lupo : public Car {public: virtual double gasUsage() { return 2.99; }; virtual double fuelTankSize() { return 30.0; }; } \end{verbatim} The \text{range} method called on the base class yields correct result for any car type: \begin{verbatim} void printMaxRange(Car &car) { std::cout << "Maximum Range: " << car.range(1.00) << "\n"; } int main() { Lupo lupo; S s; std::cout << "VW Lupo:" std::cout << "Median range: " << lupo.range(0.50) << "\n"; printMaxRange(lupo); std::cout << "Mercedes S-Class:" std::cout << "Median range: " << s.range(0.50) << "\n"; printMaxRange(s); return 0; } \end{verbatim} For both types of cars, \texttt{Lupo} and \texttt{S} the \texttt{printMaxRange} function works as expected, yielding $1003.3\;\mathrm{km}$ for the Lupo and $722.2\;\mathrm{km}$ for the S-Class. \end{example} \begin{exc} What happens if \dots \begin{itemize} \item \dots the \texttt{gasUsage} method is removed from the \texttt{Lupo} class? \item \dots the \texttt{virtual} qualifier is removed in front of the \texttt{gasUsage} method in the base class? \item \dots the \texttt{fuelTankSize} method is removed from the \texttt{Lupo} class? \item \dots the \texttt{range} method in the \texttt{S} class is overwritten? \end{itemize} \end{exc} \subsection*{Static Polymorphism} Static polymorphism has a few disadvantages, probably the most relevant in the context of \Dumux is that the compiler can not see ``inside'' the called methods and thus cannot properly optimize them. For example modern C++ compilers 'inline' short methods, that is they copy the body the function body to where it is called which saves a few instructions as well as allows further optimizations across the function call. Inlining and other cross call optimizations are next to impossible in conjunction with dynamic polymorphism, since these techniques need to be done by the compiler (i.e. at compile time) while the actual code which gets called is only determined at run time for virtual methods. To overcome this issue, template programming allows a compile time polymorphism. This scheme works by supplying an additional template parameter to the base class which specifies the type of the derived class. Whenever the base class needs to call back at the derived class, the memory of the current object is reinterpreted as a derived object and the method is then called. This scheme gives the C++ compiler complete transparency of the code executed and thus opens for much better optimization oportunities. Also, since this mechanism completely happens at compile time, it is called ``static polymorphism'' because the called method cannot be changed dynamically at runtime. \begin{example} Using static polymorphism, the base class of example \ref{example:DynPoly} can be written as \begin{verbatim} // The base class. The 'Imp' template parameter is the // type of the implementation, i.e. the derived class template class Car {public: double gasUsage() { return 4.5; }; double fuelTankSize() { throw "The derived class needs to implement the fuelTankSize() method" }; double range(double fuelTankFillLevel) { return 100*fuelTankFillLevel*asImp_().fuelTankSize()/asImp_().gasUsage(); } protected: // reinterpret the 'this' object as an object of type 'Imp' Imp &asImp_() { return *static_cast(this); } // version for constant 'this' objects const Imp &asImp_() const { return *static_cast(this); } } \end{verbatim} (Note the \texttt{asImp\_()} calls in the \texttt{range} method.) The derived classes can now be defined like this \begin{verbatim} // A Mercedes S-class car class S : public Car {public: double gasUsage() { return 9.0; }; double fuelTankSize() { return 65.0; }; } // A VW Lupo class Lupo : public Car {public: double gasUsage() { return 2.99; }; double fuelTankSize() { return 30.0; }; } \end{verbatim} \end{example} Analogously to example \ref{example:DynPoly}, the two kinds of cars can be used generically within (template) functions: \begin{verbatim} template void printMaxRange(CarType &car) { std::cout << "Maximum Range: " << car.range(1.00) << "\n"; } int main() { Lupo lupo; S s; std::cout << "VW Lupo:" std::cout << "Median range: " << lupo.range(0.50) << "\n"; printMaxRange(lupo); std::cout << "Mercedes S-Class:" std::cout << "Median range: " << s.range(0.50) << "\n"; printMaxRange(s); return 0; } \end{verbatim} \textbf{TODO: Exercise} \subsection*{Explosion of Template Arguments} A major drawback with template programming in general and with static polymorphism in particular is that the template arguments required for the base class tend to explode quickly. This is due to the fact that often template arguments are often used as arguments for other template classes. To demonstrate this point consider the local jacobian class of the two-phase, two-component box model before the \Dumux property system was introduced: \begin{verbatim} template class TwoPTwoCBoxJacobian : public TwoPTwoCBoxJacobianBase< ProblemT, BoxTraitsT, TwoPTwoCTraitsT, TwoPTwoCElementData, TwoPTwoCVertexData, TwoPTwoCFluxData >, TwoPTwoCBoxJacobian > { // ... } \end{verbatim} % \begin{frame}[fragile] % \frametitle{Nested template arguments} % One problem of static Polymorphism: % \begin{itemize} % \item Template arguments often also require template parameters % \item ``Implementation'' arguments are especially nasty: % \begin{itemize} % \item Assume a base class Base % \item Assume a class Derived and that A is C< Derived > % \item To specify Derived: % \end{itemize} % \end{itemize} % {\scriptsize % \begin{verbatim} % template % class Derived : public Base< C >, B, Derived > % \end{verbatim} % } % \end{frame} % \begin{frame}[fragile] % \frametitle{A real-world example} % {\scriptsize % } % \end{frame} % \begin{frame}[fragile] % \frametitle{Traits} % A possible solution is to specify a class which specifies the % template parameters as type definitions (often called a Traits % class): {\scriptsize % \begin{verbatim} % class Traits % { public: % typedef int A; % typedef C B; % }; % template % class Base {}; % template % class Derived : public class Base % {}; % \end{verbatim} % } %%% Local Variables: %%% mode: latex %%% TeX-master: "dumux-handbook" %%% End: