From a8de229c332694f8d3e2af2526d13a28eaa8085c Mon Sep 17 00:00:00 2001
From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de>
Date: Wed, 7 Mar 2018 11:25:25 +0100
Subject: [PATCH] [componentes][base] Throw "not implemented" error during
 compile time

---
 dumux/common/typetraits/typetraits.hh         |  38 +++
 dumux/material/components/base.hh             |  46 ++-
 dumux/material/components/benzene.hh          |   6 +
 dumux/material/components/gas.hh              |  56 +++-
 dumux/material/components/liquid.hh           |  50 ++-
 dumux/material/components/simpleh2o.hh        |  11 +
 dumux/material/components/solid.hh            |  38 ++-
 test/material/components/plotproperties.cc    | 296 ++++++++++++------
 .../ex3/components/mycompressiblecomponent.hh |  55 ++++
 .../components/myincompressiblecomponent.hh   |  43 +++
 .../h2omycompressiblecomponent.hh             |  11 +-
 .../solution/ex3/mycompressiblecomponent.hh   |   2 +-
 .../solution/ex3/myincompressiblecomponent.hh |   6 +
 13 files changed, 515 insertions(+), 143 deletions(-)
 create mode 100644 dumux/common/typetraits/typetraits.hh

diff --git a/dumux/common/typetraits/typetraits.hh b/dumux/common/typetraits/typetraits.hh
new file mode 100644
index 0000000000..3f1906478a
--- /dev/null
+++ b/dumux/common/typetraits/typetraits.hh
@@ -0,0 +1,38 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \ingroup Common
+ * \ingroup TypeTraits
+ */
+#ifndef DUMUX_TYPE_TRAITS_HH
+#define DUMUX_TYPE_TRAITS_HH
+
+#include <type_traits>
+
+namespace Dumux
+{
+    /*!
+     * \brief template which always yields a false value
+     * \tparam T Some type.
+     */
+    template<typename T>
+    struct AlwaysFalse : public std::false_type {};
+}
+#endif
diff --git a/dumux/material/components/base.hh b/dumux/material/components/base.hh
index 2d78d82c3d..8c22b80bcf 100644
--- a/dumux/material/components/base.hh
+++ b/dumux/material/components/base.hh
@@ -34,6 +34,8 @@
 #include <dune/common/exceptions.hh>
 #include <dune/common/stdstreams.hh>
 
