From 9284edb16be9043ec3f0da02fee25e61c620682e Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 22 Aug 2013 16:22:27 +0200 Subject: [PATCH 1/9] import Dune's class name code --- opm/core/utility/ClassName.hpp | 94 ++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 opm/core/utility/ClassName.hpp diff --git a/opm/core/utility/ClassName.hpp b/opm/core/utility/ClassName.hpp new file mode 100644 index 00000000..d4a568e1 --- /dev/null +++ b/opm/core/utility/ClassName.hpp @@ -0,0 +1,94 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set ts=4 sw=2 et sts=2: +/***************************************************************************** + * * + * 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, version 2. * + * * + * This file is based on works developed by the DUNE project, see * + * . The following license exception * + * applies to it: * + * * + * As a special exception, you may use the DUNE library without * + * restriction. Specifically, if other files instantiate templates or * + * use macros or inline functions from one or more of the DUNE source * + * files, or you compile one or more of the DUNE source files and link * + * them with other files to produce an executable, this does not by * + * itself cause the resulting executable to be covered by the GNU * + * General Public License. This exception does not however invalidate * + * any other reasons why the executable file might be covered by the * + * GNU General Public License. * + * * + * 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 . * + *****************************************************************************/ +#ifndef OPM_CLASSNAME_HH +#define OPM_CLASSNAME_HH + +/** \file + * \brief A free function to provide the demangled class name + * of a given object or type as a string + */ + +#include +#include +#include + +#if HAVE_CXA_DEMANGLE +#include +#endif + +namespace Opm { + +template +class ClassNameHelper_ +{ public: + static std::string name() + { + std::string className = typeid( T ).name(); +#if HAVE_CXA_DEMANGLE + int status; + char *demangled = abi::__cxa_demangle( className.c_str(), 0, 0, &status ); + if( demangled ) + { + className = demangled; + std::free( demangled ); + } +#endif // #ifdef __GNUC__ + return className; + } +}; + +#if HAVE_QUAD +// specialize for quad precision floating point values to avoid +// needing a type_info structure +template <> +class ClassNameHelper_<__float128> +{ public: + static std::string name() + { return "quad"; } +}; +#endif + +/** \brief Provide the demangled class name of a given object as a string */ +template +std::string className() +{ + return ClassNameHelper_::name(); +} + +/** \brief Provide the demangled class name of a given object as a string */ +template +std::string className(const T &t) +{ + return ClassNameHelper_::name(); +} +} // namespace Opm + +#endif // OPM_CLASSNAME_HH From d5770b92eaef55e67626e4f9e1594e166fc3bb48 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 22 Aug 2013 16:23:14 +0200 Subject: [PATCH 2/9] Import the property system from eWoms --- opm/core/utility/PropertySystem.hpp | 1199 +++++++++++++++++++++++++++ 1 file changed, 1199 insertions(+) create mode 100644 opm/core/utility/PropertySystem.hpp diff --git a/opm/core/utility/PropertySystem.hpp b/opm/core/utility/PropertySystem.hpp new file mode 100644 index 00000000..8da8ddab --- /dev/null +++ b/opm/core/utility/PropertySystem.hpp @@ -0,0 +1,1199 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * Copyright (C) 2010-2013 by Andreas Lauser * + * * + * 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 * + * MERCHANTBILITY 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Provides the magic behind the OPM property system. + * + * Properties allow to associate arbitrary data types to + * identifiers. A property is always defined on a pair (\c TypeTag, + * \c PropertyTag) where \c TypeTag is the identifier for the object the + * property is defined for and \c PropertyTag is an unique identifier of + * the property. + * + * Type tags are hierarchic and inherit properties defined on their + * ancesters. At each level, properties defined on lower levels can be + * overwritten or even made undefined. + * + * Properties may use other properties for the respective type tag and + * these properties can also be defined on an arbitrary level of the + * hierarchy. The only restriction on this is that cycles are not + * allowed when defining properties. + */ +#ifndef OPM_PROPERTIES_HH +#define OPM_PROPERTIES_HH + +#include +#include +#include + +#include // required for 'is_base_of' + +#include +#include +#include +#include +#include +#include +#include +#include + +//! \cond SKIP_THIS + +namespace Opm { +namespace Properties { + +#define OPM_GET_HEAD_(Arg1, ...) Arg1 + +#if !defined NO_PROPERTY_INTROSPECTION + +//! Internal macro which is only required if the property introspection is enabled +#define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...) \ + template <> \ + struct PropertyInfo \ + { \ + static int init() { \ + propertyName = #PropTagName; \ + PropertyRegistryKey key( \ + /*effTypeTagName=*/ Opm::className(), \ + /*kind=*/PropKind, \ + /*name=*/#PropTagName, \ + /*value=*/#__VA_ARGS__, \ + /*file=*/__FILE__, \ + /*line=*/__LINE__); \ + PropertyRegistry::addKey(key); \ + return 0; \ + } \ + static std::string propertyName; \ + static int foo; \ + }; \ + std::string PropertyInfo::propertyName; \ + int PropertyInfo::foo = \ + PropertyInfo::init(); + +//! Internal macro which is only required if the property introspection is enabled +#define TTAG_INFO_(...) \ + template <> \ + struct TypeTagInfo \ + { \ + static int init() { \ + TypeTagRegistry::addChildren<__VA_ARGS__>(); \ + return 0; \ + } \ + static int foo; \ + }; \ + int TypeTagInfo::foo = \ + TypeTagInfo::init(); + +//! Internal macro which is only required if the property introspection is enabled +#define SPLICE_INFO_(...) \ + template <> \ + struct SpliceInfo \ + { \ + static int init() { \ + TypeTagRegistry::addSplices<__VA_ARGS__>(); \ + return 0; \ + } \ + static int foo; \ + }; \ + int SpliceInfo::foo = \ + SpliceInfo::init(); + +#else +//! Don't do anything if introspection is disabled +#define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...) +#define TTAG_INFO_(EffTypeTagName, ...) +#define SPLICE_INFO_(EffTypeTagName, ...) +#endif + +// some macros for simplification + +//! \endcond + +/*! + * \ingroup PropertySystem + * \brief Convert a type tag name to a type + * + * The main advantage of the type of a \c TypeTag is that it can be + * passed as a template argument. + */ +#define TTAG(TypeTagName) Opm::Properties::TTag::TypeTagName + +/*! + * \ingroup PropertySystem + * \brief Makes a type out of a property tag name + * + * Again property type names can be passed as template argument. This + * is rarely needed, though. + */ +#define PTAG(PropTagName) Opm::Properties::PTag::PropTagName + +/*! + * \ingroup PropertySystem + * \brief Define a new type tag. + * + * A type tag can inherit the properties defined on up to five parent + * type tags. Examples: + * + * \code + * // The type tag doesn't inherit any properties from other type tags + * NEW_TYPE_TAG(FooTypeTag); + * + * // BarTypeTag inherits all properties from FooTypeTag + * NEW_TYPE_TAG(BarTypeTag, INHERITS_FROM(FooTypeTag)); + * + * // FooBarTypeTag inherits the properties of FooTypeTag as well as + * // those of BarTypeTag. Properties defined on BarTypeTag have + * // preceedence over those defined for FooTypeTag: + * NEW_TYPE_TAG(FooBarTypeTag, INHERITS_FROM(FooTypeTag, BarTypeTag)); + * \endcode + */ +#define NEW_TYPE_TAG(...) \ + namespace TTag { \ + struct OPM_GET_HEAD_(__VA_ARGS__, blubb) \ + : public TypeTag<__VA_ARGS__> \ + { }; \ + TTAG_INFO_(__VA_ARGS__, void) \ + } \ + extern int semicolonHack_ + +/*! + * \ingroup PropertySystem + * \brief Define splices for a given type tag. + * + * Splices can be seen as children which can be overridden lower in + * the hierarchy. It can thus be seen as a "deferred inheritance" + * mechanism. Example: + * + * \code + * // First, define type tags for two different linear solvers: + * // BiCGStab and SuperLU. The first needs the "MaxIterations" + * // property, the second defines the "UsePivoting" property. + * NEW_TYPE_TAG(BiCGStabSolver); + * NEW_PROP_TAG(MaxIterations); + * SET_INT_PROP(BiCGStabSolver, MaxIterations, 100); + * + * NEW_TYPE_TAG(SuperLUSolver); + * NEW_PROP_TAG(UsePivoting); + * SET_BOOL_PROP(SuperLUSolver, UsePivoting, true); + * + * // The model type tag defines the splice 'LinearSolver' and sets it + * // to the 'BiCGStabSolver' type tag. + * NEW_TYPE_TAG(ModelTypeTag); + * NEW_PROP_TAG(LinearSolver); + * SET_SPLICES(ModelTypeTag, LinearSolver); + * SET_TAG_PROP(ModelTypeTag, LinearSolver, BiCGStabSolver); + * + * // The problem type tag is derived from the model type tag, but uses + * // the SuperLU solver. Since this is done using a splice, all properties + * // defined for the "SuperLUSolver" are inherited and the ones for the + * // BiCGStabSolver type tag are undefined + * NEW_TYPE_TAG(ProblemTypeTag, INHERITS_FROM(ModelTypeTag)); + * SET_TAG_PROP(ProblemTypeTag, LinearSolver, SuperLUSolver); + * \endcode + */ +#define SET_SPLICES(TypeTagName, ...) \ + namespace PTag { \ + template<> \ + struct Splices \ + { \ + typedef RevertedTuple<__VA_ARGS__>::type tuple; \ + }; \ + SPLICE_INFO_(TTAG(TypeTagName), __VA_ARGS__) \ + } \ + extern int semicolonHack_ + +/*! + * \ingroup PropertySystem + * \brief Syntactic sugar for NEW_TYPE_TAG. + * + * See the documentation for NEW_TYPE_TAG. + */ +#define INHERITS_FROM(...) __VA_ARGS__ + +/*! + * \ingroup PropertySystem + * \brief Define a property tag. + * + * A property tag is the unique identifier for a property. It may only + * be declared once in your program. There is also no hierarchy of + * property tags as for type tags. + * + * Examples: + * + * \code + * NEW_PROP_TAG(blubbPropTag); + * NEW_PROP_TAG(blabbPropTag); + * \endcode + */ +#define NEW_PROP_TAG(PTagName) \ + namespace PTag { \ + struct PTagName; } extern int semicolonHack_ + +//! \cond SKIP_THIS +#define SET_PROP_(EffTypeTagName, PropKind, PropTagName, ...) \ + template \ + struct Property; \ + PROP_INFO_(EffTypeTagName, \ + /*kind=*/PropKind, \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + template \ + struct Property +//! \endcond + +/*! + * \ingroup PropertySystem + * \brief Set a property for a specific type tag. + * + * After this macro, you must to specify a complete body of a class + * template, including the trailing semicolon. If you need to retrieve + * another property within the class body, you can use \c TypeTag as the + * argument for the type tag for the \c GET_PROP macro. + * + * Example: + * + * \code + * SET_PROP(FooTypeTag, blubbPropTag) + * { + * static int value = 10; + * static int calculate(int arg) + * { calculateInternal_(arg); } + * + * private: + * // retrieve the blabbProp property for the TypeTag the + * // property is defined on. Note that blabbProb does not need to + * // be defined on FooTypeTag, but can also be defined for some + * // derived type tag. + * typedef typename GET_PROP(TypeTag, blabbProp) blabb; + * + * static int calculateInternal_(int arg) + * { return arg * blabb::value; }; + * \endcode + * }; + */ +#define SET_PROP(EffTypeTagName, PropTagName) \ + template \ + struct Property; \ + PROP_INFO_(EffTypeTagName, \ + /*kind=*/"opaque", \ + PropTagName, \ + /*value=*/"") \ + template \ + struct Property + +/*! + * \ingroup PropertySystem + * \brief Explicitly unset a property for a type tag. + * + * This means that the property will not be inherited from the type + * tag's parents. + * + * Example: + * + * \code + * // make the blabbPropTag property undefined for the BarTypeTag. + * UNSET_PROP(BarTypeTag, blabbPropTag); + * \endcode + */ +#define UNSET_PROP(EffTypeTagName, PropTagName) \ + template <> \ + struct PropertyUnset; \ + PROP_INFO_(EffTypeTagName, \ + /*kind=*/"withdraw", \ + PropTagName, \ + /*value=*/) \ + template <> \ + struct PropertyUnset \ + : public PropertyExplicitlyUnset \ + {} + +/*! + * \ingroup PropertySystem + * \brief Set a property to a simple constant integer value. + * + * The constant can be accessed by the \c value attribute. + */ +#define SET_INT_PROP(EffTypeTagName, PropTagName, /*Value*/...) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"int ", \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + { \ + typedef int type; \ + static constexpr int value = __VA_ARGS__; \ + } + +/*! + * \ingroup PropertySystem + * \brief Set a property to a simple constant boolean value. + * + * The constant can be accessed by the \c value attribute. + */ +#define SET_BOOL_PROP(EffTypeTagName, PropTagName, /*Value*/...) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"bool ", \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + { \ + typedef bool type; \ + static constexpr bool value = __VA_ARGS__; \ + } + +/*! + * \ingroup PropertySystem + * \brief Set a property which defines a type. + * + * The type can be accessed by the \c type attribute. + */ +#define SET_TYPE_PROP(EffTypeTagName, PropTagName, /*Value*/...) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"type ", \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + { \ + typedef __VA_ARGS__ type; \ + } + +/*! + * \ingroup PropertySystem + * \brief Set a property to a simple constant scalar value. + * + * The constant can be accessed by the \c value attribute. In order to + * use this macro, the property tag \c Scalar needs to be defined for + * the type tag. + */ +#define SET_SCALAR_PROP(EffTypeTagName, PropTagName, ...) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"scalar", \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + { \ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; \ + public: \ + typedef Scalar type; \ + static const Scalar value; \ + }; \ + template \ + const typename Property::type \ + Property::value(__VA_ARGS__) + +/*! + * \ingroup PropertySystem + * \brief Set a property to a simple constant string value. + * + * The constant can be accessed by the \c value attribute and is of + * type std::string. + */ +#define SET_STRING_PROP(EffTypeTagName, PropTagName, ...) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"string", \ + PropTagName, \ + /*value=*/__VA_ARGS__) \ + { \ + public: \ + typedef std::string type; \ + static const std::string value; \ + }; \ + template \ + const typename Property::type \ + Property::value(__VA_ARGS__) + +/*! + * \ingroup PropertySystem + * \brief Define a property containing a type tag. + * + * This is convenient for splices. + */ +#define SET_TAG_PROP(EffTypeTagName, PropTagName, ValueTypeTagName) \ + SET_PROP_(EffTypeTagName, \ + /*kind=*/"tag ", \ + PropTagName, \ + /*value=*/TTAG(ValueTypeTagName)) \ + { \ + typedef TTAG(ValueTypeTagName) type; \ + } + + +/*! + * \ingroup PropertySystem + * \brief Retrieve a property for a type tag. + * + * If you use \c GET_PROP within a template and want to refer to some + * type (including the property itself), \c GET_PROP must be preceeded by + * the '\c typename' keyword. + */ +#define GET_PROP(TypeTag, PropTagName) \ + ::Opm::Properties::GetProperty::p +//!\cond SKIP_THIS +#define GET_PROP_(TypeTag, PropTag) \ + ::Opm::Properties::GetProperty::p +//!\endcond + +/*! + * \ingroup PropertySystem + * \brief Access the \c value attribute of a property for a type tag. + * + * This is just for convenience and equivalent to + * GET_PROP(TypeTag, PropTag)::value . If the property doesn't + * have an attribute named \c value, this yields a compiler error. + */ +#define GET_PROP_VALUE(TypeTag, PropTagName) \ + ::Opm::Properties::GetProperty::p::value +//!\cond SKIP_THIS +#define GET_PROP_VALUE_(TypeTag, PropTag) \ + ::Opm::Properties::GetProperty::p::value +//!\endcond + +/*! + * \ingroup PropertySystem + * \brief Access the \c type attribute of a property for a type tag. + * + * This is just for convenience and equivalent to + * GET_PROP(TypeTag, PropTag)::type. If the property doesn't + * have an attribute named \c type, this yields a compiler error. Also, + * if you use this macro within a template, it must be preceeded by + * the \c typename keyword. + */ +#define GET_PROP_TYPE(TypeTag, PropTagName) \ + ::Opm::Properties::GetProperty::p::type +//!\cond SKIP_THIS +#define GET_PROP_TYPE_(TypeTag, PropTag) \ + ::Opm::Properties::GetProperty::p::type +//!\endcond + +#if !defined NO_PROPERTY_INTROSPECTION +/*! + * \ingroup PropertySystem + * \brief Return a human readable diagnostic message how exactly a + * property was defined. + * + * This is only enabled if the \c NO_PROPERTY_INTROSPECTION macro is not + * defined. + * + * Example: + * + * \code + * int main() + * { + * std::cout << PROP_DIAGNOSTIC(FooBarTypeTag, blabbPropTag) << "\n"; + * }; + * \endcode + */ +#define PROP_DIAGNOSTIC(TypeTag, PropTagName) \ + ::Opm::Properties::getDiagnostic(#PropTagName) + +#else +#define PROP_DIAGNOSTIC(TypeTag, PropTagName) "Property introspection disabled by macro NO_PROPERTY_INTROSPECTION." +#endif + +////////////////////////////////////////////// +// some serious template kung fu. Don't look at it too closely, it +// might damage your brain! +////////////////////////////////////////////// + +//! \cond SKIP_THIS + +namespace PTag {} +namespace TTag {} + +#if !defined NO_PROPERTY_INTROSPECTION + +namespace TTag +{ +template +struct TypeTagInfo +{}; +} + +namespace PTag +{ +template +struct SpliceInfo +{}; +} + +template +struct PropertyInfo +{}; + +class PropertyRegistryKey +{ +public: + PropertyRegistryKey() + {} + + PropertyRegistryKey(const std::string &effTypeTagName, + const std::string &propertyKind, + const std::string &propertyName, + const std::string &propertyValue, + const std::string &fileDefined, + int lineDefined) + : effTypeTagName_(effTypeTagName) + , propertyKind_(propertyKind) + , propertyName_(propertyName) + , propertyValue_(propertyValue) + , fileDefined_(fileDefined) + , lineDefined_(lineDefined) + { + } + + // copy constructor + PropertyRegistryKey(const PropertyRegistryKey &v) + : effTypeTagName_(v.effTypeTagName_) + , propertyKind_(v.propertyKind_) + , propertyName_(v.propertyName_) + , propertyValue_(v.propertyValue_) + , fileDefined_(v.fileDefined_) + , lineDefined_(v.lineDefined_) + {} + + const std::string &effTypeTagName() const + { return effTypeTagName_; } + const std::string &propertyKind() const + { return propertyKind_; } + const std::string &propertyName() const + { return propertyName_; } + const std::string &propertyValue() const + { return propertyValue_; } + const std::string &fileDefined() const + { return fileDefined_; } + int lineDefined() const + { return lineDefined_; } + +private: + std::string effTypeTagName_; + std::string propertyKind_; + std::string propertyName_; + std::string propertyValue_; + std::string fileDefined_; + int lineDefined_; +}; + + +template +struct GetProperty; + +class TypeTagRegistry +{ +public: + struct SpliceRegistryEntryBase { + virtual ~SpliceRegistryEntryBase() {}; + virtual std::string propertyName() const = 0; + }; + + template + struct SpliceRegistryEntry : public SpliceRegistryEntryBase + { + virtual std::string propertyName() const + { return PropertyInfo::template GetEffectiveTypeTag_::type, PropTag>::propertyName; } + }; + + typedef std::list SpliceList; + typedef std::map SpliceListMap; + + typedef std::list ChildrenList; + typedef std::map ChildrenListMap; + + // end of recursion. the last argument is not a child, but 'void' + // which is required for the macro magic... + template + static void addChildren() + {} + + // the last argument is not a child, but 'void' which is required + // for the macro magic... + template + static void addChildren() + { + std::string typeTagName = Opm::className(); + children_[typeTagName].push_front(Opm::className()); + addChildren(); + } + + // end of recursion. the last argument is not a child, but 'void' + // which is required for the macro magic... + template + static void addSplices() + { } + + // the last argument is not a child, but 'void' which is required + // for the macro magic... + template + static void addSplices() + { + std::string typeTagName = Opm::className(); + + SpliceRegistryEntry *tmp = new SpliceRegistryEntry; + + splices_[typeTagName].push_front(tmp); + addSplices(); + } + + static const SpliceList &splices(const std::string &typeTagName) + { return splices_[typeTagName]; } + + static const ChildrenList &children(const std::string &typeTagName) + { return children_[typeTagName]; } + +private: + static SpliceListMap splices_; + static ChildrenListMap children_; +}; + +TypeTagRegistry::SpliceListMap TypeTagRegistry::splices_; +TypeTagRegistry::ChildrenListMap TypeTagRegistry::children_; + +class PropertyRegistry +{ +public: + typedef std::map KeyList; + typedef std::map KeyListMap; + + static void addKey(const PropertyRegistryKey &key) + { + keys_[key.effTypeTagName()][key.propertyName()] = key; + } + + static const std::string &getSpliceTypeTagName(const std::string &typeTagName, + const std::string &propertyName) + { + const auto &keyIt = keys_.find(typeTagName); + const auto &keyEndIt = keys_.end(); + if (keyIt == keyEndIt) + OPM_THROW(std::runtime_error, + "Unknown type tag key '" << typeTagName << "'"); + + // check whether the propery is defined for the type tag + // currently checked + const auto &propIt = keyIt->second.find(propertyName); + const auto &propEndIt = keyIt->second.end(); + if (propIt != propEndIt) + return propIt->second.propertyValue(); + + // if not, check all children + typedef TypeTagRegistry::ChildrenList ChildrenList; + const ChildrenList &children = TypeTagRegistry::children(typeTagName); + ChildrenList::const_iterator ttagIt = children.begin(); + for (; ttagIt != children.end(); ++ttagIt) { + const auto &tmp = getSpliceTypeTagName(*ttagIt, propertyName); + if (tmp != "") + return tmp; + } + + // if the property was not defined on a given type tag, return + // the empty string. + static std::string tmp(""); + return tmp; + } + + static const PropertyRegistryKey &getKey(const std::string &effTypeTagName, + const std::string &propertyName) + { + return keys_[effTypeTagName][propertyName]; + } + + static const KeyList &getKeys(const std::string &effTypeTagName) + { + return keys_[effTypeTagName]; + } + +private: + static KeyListMap keys_; +}; +PropertyRegistry::KeyListMap PropertyRegistry::keys_; + +#endif // !defined NO_PROPERTY_INTROSPECTION + +struct PropertyUndefined { }; +class PropertyExplicitlyUnset {}; + +template +struct Property : public PropertyUndefined +{}; + +template +struct PropertyUnset : public PropertyUndefined +{}; + +template +struct propertyExplicitlyUnset +{ + const static bool value = + std::is_base_of + >::value; +}; + +template +class propertyExplicitlyUnsetOnTree +{ + static constexpr bool explicitlyUnset = propertyExplicitlyUnset::value; + + template + struct unsetOnAllChildren + { static constexpr bool value = true; }; + + template + struct unsetOnAllChildren > + { static constexpr bool value = + propertyExplicitlyUnsetOnTree::value + && unsetOnAllChildren >::value; }; + +public: + static constexpr bool value = + (explicitlyUnset || (!Tree::isLeaf && unsetOnAllChildren::value)); +}; + +template +struct propertyExplicitlyUnsetOnTree +{ + const static bool value = std::true_type::value; +}; + +template +struct propertyDefinedOnSelf +{ + const static bool value = + ! std::is_base_of >::value; +}; + + +// template class to revert the order or a std::tuple's +// arguments. This is required to make the properties of children +// defined on the right overwrite the properties of the previous +// children. this is not a very nice solution, but it works... +template +struct RevertedTuple; + +template <> +struct RevertedTuple<> +{ typedef std::tuple<> type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +struct RevertedTuple +{ typedef std::tuple type; }; + +template +class TypeTag +{ +public: + typedef SelfT SelfType; + + typedef typename RevertedTuple::type ChildrenTuple; + static constexpr bool isLeaf = std::is_same >::value; +}; + +namespace PTag { +// this class needs to be located in the PTag namespace for reasons +// you don't really want to know... +template +struct Splices +{ + typedef typename std::tuple<> tuple; +}; +} // namespace PTag + +// retrieve a property which is not defined on a splice +template +struct GetDirectProperty_ +{ + // set the ::type attribute to the type tag for which the + // requested property was defined. First check whether the + // property is directly defined for the type tag, and if not, + // check all splices, then check all children + template ::value > + struct GetEffectiveTypeTag_; + + // set the ::type attribute to the child type tag for which the + // requested property was defined. The first child is ignored. + template + struct TraverseRemainingChildren_; + + // if the first argument != void this is the value of the ::type member, ... + template + struct StopAtFirstChildElseTraverseRemaining_ + { typedef EffTypeTag type; }; + + // ... or else the type tag is defined by the remaining children + template + struct StopAtFirstChildElseTraverseRemaining_ + { typedef typename TraverseRemainingChildren_ >::type type; }; + + // set the ::type attribute to the type tag to the child for which + // the requested property was defined, or ... + template + struct TraverseRemainingChildren_ > + { typedef typename StopAtFirstChildElseTraverseRemaining_::type, RemainingChildren...>::type type; }; + + // ... if there there are no children which we did not check + // anymore, the ::type attribute is void (i.e. the property was + // not defined for a given subtree) + template + struct TraverseRemainingChildren_ > + { typedef void type; }; + + template + struct GetEffectiveTypeTag_ + { typedef CurTree type; }; + + template + struct GetEffectiveTypeTag_ + { typedef typename TraverseRemainingChildren_::type type; }; + +public: + typedef Property::type, PropertyTag> p; +}; + +template +struct GetProperty +{ + // set the ::type attribute to the type tag for which the + // requested property was defined. First check whether the + // property is directly defined for the type tag, and if not, + // check all splices, then check all children + template ::value > + struct GetEffectiveTypeTag_; + + // set the ::type attribute to the child type tag for which the + // requested property was defined. The first child is ignored. + template + struct TraverseRemainingChildren_; + + // set the ::type attribute to the type tag for which the + // requested property was defined. First check all splices of the + // type tag, then check all children. The first splice is ignored. + template + struct TraverseRemainingSplicesAndChildren_; + + // if the first argument != void this is the value of the ::type member, ... + template + struct StopAtFirstChildElseTraverseRemaining_ + { typedef EffTypeTag type; }; + + // ... or else the type tag is defined by the remaining children + template + struct StopAtFirstChildElseTraverseRemaining_ + { typedef typename TraverseRemainingChildren_ >::type type; }; + + // set the ::type attribute to the type tag to the child for which + // the requested property was defined, or ... + template + struct TraverseRemainingChildren_ > + { typedef typename StopAtFirstChildElseTraverseRemaining_::type, RemainingChildren...>::type type; }; + + // ... if there there are no children which we did not check + // anymore, the ::type attribute is void (i.e. the property was + // not defined for a given subtree) + template + struct TraverseRemainingChildren_ > + { typedef void type; }; + + template + struct StopAtSpliceIfPropDefinedElseTraverseRemaining_ + { typedef EffTypeTag type; }; + + template + struct StopAtSpliceIfPropDefinedElseTraverseRemaining_ + { typedef typename TraverseRemainingSplicesAndChildren_ >::type type; }; + + // if the property was defined for the current splice, stop + // here. If not... + template + struct StopAtFirstSpliceElseTraverseRemaining_ + { typedef typename StopAtSpliceIfPropDefinedElseTraverseRemaining_::type, + RemainingSplices...>::type type; }; + + // ... check the remaining splices. + template + struct StopAtFirstSpliceElseTraverseRemaining_ + { typedef typename TraverseRemainingSplicesAndChildren_ >::type type; }; + + // check whether the property is defined on the remaining splices + // of a list (i.e. discard its first member) ... + template + struct TraverseRemainingSplicesAndChildren_ > + { typedef typename StopAtFirstSpliceElseTraverseRemaining_, RemainingSplices...>::type type; }; + + // ... or if there are no splices left to check, proceed with the + // children of the type tag. + template + struct TraverseRemainingSplicesAndChildren_ > + { typedef typename TraverseRemainingChildren_::type type; }; + + template + struct GetEffectiveTypeTag_ + { typedef CurTree type; }; + + template + struct GetEffectiveTypeTag_ + { typedef typename TraverseRemainingSplicesAndChildren_::tuple >::type type; }; + +public: + typedef Property::type, PropertyTag> p; + typedef typename GetEffectiveTypeTag_::type q; +}; + +#if !defined NO_PROPERTY_INTROSPECTION +int myReplaceAll_(std::string &s, + const std::string &pattern, + const std::string &replacement) +{ + size_t pos; + int i = 0; + while ( (pos = s.find(pattern)) != s.npos) { + s.replace(pos, pattern.size(), replacement); + ++i; + }; + return i; +} + +std::string canonicalTypeTagNameToName_(const std::string &canonicalName) +{ + std::string result(canonicalName); + myReplaceAll_(result, "Opm::Properties::TTag::", "TTAG("); + myReplaceAll_(result, "::", ""); + result += ")"; + return result; +} + +inline bool getDiagnostic_(const std::string &typeTagName, + const std::string &propTagName, + std::string &result, + const std::string indent) +{ + const PropertyRegistryKey *key = 0; + + const PropertyRegistry::KeyList &keys = + PropertyRegistry::getKeys(typeTagName); + PropertyRegistry::KeyList::const_iterator it = keys.begin(); + for (; it != keys.end(); ++it) { + if (it->second.propertyName() == propTagName) { + key = &it->second; + break; + }; + } + + if (key) { + std::ostringstream oss; + oss << indent + << key->propertyKind() << " " + << key->propertyName() << " defined on '" + << canonicalTypeTagNameToName_(key->effTypeTagName()) << "' at " + << key->fileDefined() << ":" << key->lineDefined() << "\n"; + result = oss.str(); + return true; + } + + // print properties defined on children + typedef TypeTagRegistry::ChildrenList ChildrenList; + const ChildrenList &children = TypeTagRegistry::children(typeTagName); + ChildrenList::const_iterator ttagIt = children.begin(); + std::string newIndent = indent + " "; + for (; ttagIt != children.end(); ++ttagIt) { + if (getDiagnostic_(*ttagIt, propTagName, result, newIndent)) { + result.insert(0, indent + "Inherited from " + canonicalTypeTagNameToName_(typeTagName) + "\n"); + return true; + } + } + + return false; +} + +template +const std::string getDiagnostic(std::string propTagName) +{ + std::string result; + + std::string TypeTagName(Opm::className()); + + propTagName.replace(0, strlen("PTag("), ""); + int n = propTagName.length(); + propTagName.replace(n - 1, 1, ""); + //TypeTagName.replace(0, strlen("Opm::Properties::TTag::"), ""); + + return result; +} + +inline void print_(const std::string &rootTypeTagName, + const std::string &curTypeTagName, + const std::string &splicePropName, + std::ostream &os, + const std::string indent, + std::set &printedProperties) +{ + if (indent == "") { + os << indent << "###########\n"; + os << indent << "# Properties\n"; + os << indent << "###########\n"; + os << indent << "Properties for " << canonicalTypeTagNameToName_(curTypeTagName) << ":"; + } + else if (splicePropName != "") + os << indent << "Inherited from splice " << splicePropName << " (set to " << canonicalTypeTagNameToName_(curTypeTagName) << "):"; + else + os << indent << "Inherited from " << canonicalTypeTagNameToName_(curTypeTagName) << ":"; + const PropertyRegistry::KeyList &keys = + PropertyRegistry::getKeys(curTypeTagName); + PropertyRegistry::KeyList::const_iterator it = keys.begin(); + bool somethingPrinted = false; + for (; it != keys.end(); ++it) { + const PropertyRegistryKey &key = it->second; + if (printedProperties.count(key.propertyName()) > 0) + continue; // property already printed + if (!somethingPrinted) { + os << "\n"; + somethingPrinted = true; + } + os << indent << " " + << key.propertyKind() << " " << key.propertyName(); + if (key.propertyKind() != "opaque") { + std::string s(key.propertyValue()); + myReplaceAll_(s, "typename ", ""); + if (myReplaceAll_(s, "::Opm::Properties::TTag::", "TTAG(")) + s += ')'; + myReplaceAll_(s, "::Opm::Properties::PTag::", ""); + myReplaceAll_(s, "::Opm::Properties::GetProperty<", "GET_PROP("); + myReplaceAll_(s, ">::p::", ")::"); + myReplaceAll_(s, "GET_PROP(TypeTag, Scalar)::type", "Scalar"); + + os << " = '" << s << "'"; + } + os << " defined at " << key.fileDefined() + << ":" << key.lineDefined() + << "\n"; + printedProperties.insert(key.propertyName()); + }; + if (!somethingPrinted) + os << " (none)\n"; + // print properties defined on splices or children + std::string newIndent = indent + " "; + + // first, iterate over the splices, ... + typedef TypeTagRegistry::SpliceList SpliceList; + const SpliceList &splices = TypeTagRegistry::splices(curTypeTagName); + SpliceList::const_iterator spliceIt = splices.begin(); + for (; spliceIt != splices.end(); ++ spliceIt) { + const auto &spliceTypeTagName = PropertyRegistry::getSpliceTypeTagName(rootTypeTagName, + (*spliceIt)->propertyName()); + print_(rootTypeTagName, spliceTypeTagName, (*spliceIt)->propertyName(), os, newIndent, printedProperties); + } + + // ... then, over the children + typedef TypeTagRegistry::ChildrenList ChildrenList; + const ChildrenList &children = TypeTagRegistry::children(curTypeTagName); + ChildrenList::const_iterator ttagIt = children.begin(); + for (; ttagIt != children.end(); ++ttagIt) { + print_(rootTypeTagName, *ttagIt, /*splicePropName=*/"", os, newIndent, printedProperties); + } +} + +template +void printValues(std::ostream &os = std::cout) +{ + std::set printedProps; + print_(Opm::className(), Opm::className(), /*splicePropertyName=*/"", os, /*indent=*/"", printedProps); +} +#else // !defined NO_PROPERTY_INTROSPECTION +template +void printValues(std::ostream &os = std::cout) +{ + std::cout << + "The eWoms property system was compiled with the macro\n" + "NO_PROPERTY_INTROSPECTION defined.\n" + "No diagnostic messages this time, sorry.\n"; +} + +template +const std::string getDiagnostic(std::string propTagName) +{ + std::string result; + result = + "The eWoms property system was compiled with the macro\n" + "NO_PROPERTY_INTROSPECTION defined.\n" + "No diagnostic messages this time, sorry.\n"; + return result; +} + +#endif // !defined NO_PROPERTY_INTROSPECTION + +//! \endcond + +} // namespace Properties +} // namespace Opm + +#endif From e15a28de68c5fa329ddc01de7ed9103d23ee346b Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 22 Aug 2013 16:07:04 +0200 Subject: [PATCH 3/9] add authors to the files according to git logs --- opm/core/utility/ClassName.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opm/core/utility/ClassName.hpp b/opm/core/utility/ClassName.hpp index d4a568e1..16d7a4f8 100644 --- a/opm/core/utility/ClassName.hpp +++ b/opm/core/utility/ClassName.hpp @@ -1,6 +1,9 @@ // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set ts=4 sw=2 et sts=2: /***************************************************************************** + * Copyright (C) 2012-2013 by Andreas Lauser * + * Copyright (C) 2010 by Oliver Sander * + * Copyright (C) 2011 by Martin Nolte * * * * 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 * From 9733d9c995194dc5cfeb1b0f372ac89906fca256 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 22 Aug 2013 18:54:28 +0200 Subject: [PATCH 4/9] add a test for the property system --- CMakeLists_files.cmake | 1 + tests/test_propertysystem.cpp | 196 ++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 tests/test_propertysystem.cpp diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index e85e4fbe..5d665acf 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -140,6 +140,7 @@ list (APPEND MAIN_SOURCE_FILES # find tests -name '*.cpp' -a ! -wholename '*/not-unit/*' -printf '\t%p\n' | sort list (APPEND TEST_SOURCE_FILES tests/test_spline.cpp + tests/test_propertysystem.cpp tests/test_dgbasis.cpp tests/test_cartgrid.cpp tests/test_cubic.cpp diff --git a/tests/test_propertysystem.cpp b/tests/test_propertysystem.cpp new file mode 100644 index 00000000..aa1ae359 --- /dev/null +++ b/tests/test_propertysystem.cpp @@ -0,0 +1,196 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * Copyright (C) 2010-2012 by Andreas Lauser * + * * + * 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 . * + *****************************************************************************/ +/*! + * \file + * + * \brief This file tests the properties system. + * + * We define a few type tags and property tags, then we attach values + * to (TypeTag, PropertyTag) tuples and finally we use them in the + * main function and print some diagnostic messages. + */ +#include "config.h" + +#include + +#include + +namespace Opm { +namespace Properties { + +/////////////////// +// Define some hierarchy of type tags: +// +// Vehicle -- CompactCar -- Sedan -_ +// \ \. +// \ +- Pickup ---_ +// \ / \. +// +-- Truck ---------------^ \. +// \ \. +// +- Tank ----------------------------------+- HummerH1 +/////////////////// +NEW_TYPE_TAG(Vehicle); + +NEW_TYPE_TAG(CompactCar, INHERITS_FROM(Vehicle)); +NEW_TYPE_TAG(Truck, INHERITS_FROM(Vehicle)); +NEW_TYPE_TAG(Tank, INHERITS_FROM(Vehicle)); + +NEW_TYPE_TAG(Sedan, INHERITS_FROM(CompactCar)); +NEW_TYPE_TAG(Pickup, INHERITS_FROM(Sedan, Truck)); + +NEW_TYPE_TAG(HummerH1, INHERITS_FROM(Sedan, Pickup, Tank)); + +/////////////////// +// Define the property tags: +// TopSpeed, NumSeats, CanonCaliber, GasUsage, AutomaticTransmission, Payload +/////////////////// +NEW_PROP_TAG(TopSpeed); // [km/h] +NEW_PROP_TAG(NumSeats); // [] +NEW_PROP_TAG(CanonCaliber); // [mm] +NEW_PROP_TAG(GasUsage); // [l/100km] +NEW_PROP_TAG(AutomaticTransmission); // true/false +NEW_PROP_TAG(Payload); // [t] + +/////////////////// +// Make the AutomaticTransmission default to false +SET_BOOL_PROP(Vehicle, AutomaticTransmission, false); + +/////////////////// +// Define some values for the properties on the type tags: +// +// (CompactCar, TopSpeed) = GasUsage*35 +// (CompactCar, NumSeats) = 5 +// (CompactCar, GasUsage) = 4 +// +// (Truck, TopSpeed) = 100 +// (Truck, NumSeats) = 2 +// (Truck, GasUsage) = 12 +// (Truck, Payload) = 35 +// +// (Tank, TopSpeed) = 60 +// (Tank, GasUsage) = 65 +// (Tank, CanonCaliber) = 120 +// +// (Sedan, GasUsage) = 7 +// (Sedan, AutomaticTransmission) = true +// +// (Pickup, TopSpeed) = 120 +// (Pickup, Payload) = 5 +// +// (HummmerH1, TopSpeed) = (Pickup, TopSpeed) +/////////////////// + +SET_INT_PROP(CompactCar, TopSpeed, GET_PROP_VALUE(TypeTag, GasUsage) * 30); +SET_INT_PROP(CompactCar, NumSeats, 5); +SET_INT_PROP(CompactCar, GasUsage, 4); + +SET_INT_PROP(Truck, TopSpeed, 100); +SET_INT_PROP(Truck, NumSeats, 2); +SET_INT_PROP(Truck, GasUsage, 12); +SET_INT_PROP(Truck, Payload, 35); + +SET_INT_PROP(Tank, TopSpeed, 60); +SET_INT_PROP(Tank, GasUsage, 65); +SET_INT_PROP(Tank, CanonCaliber, 120); + +SET_INT_PROP(Sedan, GasUsage, 7); +SET_BOOL_PROP(Sedan, AutomaticTransmission, true); + +SET_INT_PROP(Pickup, TopSpeed, 120); +SET_INT_PROP(Pickup, Payload, 5); + +SET_INT_PROP(HummerH1, TopSpeed, GET_PROP_VALUE(TTAG(Pickup), TopSpeed)); + +/////////////////// +// Unmount the canon from the Hummer +UNSET_PROP(HummerH1, CanonCaliber); + +} // namespace Properties +} // namespace Opm + + +int main() +{ + // print all properties for all type tags + std::cout << "---------------------------------------\n"; + std::cout << "-- Property values\n"; + std::cout << "---------------------------------------\n"; + + std::cout << "---------- Values for CompactCar ----------\n"; + + std::cout << "(CompactCar, TopSpeed) = " << GET_PROP_VALUE(TTAG(CompactCar), TopSpeed) << "\n"; + std::cout << "(CompactCar, NumSeats) = " << GET_PROP_VALUE(TTAG(CompactCar), NumSeats) << "\n"; + std::cout << "(CompactCar, GasUsage) = " << GET_PROP_VALUE(TTAG(CompactCar), GasUsage) << "\n"; + std::cout << "(CompactCar, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(CompactCar), AutomaticTransmission) << "\n"; + + std::cout << "---------- Values for Truck ----------\n"; + + std::cout << "(Truck, TopSpeed) = " << GET_PROP_VALUE(TTAG(Truck), TopSpeed) << "\n"; + std::cout << "(Truck, NumSeats) = " << GET_PROP_VALUE(TTAG(Truck), NumSeats) << "\n"; + std::cout << "(Truck, GasUsage) = " << GET_PROP_VALUE(TTAG(Truck), GasUsage) << "\n"; + std::cout << "(Truck, Payload) = " << GET_PROP_VALUE(TTAG(Truck), Payload) << "\n"; + std::cout << "(Truck, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(Truck), AutomaticTransmission) << "\n"; + + std::cout << "---------- Values for Tank ----------\n"; + + std::cout << "(Tank, TopSpeed) = " << GET_PROP_VALUE(TTAG(Tank), TopSpeed) << "\n"; + std::cout << "(Tank, GasUsage) = " << GET_PROP_VALUE(TTAG(Tank), GasUsage) << "\n"; + std::cout << "(Tank, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(Tank), AutomaticTransmission) << "\n"; + std::cout << "(Tank, CanonCaliber) = " << GET_PROP_VALUE(TTAG(Tank), CanonCaliber) << "\n"; + + std::cout << "---------- Values for Sedan ----------\n"; + + std::cout << "(Sedan, TopSpeed) = " << GET_PROP_VALUE(TTAG(Sedan), TopSpeed) << "\n"; + std::cout << "(Sedan, NumSeats) = " << GET_PROP_VALUE(TTAG(Sedan), NumSeats) << "\n"; + std::cout << "(Sedan, GasUsage) = " << GET_PROP_VALUE(TTAG(Sedan), GasUsage) << "\n"; + std::cout << "(Sedan, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(Sedan), AutomaticTransmission) << "\n"; + + std::cout << "---------- Values for Pickup ----------\n"; + std::cout << "(Pickup, TopSpeed) = " << GET_PROP_VALUE(TTAG(Pickup), TopSpeed) << "\n"; + std::cout << "(Pickup, NumSeats) = " << GET_PROP_VALUE(TTAG(Pickup), NumSeats) << "\n"; + std::cout << "(Pickup, GasUsage) = " << GET_PROP_VALUE(TTAG(Pickup), GasUsage) << "\n"; + std::cout << "(Pickup, Payload) = " << GET_PROP_VALUE(TTAG(Pickup), Payload) << "\n"; + std::cout << "(Pickup, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(Pickup), AutomaticTransmission) << "\n"; + + std::cout << "---------- Values for HummerH1 ----------\n"; + std::cout << "(HummerH1, TopSpeed) = " << GET_PROP_VALUE(TTAG(HummerH1), TopSpeed) << "\n"; + std::cout << "(HummerH1, NumSeats) = " << GET_PROP_VALUE(TTAG(HummerH1), NumSeats) << "\n"; + std::cout << "(HummerH1, GasUsage) = " << GET_PROP_VALUE(TTAG(HummerH1), GasUsage) << "\n"; + std::cout << "(HummerH1, Payload) = " << GET_PROP_VALUE(TTAG(HummerH1), Payload) << "\n"; + std::cout << "(HummerH1, AutomaticTransmission) = " << GET_PROP_VALUE(TTAG(HummerH1), AutomaticTransmission) << "\n"; + // CanonCaliber is explcitly unset for the Hummer -> this would not compile: + // std::cout << "(HummerH1, CanonCaliber) = " << GET_PROP_VALUE(TTAG(HummerH1), CanonCaliber) << "\n"; + + std::cout << "\n"; + std::cout << "---------------------------------------\n"; + std::cout << "-- Diagnostic messages\n"; + std::cout << "---------------------------------------\n"; + + std::cout << "---- All properties for Sedan ---\n"; + Opm::Properties::printValues(); + + std::cout << "---- Message for (HummerH1, CanonCaliber) ---\n" + << PROP_DIAGNOSTIC(TTAG(HummerH1), CanonCaliber); + std::cout << "---- Message for (HummerH1, GasUsage) ---\n" + << PROP_DIAGNOSTIC(TTAG(HummerH1), GasUsage); + std::cout << "---- Message for (HummerH1, AutomaticTransmission) ---\n" + << PROP_DIAGNOSTIC(TTAG(HummerH1), AutomaticTransmission); + + return 0; +} From 783950060dc61aa28bbd1d845ed4480788ecf769 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 23 Aug 2013 12:25:24 +0200 Subject: [PATCH 5/9] make sure the header files related to the property system are installed --- CMakeLists_files.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 5d665acf..53797e2b 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -326,6 +326,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/core/transport/reorder/reordersequence.h opm/core/transport/reorder/tarjan.h opm/core/utility/Average.hpp + opm/core/utility/ClassName.hpp opm/core/utility/DataMap.hpp opm/core/utility/ErrorMacros.hpp opm/core/utility/Event.hpp @@ -360,6 +361,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/core/utility/parameters/ParameterXML.hpp opm/core/utility/parameters/tinyxml/tinystr.h opm/core/utility/parameters/tinyxml/tinyxml.h + opm/core/utility/PropertySystem.hpp opm/core/wells/InjectionSpecification.hpp opm/core/wells/ProductionSpecification.hpp opm/core/wells/WellCollection.hpp From d416ed279be39a920d42ac0047c191b4caf2cc34 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Thu, 19 Sep 2013 20:03:36 +0200 Subject: [PATCH 6/9] add Exceptions.hpp to the list of public header files --- CMakeLists_files.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 53797e2b..de50898e 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -331,6 +331,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/core/utility/ErrorMacros.hpp opm/core/utility/Event.hpp opm/core/utility/Event_impl.hpp + opm/core/utility/Exceptions.hpp opm/core/utility/Factory.hpp opm/core/utility/MonotCubicInterpolator.hpp opm/core/utility/NonuniformTableLinear.hpp From c3cc0598604ab1c5bb563303bf960f9b55255e43 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 20 Sep 2013 12:18:10 +0200 Subject: [PATCH 7/9] className(): remove unused argument object for the className(foo) variant some compilers may warn about this under some circumstances. --- opm/core/utility/ClassName.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/utility/ClassName.hpp b/opm/core/utility/ClassName.hpp index 16d7a4f8..54c49d2d 100644 --- a/opm/core/utility/ClassName.hpp +++ b/opm/core/utility/ClassName.hpp @@ -88,7 +88,7 @@ std::string className() /** \brief Provide the demangled class name of a given object as a string */ template -std::string className(const T &t) +std::string className(const T &) { return ClassNameHelper_::name(); } From 1b3217ec4b37542d953e02530ce401fed62d609c Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 20 Sep 2013 12:31:40 +0200 Subject: [PATCH 8/9] className(): get rid of the ugly ClassNameHelper_ class since full specialization of function templates is okay in C++ (only partial specialization is not allowed for them). --- opm/core/utility/ClassName.hpp | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/opm/core/utility/ClassName.hpp b/opm/core/utility/ClassName.hpp index 54c49d2d..046bc893 100644 --- a/opm/core/utility/ClassName.hpp +++ b/opm/core/utility/ClassName.hpp @@ -48,12 +48,10 @@ #endif namespace Opm { - +/** \brief Provide the demangled class name of a given object as a string */ template -class ClassNameHelper_ -{ public: - static std::string name() - { +std::string className() +{ std::string className = typeid( T ).name(); #if HAVE_CXA_DEMANGLE int status; @@ -65,32 +63,21 @@ class ClassNameHelper_ } #endif // #ifdef __GNUC__ return className; - } -}; +} #if HAVE_QUAD // specialize for quad precision floating point values to avoid // needing a type_info structure template <> -class ClassNameHelper_<__float128> -{ public: - static std::string name() - { return "quad"; } -}; +std::string className<__float128>() +{ return "quad"; } #endif -/** \brief Provide the demangled class name of a given object as a string */ -template -std::string className() -{ - return ClassNameHelper_::name(); -} - /** \brief Provide the demangled class name of a given object as a string */ template std::string className(const T &) { - return ClassNameHelper_::name(); + return className(); } } // namespace Opm From 71e6638f04b41ee9a3c734706ec49453654b5d61 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 20 Sep 2013 12:45:10 +0200 Subject: [PATCH 9/9] className(): minor comment and guard macro name fixes --- opm/core/utility/ClassName.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opm/core/utility/ClassName.hpp b/opm/core/utility/ClassName.hpp index 046bc893..4d55d3b8 100644 --- a/opm/core/utility/ClassName.hpp +++ b/opm/core/utility/ClassName.hpp @@ -31,8 +31,8 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * *****************************************************************************/ -#ifndef OPM_CLASSNAME_HH -#define OPM_CLASSNAME_HH +#ifndef OPM_CLASSNAME_HPP +#define OPM_CLASSNAME_HPP /** \file * \brief A free function to provide the demangled class name @@ -61,7 +61,7 @@ std::string className() className = demangled; std::free( demangled ); } -#endif // #ifdef __GNUC__ +#endif // HAVE_CXA_DEMANGLE return className; } @@ -81,4 +81,4 @@ std::string className(const T &) } } // namespace Opm -#endif // OPM_CLASSNAME_HH +#endif // OPM_CLASSNAME_HPP