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