+#include <dumux/common/typetraits/typetraits.hh>
+
 namespace Dumux {
 namespace Components {
 
@@ -63,38 +65,62 @@ public:
      * \brief A human readable name for the component.
      * \note Mandatory for all components
      */
+    template<class C = Implementation>
     static std::string name()
-    { return Implementation::name(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: name()");
+        DUNE_THROW(Dune::NotImplemented, "name()");
+    }
 
     /*!
      * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of the component.
      */
+    template<class C = Implementation>
     static Scalar molarMass()
-    { DUNE_THROW(Dune::NotImplemented, "Component::molarMass()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: molarMass()");
+        DUNE_THROW(Dune::NotImplemented, "molarMass()");
+    }
 
     /*!
      * \brief Returns the critical temperature in \f$\mathrm{[K]}\f$ of the component.
      */
+    template<class C = Implementation>
     static Scalar criticalTemperature()
-    { DUNE_THROW(Dune::NotImplemented, "Component::criticalTemperature()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: criticalTemperature()");
+        DUNE_THROW(Dune::NotImplemented, "criticalTemperature()");
+    }
 
     /*!
      * \brief Returns the critical pressure in \f$\mathrm{[Pa]}\f$ of the component.
      */
+    template<class C = Implementation>
     static Scalar criticalPressure()
-    { DUNE_THROW(Dune::NotImplemented, "Component::criticalPressure()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: criticalPressure()");
+        DUNE_THROW(Dune::NotImplemented, "criticalPressure()");
+    }
 
     /*!
      * \brief Returns the temperature in \f$\mathrm{[K]}\f$ at the component's triple point.
      */
+    template<class C = Implementation>
     static Scalar tripleTemperature()
-    { DUNE_THROW(Dune::NotImplemented, "Component::tripleTemperature()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: tripleTemperature()");
+        DUNE_THROW(Dune::NotImplemented, "tripleTemperature()");
+    }
 
     /*!
      * \brief Returns the pressure in \f$\mathrm{[Pa]}\f$ at the component's triple point.
      */
+    template<class C = Implementation>
     static Scalar triplePressure()
-    { DUNE_THROW(Dune::NotImplemented, "Component::triplePressure()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: triplePressure()");
+        DUNE_THROW(Dune::NotImplemented, "triplePressure()");
+    }
 
     /*!
      * \brief The vapor pressure in \f$\mathrm{[Pa]}\f$ of the component at a given
@@ -102,8 +128,12 @@ public:
      *
      * \param T temperature of the component in \f$\mathrm{[K]}\f$
      */
-    static Scalar vaporPressure(Scalar T)
-    { DUNE_THROW(Dune::NotImplemented, "Component::vaporPressure()"); }
+    template<class C = Implementation>
+    static Scalar vaporPressure(Scalar t)
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: vaporPressure(t)");
+        DUNE_THROW(Dune::NotImplemented, "vaporPressure(t)");
+    }
 
 };
 
diff --git a/dumux/material/components/benzene.hh b/dumux/material/components/benzene.hh
index ff25e7ff2c..384bcf96bf 100644
--- a/dumux/material/components/benzene.hh
+++ b/dumux/material/components/benzene.hh
@@ -49,6 +49,12 @@ public:
     static std::string name()
     { return "benzene"; }
 
+    /*!
+     * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of benzene
+     */
+    static Scalar molarMass()
+    { return 0.07811; }
+
     /*!
      * \brief The density of benzene steam at a given pressure and temperature \f$\mathrm{[kg/m^3]}\f$.
      *
diff --git a/dumux/material/components/gas.hh b/dumux/material/components/gas.hh
index 32715df7eb..b1e65284f7 100644
--- a/dumux/material/components/gas.hh
+++ b/dumux/material/components/gas.hh
@@ -27,6 +27,8 @@
 
 #include <dune/common/exceptions.hh>
 
+#include <dumux/common/typetraits/typetraits.hh>
+
 namespace Dumux {
 namespace Components {
 
@@ -43,20 +45,32 @@ public:
     /*!
      * \brief Returns true if the gas phase is assumed to be compressible
      */
+    template<class C = Component>
     static constexpr bool gasIsCompressible()
-    { return Component::gasIsCompressible(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasIsCompressible()");
+        DUNE_THROW(Dune::NotImplemented, "gasIsCompressible()");
+    }
 
     /*!
      * \brief Returns true if the gas phase viscostiy is constant
      */
+    template<class C = Component>
     static constexpr bool gasViscosityIsConstant()
-    { return Component::gasViscosityIsConstant(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasViscosityIsConstant()");
+        DUNE_THROW(Dune::NotImplemented, "gasViscosityIsConstant()");
+    }
 
     /*!
      * \brief Returns true if the gas phase is assumed to be ideal
      */
+    template<class C = Component>
     static constexpr bool gasIsIdeal()
-    { return Component::gasIsCompressible(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasIsIdeal()");
+        DUNE_THROW(Dune::NotImplemented, "gasIsIdeal()");
+    }
 
     /*!
      * \brief The density in \f$\mathrm{[kg/m^3]}\f$ of the component at a given pressure in
@@ -65,8 +79,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar gasDensity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasDensity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasDensity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasDensity(t,p)");
+    }
 
     /*!
      * \brief Specific enthalpy \f$\mathrm{[J/kg]}\f$ of the pure component in gas.
@@ -74,8 +92,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar gasEnthalpy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasEnthalpy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasEnthalpy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasEnthalpy(t,p)");
+    }
 
     /*!
      * \brief Specific internal energy \f$\mathrm{[J/kg]}\f$ of the pure component in gas.
@@ -83,8 +105,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar gasInternalEnergy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasInternalEnergy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasInternalEnergy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasInternalEnergy(t,p)");
+    }
 
     /*!
      * \brief The dynamic viscosity \f$\mathrm{[Pa*s]}\f$ of the pure component at a given pressure in
@@ -93,24 +119,36 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar gasViscosity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasViscosity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasViscosity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasViscosity(t,p)");
+    }
 
     /*!
      * \brief Thermal conductivity of the component \f$\mathrm{[W/(m*K)]}\f$ as a gas.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar gasThermalConductivity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasThermalConductivity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasThermalConductivity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasThermalConductivity(t,p)");
+    }
 
     /*!
      * \brief Specific isobaric heat capacity of the component \f$\mathrm{[J/(kg*K)]}\f$ as a gas.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar gasHeatCapacity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::gasHeatCapacity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: gasHeatCapacity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "gasHeatCapacity(t,p)");
+    }
 
 };
 
diff --git a/dumux/material/components/liquid.hh b/dumux/material/components/liquid.hh
index aa088d37ef..14645b81d1 100644
--- a/dumux/material/components/liquid.hh
+++ b/dumux/material/components/liquid.hh
@@ -27,6 +27,8 @@
 
 #include <dune/common/exceptions.hh>
 
+#include <dumux/common/typetraits/typetraits.hh>
+
 namespace Dumux {
 namespace Components {
 
@@ -43,14 +45,22 @@ public:
     /*!
      * \brief Returns true if the liquid phase is assumed to be compressible
      */
+    template<class C = Component>
     static constexpr bool liquidIsCompressible()
-    { return Component::liquidIsCompressible(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidIsCompressible()");
+        DUNE_THROW(Dune::NotImplemented, "liquidIsCompressible()");
+    }
 
     /*!
      * \brief Returns true if the liquid phase viscostiy is constant
      */
+    template<class C = Component>
     static constexpr bool liquidViscosityIsConstant()
-    { return Component::liquidViscosityIsConstant(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidViscosityIsConstant()");
+        DUNE_THROW(Dune::NotImplemented, "liquidViscosityIsConstant()");
+    }
 
     /*!
      * \brief The density \f$\mathrm{[kg/m^3]}\f$ of the liquid component at a given pressure in
@@ -59,8 +69,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar liquidDensity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidDensity(t,p)"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidDensity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidDensity(t,p)");
+    }
 
     /*!
      * \brief The dynamic liquid viscosity \f$\mathrm{[Pa*s]}\f$ of the pure component.
@@ -68,8 +82,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar liquidViscosity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidViscosity(t,p)"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidViscosity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidViscosity(t,p)");
+    }
 
     /*!
      * \brief Specific enthalpy \f$\mathrm{[J/kg]}\f$ of the pure component in liquid.
@@ -77,8 +95,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar liquidEnthalpy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidEnthalpy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidEnthalpy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidEnthalpy(t,p)");
+    }
 
     /*!
      * \brief Specific internal energy \f$\mathrm{[J/kg]}\f$ of pure the pure component in liquid.
@@ -86,24 +108,36 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar liquidInternalEnergy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidInternalEnergy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidInternalEnergy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidInternalEnergy(t,p)");
+    }
 
     /*!
      * \brief Thermal conductivity of the component \f$\mathrm{[W/(m*K)]}\f$ as a liquid.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar liquidThermalConductivity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidThermalConductivity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidThermalConductivity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidThermalConductivity(t,p)");
+    }
 
     /*!
      * \brief Specific isobaric heat capacity of the component \f$\mathrm{[J/(kg*K)]}\f$ as a liquid.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar liquidHeatCapacity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::liquidHeatCapacity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: liquidHeatCapacity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "liquidHeatCapacity(t,p)");
+    }
 };
 
 } // end namespace Components
diff --git a/dumux/material/components/simpleh2o.hh b/dumux/material/components/simpleh2o.hh
index f7ea57d880..90f835eabc 100644
--- a/dumux/material/components/simpleh2o.hh
+++ b/dumux/material/components/simpleh2o.hh
@@ -322,6 +322,17 @@ public:
        return 0.025;
     }
 
+    /*!
+     * \brief Specific isobaric heat capacity of water steam \f$\mathrm{[J/(kg*K)}\f$.
+     *        source: http://webbook.nist.gov/cgi/fluid.cgi?ID=C7732185&Action=Page
+     *        @ T= 372.76K (99.6°C) , p=0.1MPa)
+     * \param temperature temperature of component in \f$\mathrm{[K]}\f$
+     * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
+     */
+    static Scalar gasHeatCapacity(Scalar temperature, Scalar pressure)
+    {
+        return 2.08e3;
+    }
 
 };
 
diff --git a/dumux/material/components/solid.hh b/dumux/material/components/solid.hh
index 58fb8756c4..c1d2c825c2 100644
--- a/dumux/material/components/solid.hh
+++ b/dumux/material/components/solid.hh
@@ -27,6 +27,8 @@
 
 #include <dune/common/exceptions.hh>
 
+#include <dumux/common/typetraits/typetraits.hh>
+
 namespace Dumux {
 namespace Components {
 
@@ -43,8 +45,12 @@ public:
     /*!
      * \brief Returns true if the solid phase is assumed to be compressible
      */
+    template<class C = Component>
     static constexpr bool solidIsCompressible()
-    { return Component::solidIsCompressible(); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidIsCompressible()");
+        DUNE_THROW(Dune::NotImplemented, "solidIsCompressible()");
+    }
 
     /*!
      * \brief The density in \f$\mathrm{[kg/m^3]}\f$ of the component at a given pressure in
@@ -53,8 +59,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar solidDensity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::solidDensity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidDensity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "solidDensity(t,p)");
+    }
 
     /*!
      * \brief Specific enthalpy \f$\mathrm{[J/kg]}\f$ of the pure component in solid.
@@ -62,8 +72,12 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar solidEnthalpy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::solidEnthalpy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidEnthalpy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "solidEnthalpy(t,p)");
+    }
 
     /*!
      * \brief Specific internal energy \f$\mathrm{[J/kg]}\f$ of the pure component in solid.
@@ -71,24 +85,36 @@ public:
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static const Scalar solidInternalEnergy(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::solidInternalEnergy()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidInternalEnergy(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "solidInternalEnergy(t,p)");
+    }
 
     /*!
      * \brief Thermal conductivity of the component \f$\mathrm{[W/(m*K)]}\f$ as a solid.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar solidThermalConductivity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::solidThermalConductivity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidThermalConductivity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "solidThermalConductivity(t,p)");
+    }
 
     /*!
      * \brief Specific isobaric heat capacity of the component \f$\mathrm{[J/(kg*K)]}\f$ as a solid.
      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
      */
+    template<class C = Component>
     static Scalar solidHeatCapacity(Scalar temperature, Scalar pressure)
-    { DUNE_THROW(Dune::NotImplemented, "Component::solidHeatCapacity()"); }
+    {
+        static_assert(AlwaysFalse<C>::value, "Mandatory function not implemented: solidHeatCapacity(t,p)");
+        DUNE_THROW(Dune::NotImplemented, "solidHeatCapacity(t,p)");
+    }
 
 };
 
diff --git a/test/material/components/plotproperties.cc b/test/material/components/plotproperties.cc
index 2cfc8b5b4a..39b5684e06 100644
--- a/test/material/components/plotproperties.cc
+++ b/test/material/components/plotproperties.cc
@@ -24,9 +24,12 @@
 
 #include "config.h"
 #include <array>
+#include <algorithm>
 #include <cstring>
 #include <limits>
 #include <vector>
+#include <dumux/common/typetraits/isvalid.hh>
+#include <dumux/common/typetraits/typetraits.hh>
 #include <dumux/io/gnuplotinterface.hh>
 #include <dumux/material/components/air.hh>
 #include <dumux/material/components/benzene.hh>
@@ -46,7 +49,186 @@
 #include <dumux/material/components/xylene.hh>
 
 using namespace std;
+using namespace Dumux;
 
+namespace Dumux {
+
+//! Helper struct to deactivate static assertions in component's base classes.
+struct DisableStaticAssert {};
+
+/*!
+ * \brief Specialization of Dumux::AlwaysFalse for the struct defined
+ *        above. This is done in order to deactivate the static_assert in
+ *        the base classes of components. If the base class function is compiled
+ *        we do not call it (see below).
+ */
+template<>
+struct AlwaysFalse<DisableStaticAssert> : public std::true_type {};
+}
+
+//! helper structs for detecting if a component has certain functions overloaded
+struct checkLiqDen { template<class C> auto operator()(C&& c) -> decltype(C::template liquidDensity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkLiqEnth { template<class C> auto operator()(C&& c) -> decltype(C::template liquidEnthalpy<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkLiqHeatCap { template<class C> auto operator()(C&& c) -> decltype(C::template liquidHeatCapacity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkLiqVisc { template<class C> auto operator()(C&& c) -> decltype(C::template liquidViscosity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkLiqThermCond { template<class C> auto operator()(C&& c) -> decltype(C::template liquidThermalConductivity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkGasDen { template<class C> auto operator()(C&& c) -> decltype(C::template gasDensity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkGasEnth { template<class C> auto operator()(C&& c) -> decltype(C::template gasEnthalpy<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkGasHeatCap { template<class C> auto operator()(C&& c) -> decltype(C::template gasHeatCapacity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkGasVisc { template<class C> auto operator()(C&& c) -> decltype(C::template gasViscosity<DisableStaticAssert>(0.0, 0.0)) {}; };
+struct checkGasThermCond { template<class C> auto operator()(C&& c) -> decltype(C::template gasThermalConductivity<DisableStaticAssert>(0.0, 0.0)) {}; };
+
+//! plot given values
+template<class Functor>
+void plot(Functor&& f,
+          const vector<double>& T,
+          const double pressure,
+          const std::string& compName,
+          const std::string& phaseName,
+          const std::string& propName,
+          const std::string& unit,
+          bool openPlot)
+{
+    vector<double> values(T.size());
+    for (int i = 0; i < T.size(); ++i)
+        values[i] = f(T[i], pressure);
+
+    const auto minMax = minmax_element(values.begin(), values.end());
+    Dumux::GnuplotInterface<double> gnuplot(true);
+    gnuplot.setOpenPlotWindow(openPlot);
+    gnuplot.setCreateImage(true);
+    gnuplot.setXRange(T[0], T[T.size()-1]);
+    gnuplot.setYRange(*(minMax.first)*0.999, *(minMax.second)*1.001);
+    gnuplot.setXlabel("temperature [K]");
+    gnuplot.setYlabel(phaseName + " " + propName + " " + unit);
+    gnuplot.setDatafileSeparator(',');
+    gnuplot.addDataSetToPlot(T, values, compName + "_" + phaseName + "_" + propName + ".csv");
+    gnuplot.plot(compName + "_" + phaseName + "_" + propName);
+}
+
+//! Plot properties if overloads compile
+template<class C, class hasNoDensityOverload = checkLiqDen>
+auto plotLiquidDensity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoDensityOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::liquidDensity(T, p); };
+    plot(f, T, p, C::name(), "liquid", "density", "[kg/^3]", openPlot);
+}
+
+template<class C, class hasNoEnthalpyOverload = checkLiqEnth>
+auto plotLiquidEnthalpy(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoEnthalpyOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::liquidEnthalpy(T, p); };
+    plot(f, T, p, C::name(), "liquid", "enthalpy", "[J/(kg)]", openPlot);
+}
+
+template<class C, class hasNoHeatCapOverload = checkLiqHeatCap>
+auto plotLiquidHeatCapacity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoHeatCapOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::liquidHeatCapacity(T, p); };
+    plot(f, T, p, C::name(), "liquid", "heat capacity", "[J/(kg*K)]", openPlot);
+}
+
+template<class C, class hasNoViscOverload = checkLiqVisc>
+auto plotLiquidViscosity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoViscOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::liquidViscosity(T, p); };
+    plot(f, T, p, C::name(), "liquid", "viscosity", "[Pa*s]", openPlot);
+}
+
+template<class C, class hasNoThermCondOverload = checkLiqThermCond>
+auto plotLiquidThermalConductivity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoThermCondOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::liquidThermalConductivity(T, p); };
+    plot(f, T, p, C::name(), "liquid", "thermal conductivity", "[J/(kg*K)]", openPlot);
+}
+
+template<class C, class hasNoDensityOverload = checkGasDen>
+auto plotGasDensity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoDensityOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::gasDensity(T, p); };
+    plot(f, T, p, C::name(), "gas", "density", "[kg/^3]", openPlot);
+}
+
+template<class C, class hasNoEnthalpyOverload = checkGasEnth>
+auto plotGasEnthalpy(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoEnthalpyOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::gasEnthalpy(T, p); };
+    plot(f, T, p, C::name(), "gas", "enthalpy", "[J/(kg)]", openPlot);
+}
+
+template<class C, class hasNoHeatCapOverload = checkGasHeatCap>
+auto plotGasHeatCapacity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoHeatCapOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::gasHeatCapacity(T, p); };
+    plot(f, T, p, C::name(), "gas", "heat capacity", "[J/(kg*K)]", openPlot);
+}
+
+template<class C, class hasNoViscOverload = checkGasVisc>
+auto plotGasViscosity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoViscOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::gasViscosity(T, p); };
+    plot(f, T, p, C::name(), "gas", "viscosity", "[Pa*s]", openPlot);
+}
+
+template<class C, class hasNoThermCondOverload = checkGasThermCond>
+auto plotGasThermalConductivity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<!decltype(isValid(hasNoThermCondOverload{})(declval<C>()))::value, void>
+{
+    auto f = [] (auto T, auto p) { return C::gasThermalConductivity(T, p); };
+    plot(f, T, p, C::name(), "gas", "thermal conductivity", "[J/(kg*K)]", openPlot);
+}
+
+//! Do not plot properties if overloads don't compile
+template<class C, class hasNoDensityOverload = checkLiqDen>
+auto plotLiquidDensity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoDensityOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoEnthalpyOverload = checkLiqEnth>
+auto plotLiquidEnthalpy(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoEnthalpyOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoHeatCapOverload = checkLiqHeatCap>
+auto plotLiquidHeatCapacity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoHeatCapOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoViscOverload = checkLiqVisc>
+auto plotLiquidViscosity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoViscOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoThermCondOverload = checkLiqThermCond>
+auto plotLiquidThermalConductivity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoThermCondOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoDensityOverload = checkGasDen>
+auto plotGasDensity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoDensityOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoEnthalpyOverload = checkGasEnth>
+auto plotGasEnthalpy(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoEnthalpyOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoHeatCapOverload = checkGasHeatCap>
+auto plotGasHeatCapacity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoHeatCapOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoViscOverload = checkGasVisc>
+auto plotGasViscosity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoViscOverload{})(declval<C>()))::value, void> {}
+
+template<class C, class hasNoThermCondOverload = checkGasThermCond>
+auto plotGasThermalConductivity(const vector<double>& T, double p, bool openPlot)
+-> typename std::enable_if_t<decltype(isValid(hasNoThermCondOverload{})(declval<C>()))::value, void> {}
+
+//! a number of properties of a component
 template<class Component>
 void plotStuff(bool openPlotWindow)
 {
@@ -57,109 +239,19 @@ void plotStuff(bool openPlotWindow)
     const unsigned int numIntervals = 100;
     vector<double> T(numIntervals + 1);
     for (int i = 0; i <= numIntervals; i++)
-    {
         T[i] = TMin + TRange * double(i) /double(numIntervals);
-    }
-
-    // components
-    const unsigned int liquidPhaseIdx = 0;
-    const unsigned int gasPhaseIdx = 1;
-
-    const unsigned int numPhases = 2;
-    array<string, numPhases> phaseNames;
-    phaseNames[liquidPhaseIdx] = "liquid";
-    phaseNames[gasPhaseIdx] = "gas";
-
-    const unsigned int numProperties = 5;
-    array<string, numProperties> propertyNames;
-    array<string, numProperties> propertyUnits;
-    unsigned int densityIdx = 0;
-    propertyNames[densityIdx] = "density";
-    propertyUnits[densityIdx] = "[kg/m^3]";
-    unsigned int enthalpyIdx = 1;
-    propertyNames[enthalpyIdx] = "enthalpy";
-    propertyUnits[enthalpyIdx] = "[J/(kg)]";
-    unsigned int heatCapacityIdx = 2;
-    propertyNames[heatCapacityIdx] = "heatCapacity";
-    propertyUnits[heatCapacityIdx] = "[J/(kg*K)]";
-    unsigned int viscosityIdx = 3;
-    propertyNames[viscosityIdx] = "viscosity";
-    propertyUnits[viscosityIdx] = "[Pa*s]";
-    unsigned int thermalConductivityIdx = 4;
-    propertyNames[thermalConductivityIdx] = "thermalConductivity";
-    propertyUnits[thermalConductivityIdx] = "[W/(m*K)]";
-    array<array<vector<double>, numProperties>, numPhases> property;
-    array<array<bool, numProperties>, numPhases> propertyAvailable;
-    array<array<array<double, 2>, numProperties>, numPhases> propertyMinMax;
-
-    // get values from component functions
-    for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
-    {
-        for (unsigned int propertyIdx = 0; propertyIdx < numProperties; ++propertyIdx)
-        {
-            propertyAvailable[phaseIdx][propertyIdx] = true;
-            propertyMinMax[phaseIdx][propertyIdx][0] = std::numeric_limits<double>::max();
-            propertyMinMax[phaseIdx][propertyIdx][1] = std::numeric_limits<double>::min();
-            property[phaseIdx][propertyIdx].resize(numIntervals+1);
-        }
-
-        for (int i = 0; i <= numIntervals; i++)
-        {
-            if (phaseIdx == liquidPhaseIdx)
-            {
-                try { property[phaseIdx][densityIdx][i] = Component::liquidDensity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][densityIdx] = false; }
-                try { property[phaseIdx][enthalpyIdx][i] = Component::liquidEnthalpy(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][enthalpyIdx] = false; }
-                try { property[phaseIdx][heatCapacityIdx][i] = Component::liquidHeatCapacity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][heatCapacityIdx] = false; }
-                try { property[phaseIdx][viscosityIdx][i] = Component::liquidViscosity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][viscosityIdx] = false; }
-                try { property[phaseIdx][thermalConductivityIdx][i] = Component::liquidThermalConductivity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][thermalConductivityIdx] = false; }
-            }
-            if (phaseIdx == gasPhaseIdx)
-            {
-                try { property[phaseIdx][densityIdx][i] = Component::gasDensity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][densityIdx] = false; }
-                try { property[phaseIdx][enthalpyIdx][i] = Component::gasEnthalpy(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][enthalpyIdx] = false; }
-                try { property[phaseIdx][heatCapacityIdx][i] = Component::gasHeatCapacity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][heatCapacityIdx] = false; }
-                try { property[phaseIdx][viscosityIdx][i] = Component::gasViscosity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][viscosityIdx] = false; }
-                try { property[phaseIdx][thermalConductivityIdx][i] = Component::gasThermalConductivity(T[i], pressure); }
-                catch (Dune::NotImplemented &e) { propertyAvailable[phaseIdx][thermalConductivityIdx] = false; }
-            }
-
-            for (unsigned int propertyIdx = 0; propertyIdx < numProperties; ++propertyIdx)
-            {
-                propertyMinMax[phaseIdx][propertyIdx][0] = std::min(propertyMinMax[phaseIdx][propertyIdx][0], property[phaseIdx][propertyIdx][i]);
-                propertyMinMax[phaseIdx][propertyIdx][1] = std::max(propertyMinMax[phaseIdx][propertyIdx][1], property[phaseIdx][propertyIdx][i]);
-            }
-        }
-    }
-
-    // plot densities
-    for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
-    {
-        for (unsigned int propertyIdx = 0; propertyIdx < numProperties; ++propertyIdx)
-        {
-            if (!propertyAvailable[phaseIdx][propertyIdx])
-                continue;
-
-            Dumux::GnuplotInterface<double> gnuplot(true);
-            gnuplot.setOpenPlotWindow(openPlotWindow);
-            gnuplot.setCreateImage(true);
-            gnuplot.setXRange(TMin, TMax);
-            gnuplot.setYRange(propertyMinMax[phaseIdx][propertyIdx][0]*0.999, propertyMinMax[phaseIdx][propertyIdx][1]*1.001);
-            gnuplot.setXlabel("temperature [K]");
-            gnuplot.setYlabel(phaseNames[phaseIdx] + " " + propertyNames[propertyIdx] + " " + propertyUnits[propertyIdx]);
-            gnuplot.setDatafileSeparator(',');
-            gnuplot.addDataSetToPlot(T, property[phaseIdx][propertyIdx], Component::name() + "_" + phaseNames[phaseIdx] + "_" + propertyNames[propertyIdx] + ".csv");
-            gnuplot.plot(Component::name() + "_" + phaseNames[phaseIdx] + "_" + propertyNames[propertyIdx]);
-        }
-    }
+
+    plotLiquidDensity<Component>(T, pressure, openPlotWindow);
+    plotLiquidEnthalpy<Component>(T, pressure, openPlotWindow);
+    plotLiquidHeatCapacity<Component>(T, pressure, openPlotWindow);
+    plotLiquidViscosity<Component>(T, pressure, openPlotWindow);
+    plotLiquidThermalConductivity<Component>(T, pressure, openPlotWindow);
+
+    plotGasDensity<Component>(T, pressure, openPlotWindow);
+    plotGasEnthalpy<Component>(T, pressure, openPlotWindow);
+    plotGasHeatCapacity<Component>(T, pressure, openPlotWindow);
+    plotGasViscosity<Component>(T, pressure, openPlotWindow);
+    plotGasThermalConductivity<Component>(T, pressure, openPlotWindow);
 }
 
 ////////////////////////
