From e80ec52a9e3bd8d80f56c1b1775d9afe942cad48 Mon Sep 17 00:00:00 2001
From: Andreas Lauser <and@poware.org>
Date: Thu, 4 Nov 2010 15:10:34 +0000
Subject: [PATCH] time manager: do not call problem.nextTimeStepSize() at the
 begining of a new episode

handbook: some improvements

git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@4589 2fb0f335-1f38-0410-981e-8018bf24f1b0
---
 doc/handbook/propertysystem.tex | 178 ++++++++++++++++++++------------
 doc/handbook/structure.tex      |   6 +-
 dumux/common/timemanager.hh     |   9 +-
 3 files changed, 123 insertions(+), 70 deletions(-)

diff --git a/doc/handbook/propertysystem.tex b/doc/handbook/propertysystem.tex
index 47ac96bbc1..980f433545 100644
--- a/doc/handbook/propertysystem.tex
+++ b/doc/handbook/propertysystem.tex
@@ -40,6 +40,7 @@ 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
@@ -53,7 +54,7 @@ run time.
   \texttt{range} method can retrieve information it needs, it does not
   need to be polymorphic.
 \begin{verbatim}
-// the base class
+// The base class
 class Car
 {public:
   virtual double gasUsage() 
@@ -67,7 +68,7 @@ class Car
 
   Actual car models can now derived from the base class:
 \begin{verbatim}
-// a Mercedes S-class car
+// A Mercedes S-class car
 class S : public Car
 {public:
   virtual double gasUsage() { return 9.0; };
@@ -122,57 +123,124 @@ What happens if \dots
 
 \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 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 the 'this' object as an object of type 'Imp'
+  Imp &asImp_() { return *static_cast<Imp*>(this); }
+  // version for constant 'this' objects
+  const Imp &asImp_() const { return *static_cast<const Impl*>(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<S>
+{public:
+  double gasUsage() { return 9.0; };
+  double fuelTankSize() { return 65.0; };
+}
 
-%  can be written by specifying types as
-% template parameters
-%   \item For complex software, the number of template arguments can get
-%     quite large
-%   \item If an additional template argument is required for a base
-%     class template, all derived classes must also be adapted
-%   \end{itemize}
-% \end{frame}
+// A VW Lupo
+class Lupo : public Car<Lupo>
+{public:
+  double gasUsage() { return 2.99; };
+  double fuelTankSize() { return 30.0; };
+}
+\end{verbatim}
+\end{example}
 
-% \begin{frame}
-%   \frametitle{Dynamic Polymorphism}
+Analogously to example \ref{example:DynPoly}, the two kinds of cars
+can be used generically within (template) functions:
+\begin{verbatim}
+template <class CarType>
+void printMaxRange(CarType &car)
+{ std::cout << "Maximum Range: " << car.range(1.00) << "\n"; }
 
-%   If a class wants to make a callback to a derived class, the
-%   repective method can be declared {\tt virtual}. This has drawbacks:
-%   \begin{itemize}
-%   \item Overhead due to indirect function call
-%   \item No way for the compiler to inline the method
-%   \end{itemize}
-% \end{frame}
+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}
 
-% \begin{frame}[fragile]
-%   \frametitle{Static Polymorphism}
+\textbf{TODO: Exercise}
 
-%   Static polymorphism can be used if the type of the derived class is
-%   known at compile time:
-%   \begin{itemize}
-%   \item Additional template parameter {\tt Implementation} for the base class:
-% {\scriptsize
-% \begin{verbatim}
-% template <class Implementation>
-% class Base;
-% \end{verbatim}
-% }
-% \item A static cast to {\tt Implementation} is done before each call-back:
-% {\scriptsize
-% \begin{verbatim}
-% static_cast<Implementation*>(this)->callToImplementation();
-% \end{verbatim}
-% }
-%   \item Derived classes are specified like this:
-% {\scriptsize
-% \begin{verbatim}
-% class Derived : public Base<Derived> {};
-% \end{verbatim}
-% }
-% \end{itemize}
+\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 ProblemT, class BoxTraitsT, class TwoPTwoCTraitsT>
+class TwoPTwoCBoxJacobian
+  : public TwoPTwoCBoxJacobianBase<
+              ProblemT, 
+              BoxTraitsT,
+              TwoPTwoCTraitsT,
+              TwoPTwoCElementData<TwoPTwoCTraitsT,ProblemT>,
+              TwoPTwoCVertexData<TwoPTwoCTraitsT,ProblemT>,
+              TwoPTwoCFluxData<TwoPTwoCTraitsT,
+                               ProblemT,
+                               TwoPTwoCVertexData<TwoPTwoCTraitsT,
+                                                  ProblemT> >,
+              TwoPTwoCBoxJacobian<ProblemT,
+                                  BoxTraitsT,
+                                  TwoPTwoCTraitsT> >
+{
+// ...
+}
+\end{verbatim}
 
-% \end{frame}
 
 % \begin{frame}[fragile]
 %   \frametitle{Nested template arguments}
@@ -199,26 +267,6 @@ What happens if \dots
 %   \frametitle{A real-world example}
 
 % {\scriptsize
-% \begin{verbatim}
-% template<class ProblemT, class BoxTraitsT, class TwoPTwoCTraitsT>
-% class TwoPTwoCBoxJacobian
-%   : public TwoPTwoCBoxJacobianBase<
-%               ProblemT, 
-%               BoxTraitsT,
-%               TwoPTwoCTraitsT,
-%               TwoPTwoCElementData<TwoPTwoCTraitsT,ProblemT>,
-%               TwoPTwoCVertexData<TwoPTwoCTraitsT,ProblemT>,
-%               TwoPTwoCFluxData<TwoPTwoCTraitsT,
-%                                ProblemT,
-%                                TwoPTwoCVertexData<TwoPTwoCTraitsT,
-%                                                   ProblemT> >,
-%               TwoPTwoCBoxJacobian<ProblemT,
-%                                   BoxTraitsT,
-%                                   TwoPTwoCTraitsT> >
-% {
-% // ...
-% }
-% \end{verbatim}
 % }
 % \end{frame}
 
diff --git a/doc/handbook/structure.tex b/doc/handbook/structure.tex
index c8588bf7b4..7409a1243a 100644
--- a/doc/handbook/structure.tex
+++ b/doc/handbook/structure.tex
@@ -1,6 +1,6 @@
-\chapter{Structure}
+\chapter{Directory Structure}
 
-We briefly describe the structure of \Dumux in terms 
+We briefly describe the directory structure of \Dumux in terms 
 of subdirectories, source files, and tests. For more details, 
 the Doxygen documentation should be considered. 
 \Dumux comes in form of a DUNE module \texttt{dumux}. 
@@ -114,4 +114,4 @@ Doxygen documentation should be considered.
     Structure of the directory \texttt{dumux} containing the \Dumux source files.
   }
 \end{figure}
-\end{landscape}
\ No newline at end of file
+\end{landscape}
diff --git a/dumux/common/timemanager.hh b/dumux/common/timemanager.hh
index 40d8eea7af..292a31bfb4 100644
--- a/dumux/common/timemanager.hh
+++ b/dumux/common/timemanager.hh
@@ -369,13 +369,18 @@ public:
                 problem_->serialize();
 
             // notify the problem if an episode is finished
-            if (episodeIsOver())
+            Scalar nextDt = problem_->nextTimeStepSize(dt);
+            if (episodeIsOver()) {
                 problem_->episodeEnd();
+                // the problem sets the initial time step size of a
+                // new episode...
+                nextDt = timeStepSize();
+            }
 
             // notify the problem that the timestep is done and ask it
             // for a suggestion for the next timestep size
             // set the time step size for the next step
-            setTimeStepSize(problem_->nextTimeStepSize(timeStepSize_));
+            setTimeStepSize(nextDt);
 
             if (verbose_) {
                 std::cout <<
-- 
GitLab