Commit 55f491bc authored by Thomas Fetzer's avatar Thomas Fetzer
Browse files

[handbook]

updated handbook:
- added CMake instruction, removed autotools specific parts
- restructured Guidline, TipsNTricks and Detailed Intruction section
- colorful DuMuX code
- small updates in TipsNTricks



git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@14497 2fb0f335-1f38-0410-981e-8018bf24f1b0
parent c6e82899
set(TEX_INPUTS
designpatterns.tex
DumuxFlow.tex
fluidframework.tex
getting-started.tex
......@@ -10,16 +9,16 @@ set(TEX_INPUTS
newFolder.tex
dumux-handbook.tex
NewtonInANutshell.tex
parameterTree.tex
parameterfiles.tex
propertysystem.tex
quick-install.tex
quickstart-guide.tex
spatialdiscretization.tex
restartsimulations.tex
structure.tex
TipsNTricks.tex
tutorial-coupled.tex
tutorial-decoupled.tex
tutorial-newmodel.tex
tutorial.tex
ModelDescriptions/1p2cimplicitmodel.tex
ModelDescriptions/1pdecoupledmodel.tex
......
......@@ -15,7 +15,7 @@ Section \ref{implementation} is structured by \fbox{boxes} and $\overrightarrow{
For keeping things simple, the program flow of a \verb+2p+ model is shown.
There are extensive comments regarding the formating in the tex file: so feel free, to enhance this description.
\section{Structure -- by content}
\section{Structure -- by Content}
\label{content}
% by means of this enumerated list, the connection between algorithm and content can be achieved by references to the labels of this list.
This list shows the algorithmic outline of a typical \Dumux run. Each item stands for a characteristic step within the modeling framework.
......@@ -126,7 +126,7 @@ finalize
\textcircled{\ref{elem}} \textsc{Newton} step\\
\textcircled{\ref{calc}} Element-wise assembly
\section{Structure -- by implementation}
\section{Structure -- by Implementation}
\label{implementation}
This section is supposed to help you in getting an idea how things are handled in \Dumux and in which files things are written down.
This is not intuitivly clear, therefore it is mentioned for each \fbox{step-stone}. \textbf{called by} tells you from which file a function is
......
\chapter{Tips \& Tricks}
This chapter tries to be a useful collection of tips and tricks that can be handy when working with
\Dumux. One of the most prominent ideas for developing \Dune / \Dumux is that reinventing the wheel in terms of FEM code should
be avoided. We try to follow this idea also in the day-to-day work by stating the \emph{tell us dogma}: ``If you found something useful,
handy or for other reasons helping when working with \Dumux: put it into this chapter.'' or inform at least the other developers and write
to the mailing list \texttt{dumux@iws.uni-stuttgart.de} so somebody else can.
This chapter tries to be a useful collection of tips and tricks that can be handy
when working with \Dumux. One of the most prominent ideas for developing
\Dune / \Dumux is that reinventing the wheel in terms of FEM code should
be avoided. We try to follow this idea also in the day-to-day work by
stating the \emph{tell us dogma}: ``If you found something useful,
handy or for other reasons helping when working with \Dumux: put it into
this chapter.'' or inform other developers and write to
\paragraph{Using the \Dumux-Eclipse profile}
\section{\Dumux - General Remarks}
Everybody using the same profile has the advantage of resulting in less conflicts when different developing environments are used:
\begin{enumerate}
\item in eclipse open: \texttt{Window} $\rightarrow$ \texttt{Preferences} $\rightarrow$ \texttt{C/C++} $\rightarrow$ \texttt{Code Style} $\rightarrow$ Formatter
\item press the \texttt{Import} button
\item choose the file \texttt{eclipse\_profile.xml} from your dumux-devel directory
\item make sure that that now \Dumux is chosen in \texttt{Select a profile}
\end{enumerate}
\paragraph{Flyspray}
Flyspray or bug-tracking system is a software application mainly designed to
keep track of reported software development requests. This includes reported
bugs and development requests for new or improved features. The main benefit
of a bug-tracking system is to provide a clear centralized overview of all
recorded requests and their state. \Dumux users and developers can submit
development requests at \url{http://www.dumux.org/flyspray/}.
\paragraph{Dashboard}
The testing-dashboard is a tool to constantly check the \Dumux problems for compiling
or running correctly. It is a useful tool to check the impacts of your commits
and for quality management. The dashboard is available at
\url{http://www.dumux.org/dashboard.php}.
\paragraph{The \Dumux-Mailing List:}
If you have questions concerning \Dumux, hints for the \Dumux-developers
or specific problems, which you really struggle to solve on your own,
you can contact the mailing list \url{dumux@iws.uni-stuttgart.de}.
You can also subscribed to the mailing list via
\url{https://listserv.uni-stuttgart.de/mailman/listinfo/dumux}, then you
will be informed about upcoming releases or events.
\paragraph{The Commit-Mailing List:}
If you further want to be informed about commits to the dumux can subscribe
to the commit mailing list:
\url{https://listserv.uni-stuttgart.de/mailman/listinfo/dumux-commits}.
\section{Developing \Dumux}
\paragraph{Checking Your Commits:}
\Dumux is developed with the help of Subversion (\texttt{svn}).
This means that at some point you will commit your new and/or advanced features
to the repository. In the following some additional guidelines are shown which are
are good practice. Especially if you plan on committing to the stable part of
\Dumux you must follow these steps.
\begin{itemize}
\item add files and folders to your repository
\item run \texttt{make doc} in your build-directory
\item run \texttt{make headercheck} in your build-directory
\item run \texttt{ctest} in your build-directory
\item double-check whether the test are working. \textbf{If not} please
investigate whether an update of the reference solution or a review
of your changes is necessary
\item double-check whether you include all necessary files to your commit
\item commit
\item check-out dumux in new folder and test if everything is still working
(this is necessary to keep bump in the workflow small).
\item check the testing-dashboard (see above), whether everything is still working
\end{itemize}
\paragraph{Naming conventions}
General guidelines for naming conventions are specified in Section \ref{guidelines}.
However, in order to avoid ambiguity a list of proposed names for variables, types,
functions etc is provided where users and mainly \Dumux developers can refer for
standards (check \texttt{dumux-devel/\allowbreak doc/\allowbreak naminglist/\allowbreak naming-conventions.odt}).
\paragraph{Checking whether commit worked}
\paragraph{Errors Messages Related to the Property System}
The property system is a powerful tool and internally does some template and macro magic.
The price for it are sometimes unintuitive compiler error messages. For example if the
definition of a property could not be found, the error is:
\begin{lstlisting}[style=DumuxCode,numbers=none]
error: no type named 'p' in 'struct Dumux::Properties::GetProperty<Dumux::Properties::TTag::TestProblem, Dumux::Properties::PTag::Scalar, Dumux::Properties::TTag::TestProblem, -1000>'
\end{lstlisting}
\Dumux is developed with the help of Subversion (short SVN, see \texttt{http://subversion.apache.org/pronunciation/index.html}). This means that at some point you will commit your new
and/or advanced features (hereafter called ``stuff'') to the repository. But maybe you forgot to commit this one and tiny change in one file you forgot about.
This may result in \Dumux not compiling any more on another person's computer after updating. You can prevent this by checking out \Dune and \Dumux twice. Now you can work in one version and after committing you can simply update the pristine version and see whether it still works there, too.
This approach really helps keeping the bumps in the work-flow small.
\noindent So check whether you did not misspelled any name related to the property system in the
line of the error message and whether you really declared the type tag you use there.\\
Further check, if the \texttt{Problem} property was defined and spelled correctly.
\paragraph{Using \Dune debug streams}
\paragraph{Patching Files or Modules}
See \ref{sc:patchingDUNE} if you need to apply patches to \Dumux or \Dune.
If you want to send changes to an other developer of \Dumux providing patches
can be quite smart. To create a patch simply type:
\begin{lstlisting}[style=Bash]
$ svn diff > PATCHFILE
\end{lstlisting}
\noindent which creates a text file containing all your changes to the files
in the current folder or its subdirectories.
Other developers can now simply apply this patch by
\begin{lstlisting}[style=Bash]
$ path -p0 < PATCHFILE
\end{lstlisting}
\paragraph{Using \Dune Debug Streams}
\Dune provides a helpful feature, for keeping your debug-output organized.
In stead of juggling with a bazillion \texttt{std::cout <<} statements or keeping some debug-precompiler statements organized, which are generally and strongly discouraged see \ref{guidelines} in order not to get
flooded away by your output \Dune gives you a nice tool by the so called debug streams.
......@@ -42,10 +109,11 @@ This approach really helps keeping the bumps in the work-flow small.
They are used as follows: \lstinline{Dune::dinfo << "message";} or \lstinline{Dune::dgrave << "message";} .
The debug streams are switched on/off via setting \lstinline{#define DUNE_MINIMAL_DEBUG_LEVEL 4}
in the source your application. If the value is set to i.\,g. 4 the output generated after \lstinline{Dune::dinfo} (level 4 and 5) will printed anywhere.
in the source your application. If the value is set to e.\,g. 4 only the output generated after
\lstinline{Dune::dwarn} and \lstinline{Dune::dgrave} will be printed.
\paragraph{File name and line number by predefined macro}
\paragraph{File Name and Line Number by Predefined Macro}
If you want to know where some output or debug information came from, you can use the predefined macros \lstinline{__FILE__} and \lstinline{__LINE__}
which are used like\\
\lstinline{dataFile << "# This was written from "<< __FILE__ << ", line " << __LINE__ << "\n";}\\
......@@ -53,8 +121,7 @@ which translates into a line in the output file reading\\
\lstinline{# This was written from [..]/dumux/dumux/io/outputToFile.hh, line 261}\\
This can also be very useful, if you want to have information about where some warning or debug information was issued.
\paragraph{Option files optim.opts and debug.opts}
\paragraph{Option Files optim.opts and debug.opts}
As explained on page \pageref{buildIt} \Dune and \Dumux are built with the help of the \texttt{dunecontrol}.
A lot of options need to be specified for that, which is done in the \texttt{debug.opts} resp. \texttt{optim.opts}
(plus \texttt{.suse11.2} if applicable) in your \texttt{dumux-devel} directory. These two files differ in the way \Dune and \Dumux are compiled: either for debugging or for fast simulation. Switching between these two states is really
......@@ -77,24 +144,62 @@ be debugged because the debugger gets confused. But the cool thing is, that you
Debugging with the optimization options active will lead to erratic behavior while debugging.
\paragraph{Faster build with dunecontrol}
\paragraph{Faster Build with Dunecontrol}
A complete build using \texttt{dunecontrol} takes some time. If there were just small changes in the folder structure, it is usually sufficient to run dunecontrol with option \texttt{autogen} instead of \texttt{all}, and afterwards creating the makefiles with option \texttt{configure}.
An other possibility to speed up dunecontrol is caching of configure results. Add to the configure flags the line \texttt{--cache-file=/tmp/dune-config.cache} in you options file.
\paragraph{Error messages related to the property system}
The property system is a powerful tool and internally does some template and macro magic.
The price for it are sometimes unintuitive compiler error messages. For example if the
definition of a property could not be found, the error is:
\begin{lstlisting}[style=DumuxCode,numbers=none]
error: no type named 'p' in 'struct Dumux::Properties::GetProperty<Dumux::Properties::TTag::TestProblem, Dumux::Properties::PTag::Scalar, Dumux::Properties::TTag::TestProblem, -1000>'
\end{lstlisting}
\section{External Tools}
\subsection{svn}
So check whether you did not misspelled any name related to the property system in the
line of the error message and whether you really declared the type tag you use there.
\paragraph{Basic Commands}
The basic svn commands are:
\begin{itemize}
\item \texttt{svn checkout} checkout an repository
\item \texttt{svn update} updates file/folder
\item \texttt{svn status} to check which files/folders have been changed.
\texttt{M}odified, \texttt{D}eleted, \texttt{A}dded, \texttt{?} not in repository
\item \texttt{svn diff} to see the changes of a file/folder
\item \texttt{svn commit} upload changes to the repository (only with meaningful
commit messages)
\end{itemize}
The above shows you the necessary steps if you use the command line. There are also other tools providing a graphical
user interface for using svn like kdesvn or eclipse.
\paragraph{Flyspray}
Flyspray or bug-tracking system is a software application mainly designed to keep track of reported software development requests. This includes reported bugs and development requests for new or improved features. The main benefit of a bug-tracking system is to provide a clear centralized overview of all recorded requests and their state. \Dumux users and developers can submit development requests at \texttt{http://www.dumux.org/flyspray/}.
\paragraph{Properties/Attributes}
How to set the SVN attributes:
\begin{itemize}
\item{\em eclipse}: right click on the file/folder $\rightarrow$ ``team''
$\rightarrow$ ``add to svn:ignore\dots''
\item{\em kdesvn}: right click on the file/folder $\rightarrow$ ``ignore/unignore
current item''
\item{\em SVN on shell}: \verb+svn propedit svn:ignore .+
\end{itemize}
\paragraph{Naming conventions}
General guidelines for naming conventions are specified in Section \ref{guidelines}. However, in order to avoid ambiguity a list of proposed names for variables, types, functions etc is provided where users and mainly \Dumux developers can refer for standards (check \texttt{dumux-devel/doc/naminglist/\\naming-conventions.odt}).
\subsection{eclipse}
\paragraph{Using the \Dumux-Eclipse Profile}
Everybody using the same profile has the advantage of resulting in less conflicts
when different developing environments are used:
\begin{enumerate}
\item in eclipse open: \texttt{Window} $\rightarrow$ \texttt{Preferences} $\rightarrow$ \texttt{C/C++} $\rightarrow$ \texttt{Code Style} $\rightarrow$ Formatter
\item press the \texttt{Import} button
\item choose the file \texttt{eclipse\_profile.xml} from your dumux-devel directory
\item make sure that that now \Dumux is chosen in \texttt{Select a profile}
\end{enumerate}
% \subsection{kate}
\subsection{ParaView}
\paragraph{Reload Button:}
Yes, you read it right. There is script to reload \texttt{pvd} files or
series of \texttt{vtu} files since ParaView 4.2. The scripts are available
under the links below. Just save the specific code portion in a file and load
it via \texttt{Macros} $\rightarrow$ \texttt{Add new macro}.\\
\texttt{vtk}: \url{http://markmail.org/message/exxynsgishbvtngg#query:+page:1+mid:rxlwxs7uqrfgibyv+state:results}\\
\texttt{pvd}: \url{http://markmail.org/message/exxynsgishbvtngg#query:+page:1+mid:rxlwxs7uqrfgibyv+state:results}.
\paragraph{Guide:}
Since ParaView 4.3.1 The ParaView-Guide is partly
available for free download, see \url{http://www.paraview.org/documentation/}.
It corresponds to the ParaView-book, only without three application chaptes.
Attention its size is 180 MiB.
\chapter{Design Patterns}
\label{chap:DesignPatterns}
This chapter tries to give a high-level understanding of some of the
fundamental techniques which are used by \Dune and \Dumux and the
motivation behind these design decisions. It is assumed that the
reader already has basic experience in object oriented programming
with \Cplusplus.
First, a quick motivation of \Cplusplus template programming is given. Then
follows an introduction to polymorphism and its opportunities as
opened by the template mechanism. After that, some drawbacks
associated with template programming are discussed, in particular the
blow-up of identifier names, the proliferation of template arguments
and some approaches on how to deal with these problems.
\section{\Cplusplus Template Programming}
One of the main features of modern versions of the \Cplusplus programming
language is robust support for templates. Templates are a mechanism
for code generation built directly into the compiler. For the
motivation behind templates, consider a linked list of \texttt{double}
values which could be implemented like this:
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
struct DoubleList {
DoubleList(const double &val, DoubleList *prevNode = 0)
{ value = val; if (prevNode) prevNode->next = this; };
double value;
DoubleList *next;
};
int main() {
DoubleList *head, *tail;
head = tail = new DoubleList(1.23);
tail = new DoubleList(2.34, tail);
tail = new DoubleList(3.56, tail);
};
\end{lstlisting}
But what should be done if a list of strings is also required? The
only ``clean'' way to achive this without templates would be to copy
\texttt{DoubleList}, then rename it and change the type of the
\texttt{value} attribute. It is obvious that this is a very
cumbersome, error-prone and unproductive process. For this reason,
recent standards of the \Cplusplus programming language specify the template
mechanism, which is a way of letting the compiler do the tedious work. Using
templates, a generic linked list can be implemented like this:
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
template <class ValueType>
struct List {
List(const ValueType &val, List *prevNode = 0)
{ value = val; if (prevNode) prevNode->next = this; };
ValueType value;
List *next;
};
int main() {
typedef List<double> DoubleList;
DoubleList *head, *tail;
head = tail = new DoubleList(1.23);
tail = new DoubleList(2.34, tail);
tail = new DoubleList(3.56, tail);
typedef List<const char*> StringList;
StringList *head2, *tail2;
head2 = tail2 = new StringList("Hello");
tail2 = new StringList(", ", tail2);
tail2 = new StringList("World!", tail2);
};
\end{lstlisting}
Compared to approaches which use external tools for code generation --
which is the approach chosen for example by the
FEniCS~\cite{FENICS-HP} project -- or heavy (ab)use of the C
preprocessor -- as done for example by the UG framework~\cite{UG-HP}
-- templates have several advantages:
\begin{description}
\item[Well Programmable:] Programming errors are directly detected by
the \Cplusplus compiler. Thus, diagnostic messages from the compiler are
directly useful because the source code compiled is the
same as the one written by the developer. This is not the case
for code generators and C-preprocessor macros where the actual
statements processed by the compiler are obfuscated.
\item[Easily Debugable:] Programs which use the template mechanism can be
debugged almost as easily as \Cplusplus programs which do not use
templates. This is due to the fact that the debugger always knows
the ``real'' source file and line number.
\end{description}
For these reasons \Dune and \Dumux extensively use the template
mechanism. Both projects also try to avoid duplicating functionality
provided by the Standard Template Library (STL,~\cite{STL-REF-HP})
which is part of the \Cplusplus standard and was improved in the \Cplusplus11 standard.
\section{Polymorphism}
In object oriented programming, some methods often make sense for all
classes in a hierarchy, but what actually needs to be \textit{done}
can differ for each concrete class. This observation motivates
\textit{polymorphism}. Fundamentally, polymorphism means all
techniques in which a method call results in the processor executing code
which is specific to the type of object for which the method is
called\footnote{This is the \textit{poly} of polymorphism: There are
multiple ways to achieve the same goal.}.
In \Cplusplus, there are two common ways to achieve polymorphism: The
traditional dynamic polymorphism which does not require template
programming, and static polymorphism which is made possible by the
template mechanism.
\subsection*{Dynamic Polymorphism}
To utilize \textit{dynamic polymorphism} in \Cplusplus, 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 \texttt{virtual}. If such a method is
called on an object, the compiler generates code which retrieves the
method's memory address from the object's \texttt{vtable} and then
continues execution at this address. This explains why this mechanism
is called \textbf{dynamic} polymorphism: the code which is actually
executed is dynamically determined at run time.
\begin{example}
\label{example:DynPoly}
A class called \texttt{Car} could feature the methods
\texttt{gasUsage}, which by default corresponds to the current
$CO_2$ emission goal of the European Union -- line \ref{designpatterns:virtual-usage} -- but can be changed by
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$ -- line \ref{designpatterns:totally-virtual} -- in the
base class. This tells the compiler that it is mandatory for this
method to be defined in 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 the information it needs, it does not
need to be polymorphic.
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
// The base class
class Car
{public:
virtual double gasUsage()
{ return 4.5; };/*@\label{designpatterns:virtual-usage}@*/
virtual double fuelTankSize() = 0;/*@\label{designpatterns:totally-virtual}@*/
double range(double fuelTankFillLevel)
{ return 100*fuelTankFillLevel*fuelTankSize()/gasUsage(); }
};
\end{lstlisting}
\noindent
Actual car models can now be derived from the base class like this:
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
// 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{lstlisting}
\noindent
Calling the \texttt{range} method yields the correct result for any
kind of car:
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
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);
}
\end{lstlisting}
For both types of cars, \texttt{Lupo} and \texttt{S} the function
\texttt{printMaxRange} works as expected, it yields
$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}
Dynamic polymorphism has a few disadvantages. The most relevant in the
context of \Dumux is that the compiler can not see ``inside'' the
called methods and thus cannot optimize properly. For example, modern
\Cplusplus compilers 'inline' short methods, i.e. they copy the method's body
to where it is called. First, inlining allows to save a few
instructions by avoiding to jump into and out of the method. Second,
and more importantly, inlining also allows further optimizations which
depend on specific properties of the function arguments (e.g. constant
value elimination) or the contents of the function body (e.g. loop
unrolling). Unfortunately, inlining and other cross-method
optimizations are made next to impossible by dynamic
polymorphism. This is because these optimizations are accomplished by the
compiler (i.e. at compile time) whilst the code which actually gets
executed is only determined at run time for \texttt{virtual}
methods. To overcome this issue, template programming can be used to
achive polymorphism at compile time. This works by supplying the type
of the derived class as an additional template parameter to the base
class. Whenever the base class needs to call back the derived class, \texttt{this} pointer of the base class is reinterpreted as
being a pointer to an object of the derived class and the method is
then called on the reinterpreted pointer. This scheme gives the \Cplusplus
compiler complete transparency of the code executed and thus opens
much better optimization oportunities. Since this mechanism completely
happens at compile time, it is called ``static polymorphism'' because
the called method cannot be dynamically changed at runtime.
\begin{example}
Using static polymorphism, the base class of example \ref{example:DynPoly}
can be implemented like this:
\begin{lstlisting}[name=staticcars,basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
// The base class. The 'Imp' template parameter is the
// type of implementation, i.e. the derived class
template <class Imp>
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 'this' as a pointer to an object of type 'Imp'
Imp &asImp_() { return *static_cast<Imp*>(this); }
};
\end{lstlisting}
(Notice the \texttt{asImp\_()} calls in the \texttt{range} method.) The
derived classes may now be defined like this:
\begin{lstlisting}[name=staticcars,basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
// A Mercedes S-class car
class S : public Car<S>
{public:
double gasUsage() { return 9.0; };
double fuelTankSize() { return 65.0; };
};
// A VW Lupo
class Lupo : public Car<Lupo>
{public:
double gasUsage() { return 2.99; };
double fuelTankSize() { return 30.0; };
};
\end{lstlisting}
\end{example}
\noindent
Analogous to example \ref{example:DynPoly}, the two kinds of cars can
be used generically within (template) functions:
\begin{lstlisting}[name=staticcars,basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
template <class CarType>
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{lstlisting}
%\textbf{TODO: Exercise}
\section{Common Template Programming Related Problems}
Although \Cplusplus template programming opens a few intriguing
possibilities, it also has a few disadvantages. In this section, a few
of them are outlined and some hints on how they can be dealt with are
provided.
\subsection*{Identifier-Name Blow-Up}
One particular problem with the advanced use of \Cplusplus templates is that the
canonical identifier names for types and methods quickly become really
long and unintelligible. For example, a typical error message
generated using GCC 4.5 and \Dune-PDELab looks like this
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize, numbersep=5pt]
test_pdelab.cc:171:9: error: no matching function for call to ‘Dune::\
PDELab::GridOperatorSpace<Dune::PDELab::PowerGridFunctionSpace<Dune::\
PDELab::GridFunctionSpace<Dune::GridView<Dune::DefaultLeafGridViewTraits\
<const Dune::UGGrid<3>, (Dune::PartitionIteratorType)4u> >, Dune::\
PDELab::Q1LocalFiniteElementMap<double, double, 3>, Dune::PDELab::\
NoConstraints, Dumux::PDELab::BoxISTLVectorBackend<Dumux::Properties::\
TTag::LensProblem> >, 2, Dune::PDELab::GridFunctionSpaceBlockwiseMapper>\
, Dune::PDELab::PowerGridFunctionSpace<Dune::PDELab::GridFunctionSpace<\
Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::UGGrid<3>, \
(Dune::PartitionIteratorType)4u> >, Dune::PDELab::Q1LocalFiniteElementMap\
<double, double, 3>, Dune::PDELab::NoConstraints, Dumux::PDELab::\
BoxISTLVectorBackend<Dumux::Properties::TTag::LensProblem> >, 2, Dune::\
PDELab::GridFunctionSpaceBlockwiseMapper>, Dumux::PDELab::BoxLocalOperator\
<Dumux::Properties::TTag::LensProblem>, Dune::PDELab::\
ConstraintsTransformation<long unsigned int, double>, Dune::PDELab::\
ConstraintsTransformation<long unsigned int, double>, Dune::PDELab::\
ISTLBCRSMatrixBackend<2, 2>, true>::GridOperatorSpace()’
\end{lstlisting}
This seriously complicates diagnostics. Although there is no full
solution to this problem yet, an effective way of dealing with such
kinds of error messages is to ignore the type information and to just
look at the location given at the beginning of the line. If nested
templates are used, the lines printed by the compiler above the actual
error message specify how exactly the code was instantiated (the lines
starting with ``\texttt{instantiated from}''). In this case it is
advisable to look at the innermost source code location of ``recently
added'' source code.
\subsection*{Proliferation of Template Parameters}
Templates often need a large number of template parameters. For
example, the error message above was produced by the following
snipplet:
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,numbers=left,numberstyle=\tiny, numbersep=5pt]
int main()
{
enum {numEq = 2};
enum {dim = 3};
typedef Dune::UGGrid<dim> Grid;
typedef Grid::LeafGridView GridView;
typedef Dune::PDELab::Q1LocalFiniteElementMap<double,double,dim> FEM;
typedef TTAG(LensProblem) TypeTag;
typedef Dune::PDELab::NoConstraints Constraints;
typedef Dune::PDELab::GridFunctionSpace<
GridView, FEM, Constraints, Dumux::PDELab::BoxISTLVectorBackend<TypeTag>
>
doubleGridFunctionSpace;
typedef Dune::PDELab::PowerGridFunctionSpace<
doubleGridFunctionSpace,
numEq,
Dune::PDELab::GridFunctionSpaceBlockwiseMapper
>
GridFunctionSpace;
typedef typename GridFunctionSpace::ConstraintsContainer<double>::Type
ConstraintsTrafo;
typedef Dumux::PDELab::BoxLocalOperator<TypeTag> LocalOperator;
typedef Dune::PDELab::GridOperatorSpace<
GridFunctionSpace,