diff --git a/tutorial/ex3/components/mycompressiblecomponent.hh b/tutorial/ex3/components/mycompressiblecomponent.hh
index 65d48fe25a..0e65ac440e 100644
--- a/tutorial/ex3/components/mycompressiblecomponent.hh
+++ b/tutorial/ex3/components/mycompressiblecomponent.hh
@@ -51,6 +51,61 @@ public:
      * TODO: Copy the methods implemented in MyIncompressibleComponent and substitute
      *       the density calculation by the expression given in the exercise description.
      */
+
+     /*!
+      * \brief Returns true if the liquid phase is assumed to be compressible
+      */
+     static constexpr bool liquidIsCompressible()
+     {
+         // TODO: replace the line below by a meaningful return statement
+         DUNE_THROW(Dune::NotImplemented, "Todo: implement liquidIsCompressible()");
+     }
+
+     /*!
+      * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of the component.
+      */
+     static Scalar molarMass()
+     {
+         // TODO: replace the line below by a meaningful return statement
+         DUNE_THROW(Dune::NotImplemented, "Todo: implement molar mass");
+     }
+
+     /*!
+      * \brief The density \f$\mathrm{[kg/m^3]}\f$ of the liquid component at a given pressure in
+      *          \f$\mathrm{[Pa]}\f$ and temperature in \f$\mathrm{[K]}\f$.
+      *
+      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
+      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
+      */
+     static Scalar liquidDensity(Scalar temperature, Scalar pressure)
+     {
+         // TODO: replace the line below by a meaningful return statement
+         DUNE_THROW(Dune::NotImplemented, "Todo: implement liquid density");
+     }
+
+     /*!
+      * \brief The dynamic liquid viscosity \f$\mathrm{[Pa*s]}\f$ of the pure component.
+      *
+      * \param temperature temperature of component in \f$\mathrm{[K]}\f$
+      * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
+      */
+     static Scalar liquidViscosity(Scalar temperature, Scalar pressure)
+     {
+         // TODO: replace the line below by a meaningful return statement
+         DUNE_THROW(Dune::NotImplemented, "Todo: implement liquid viscosity");
+     }
+
+     /*!
+      * \brief The vapor pressure in \f$\mathrm{[Pa]}\f$ of the component at a given
+      *        temperature in \f$\mathrm{[K]}\f$.
+      *
+      * \param T temperature of the component in \f$\mathrm{[K]}\f$
+      */
+     static Scalar vaporPressure(Scalar t)
+     {
+         // TODO: replace the line below by a meaningful return statement
+         DUNE_THROW(Dune::NotImplemented, "Todo: implement vapour pressure");
+     }
 };
 
 } // end namespace
diff --git a/tutorial/ex3/components/myincompressiblecomponent.hh b/tutorial/ex3/components/myincompressiblecomponent.hh
index 9809100b21..b37266ceac 100644
--- a/tutorial/ex3/components/myincompressiblecomponent.hh
+++ b/tutorial/ex3/components/myincompressiblecomponent.hh
@@ -49,6 +49,49 @@ public:
     /*!
      * TODO: Implement the methods for the component data given in the exercise description.
      */
+
+    /*!
+     * \brief Returns true if the liquid phase is assumed to be compressible
+     */
+    static constexpr bool liquidIsCompressible()
+    {
+        // TODO: replace the line below by a meaningful return statement
+        DUNE_THROW(Dune::NotImplemented, "Todo: implement liquidIsCompressible()");
+    }
+
+    /*!
+     * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of the component.
+     */
+    static Scalar molarMass()
+    {
+        // TODO: replace the line below by a meaningful return statement
+        DUNE_THROW(Dune::NotImplemented, "Todo: implement molarMass()");
+    }
+
+    /*!
+     * \brief The density \f$\mathrm{[kg/m^3]}\f$ of the liquid component at a given pressure in
+     *          \f$\mathrm{[Pa]}\f$ and temperature in \f$\mathrm{[K]}\f$.
+     *
+     * \param temperature temperature of component in \f$\mathrm{[K]}\f$
+     * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
+     */
+    static Scalar liquidDensity(Scalar temperature, Scalar pressure)
+    {
+        // TODO: replace the line below by a meaningful return statement
+        DUNE_THROW(Dune::NotImplemented, "Todo: implement liquidDensity()");
+    }
+
+    /*!
+     * \brief The dynamic liquid viscosity \f$\mathrm{[Pa*s]}\f$ of the pure component.
+     *
+     * \param temperature temperature of component in \f$\mathrm{[K]}\f$
+     * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$
+     */
+    static Scalar liquidViscosity(Scalar temperature, Scalar pressure)
+    {
+        // TODO: replace the line below by a meaningful return statement
+        DUNE_THROW(Dune::NotImplemented, "Todo: implement liquidViscosity()");
+    }
 };
 
 } // end namespace
diff --git a/tutorial/ex3/fluidsystems/h2omycompressiblecomponent.hh b/tutorial/ex3/fluidsystems/h2omycompressiblecomponent.hh
index 7cf90ae851..783075d4b0 100644
--- a/tutorial/ex3/fluidsystems/h2omycompressiblecomponent.hh
+++ b/tutorial/ex3/fluidsystems/h2omycompressiblecomponent.hh
@@ -412,14 +412,7 @@ public:
     static Scalar enthalpy(const FluidState &fluidState,
                            int phaseIdx)
     {
-        assert(0 <= phaseIdx && phaseIdx < numPhases);
-        if (phaseIdx == wPhaseIdx) {
-            return H2O::liquidEnthalpy(fluidState.temperature(phaseIdx), fluidState.pressure(phaseIdx));
-        }
-        else {
-            return MyCompressibleComponent::liquidEnthalpy(fluidState.temperature(phaseIdx), fluidState.pressure(phaseIdx));
-        }
-        DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);
+        DUNE_THROW(Dune::NotImplemented, "FluidSystems::H2OMyCompressibleComponent::enthalpy()");
     }
 
     using Base::heatCapacity;
@@ -427,7 +420,7 @@ public:
     static Scalar heatCapacity(const FluidState &fluidState,
                                int phaseIdx)
     {
-        DUNE_THROW(Dune::NotImplemented, "FluidSystems::H2ONAPL::heatCapacity()");
+        DUNE_THROW(Dune::NotImplemented, "FluidSystems::H2OMyCompressibleComponent::heatCapacity()");
     }
 
     using Base::thermalConductivity;
diff --git a/tutorial/solution/ex3/mycompressiblecomponent.hh b/tutorial/solution/ex3/mycompressiblecomponent.hh
index 619bedfb80..1b203ac401 100644
--- a/tutorial/solution/ex3/mycompressiblecomponent.hh
+++ b/tutorial/solution/ex3/mycompressiblecomponent.hh
@@ -99,7 +99,7 @@ public:
     /*!
      * \brief Returns true if the liquid phase is assumed to be compressible
      */
-    static bool liquidIsCompressible()
+    static constexpr bool liquidIsCompressible()
     { return true; }
 };
 
diff --git a/tutorial/solution/ex3/myincompressiblecomponent.hh b/tutorial/solution/ex3/myincompressiblecomponent.hh
index f8af80ea8a..c67b8dcc77 100644
--- a/tutorial/solution/ex3/myincompressiblecomponent.hh
+++ b/tutorial/solution/ex3/myincompressiblecomponent.hh
@@ -75,6 +75,12 @@ public:
     {
         return 5.7e-4;// [Pa*s]
     }
+
+    /*!
+     * \brief Returns true if the liquid phase is assumed to be compressible
+     */
+    static constexpr bool liquidIsCompressible()
+    { return false; }
 };
 
 } // end namespace
-- 
GitLab