propertysystem.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2010-2014 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
40 #ifndef EWOMS_PROPERTIES_HH
41 #define EWOMS_PROPERTIES_HH
42 
43 #include <opm/material/common/ClassName.hpp>
44 #include <opm/common/ErrorMacros.hpp>
45 #include <opm/common/Exceptions.hpp>
46 
47 #include <type_traits> // required for 'is_base_of<A, B>'
48 
49 #include <map>
50 #include <set>
51 #include <list>
52 #include <string>
53 #include <iostream>
54 #include <sstream>
55 #include <cstring>
56 #include <tuple>
57 
59 
60 namespace Ewoms {
61 namespace Properties {
62 
63 #define EWOMS_GET_HEAD_(Arg1, ...) Arg1
64 
65 #if !defined NO_PROPERTY_INTROSPECTION
66 
68 #define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...) \
69  template <> \
70  struct PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)> \
71  { \
72  static int init() { \
73  propertyName = #PropTagName; \
74  PropertyRegistryKey key( \
75  /*effTypeTagName=*/ Opm::className<TTAG(EffTypeTagName)>(), \
76  /*kind=*/PropKind, \
77  /*name=*/#PropTagName, \
78  /*value=*/#__VA_ARGS__, \
79  /*file=*/__FILE__, \
80  /*line=*/__LINE__); \
81  PropertyRegistry::addKey(key); \
82  return 0; \
83  } \
84  static std::string propertyName; \
85  static int foo; \
86  }; \
87  std::string PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)>::propertyName; \
88  int PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)>::foo = \
89  PropertyInfo<TTAG(EffTypeTagName), PTAG(PropTagName)>::init();
90 
92 #define TTAG_INFO_(...) \
93  template <> \
94  struct TypeTagInfo<EWOMS_GET_HEAD_(__VA_ARGS__)> \
95  { \
96  static int init() { \
97  TypeTagRegistry::addChildren<__VA_ARGS__>(); \
98  return 0; \
99  } \
100  static int foo; \
101  }; \
102  int TypeTagInfo<EWOMS_GET_HEAD_(__VA_ARGS__)>::foo = \
103  TypeTagInfo<EWOMS_GET_HEAD_(__VA_ARGS__)>::init();
104 
106 #define SPLICE_INFO_(...) \
107  template <> \
108  struct SpliceInfo<EWOMS_GET_HEAD_(__VA_ARGS__)> \
109  { \
110  static int init() { \
111  TypeTagRegistry::addSplices<__VA_ARGS__>(); \
112  return 0; \
113  } \
114  static int foo; \
115  }; \
116  int SpliceInfo<EWOMS_GET_HEAD_(__VA_ARGS__)>::foo = \
117  SpliceInfo<EWOMS_GET_HEAD_(__VA_ARGS__)>::init();
118 
119 #else
120 #define PROP_INFO_(EffTypeTagName, PropKind, PropTagName, ...)
122 #define TTAG_INFO_(EffTypeTagName, ...)
123 #define SPLICE_INFO_(EffTypeTagName, ...)
124 #endif
125 
126 // some macros for simplification
127 
129 
137 #define TTAG(TypeTagName) Ewoms::Properties::TTag::TypeTagName
138 
146 #define PTAG(PropTagName) Ewoms::Properties::PTag::PropTagName
147 
168 #define NEW_TYPE_TAG(...) \
169  namespace TTag { \
170  struct EWOMS_GET_HEAD_(__VA_ARGS__, blubb) \
171  : public TypeTag<__VA_ARGS__> \
172  { }; \
173  TTAG_INFO_(__VA_ARGS__, void) \
174  } \
175  extern int semicolonHack_
176 
212 #define SET_SPLICES(TypeTagName, ...) \
213  namespace PTag { \
214  template<> \
215  struct Splices<TTAG(TypeTagName)> \
216  { \
217  typedef RevertedTuple<__VA_ARGS__>::type tuple; \
218  }; \
219  SPLICE_INFO_(TTAG(TypeTagName), __VA_ARGS__) \
220  } \
221  extern int semicolonHack_
222 
229 #define INHERITS_FROM(...) __VA_ARGS__
230 
246 #define NEW_PROP_TAG(PTagName) \
247  namespace PTag { \
248  struct PTagName; } extern int semicolonHack_
249 
251 #define SET_PROP_(EffTypeTagName, PropKind, PropTagName, ...) \
252  template <class TypeTag> \
253  struct Property<TypeTag, \
254  TTAG(EffTypeTagName), \
255  PTAG(PropTagName)>; \
256  PROP_INFO_(EffTypeTagName, \
257  /*kind=*/PropKind, \
258  PropTagName, \
259  /*value=*/__VA_ARGS__) \
260  template <class TypeTag> \
261  struct Property<TypeTag, \
262  TTAG(EffTypeTagName), \
263  PTAG(PropTagName) >
264 
296 #define SET_PROP(EffTypeTagName, PropTagName) \
297  template <class TypeTag> \
298  struct Property<TypeTag, \
299  TTAG(EffTypeTagName), \
300  PTAG(PropTagName)>; \
301  PROP_INFO_(EffTypeTagName, \
302  /*kind=*/"opaque", \
303  PropTagName, \
304  /*value=*/"<opaque>") \
305  template <class TypeTag> \
306  struct Property<TypeTag, \
307  TTAG(EffTypeTagName), \
308  PTAG(PropTagName) >
309 
324 #define UNSET_PROP(EffTypeTagName, PropTagName) \
325  template <> \
326  struct PropertyUnset<TTAG(EffTypeTagName), \
327  PTAG(PropTagName) >; \
328  PROP_INFO_(EffTypeTagName, \
329  /*kind=*/"withdraw", \
330  PropTagName, \
331  /*value=*/<none>) \
332  template <> \
333  struct PropertyUnset<TTAG(EffTypeTagName), \
334  PTAG(PropTagName) > \
335  : public PropertyExplicitlyUnset \
336  {}
337 
344 #define SET_INT_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
345  SET_PROP_(EffTypeTagName, \
346  /*kind=*/"int ", \
347  PropTagName, \
348  /*value=*/__VA_ARGS__) \
349  { \
350  typedef int type; \
351  static const int value = __VA_ARGS__; \
352  }
353 
360 #define SET_BOOL_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
361  SET_PROP_(EffTypeTagName, \
362  /*kind=*/"bool ", \
363  PropTagName, \
364  /*value=*/__VA_ARGS__) \
365  { \
366  typedef bool type; \
367  static const bool value = __VA_ARGS__; \
368  }
369 
376 #define SET_TYPE_PROP(EffTypeTagName, PropTagName, /*Value*/...) \
377  SET_PROP_(EffTypeTagName, \
378  /*kind=*/"type ", \
379  PropTagName, \
380  /*value=*/__VA_ARGS__) \
381  { \
382  typedef __VA_ARGS__ type; \
383  }
384 
393 #define SET_SCALAR_PROP(EffTypeTagName, PropTagName, ...) \
394  SET_PROP_(EffTypeTagName, \
395  /*kind=*/"scalar", \
396  PropTagName, \
397  /*value=*/__VA_ARGS__) \
398  { \
399  typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; \
400  public: \
401  typedef Scalar type; \
402  static const Scalar value; \
403  }; \
404  template <class TypeTag> \
405  const typename Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::type \
406  Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::value(__VA_ARGS__)
407 
415 #define SET_STRING_PROP(EffTypeTagName, PropTagName, ...) \
416  SET_PROP_(EffTypeTagName, \
417  /*kind=*/"string", \
418  PropTagName, \
419  /*value=*/__VA_ARGS__) \
420  { \
421  public: \
422  typedef std::string type; \
423  static const std::string value; \
424  }; \
425  template <class TypeTag> \
426  const typename Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::type \
427  Property<TypeTag, TTAG(EffTypeTagName), PTAG(PropTagName)>::value(__VA_ARGS__)
428 
435 #define SET_TAG_PROP(EffTypeTagName, PropTagName, ValueTypeTagName) \
436  SET_PROP_(EffTypeTagName, \
437  /*kind=*/"tag ", \
438  PropTagName, \
439  /*value=*/TTAG(ValueTypeTagName)) \
440  { \
441  typedef TTAG(ValueTypeTagName) type; \
442  }
443 
444 
453 #define GET_PROP(TypeTag, PropTagName) \
454  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p
455 #define GET_PROP_(TypeTag, PropTag) \
457  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p
458 
468 #define GET_PROP_VALUE(TypeTag, PropTagName) \
469  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p::value
470 #define GET_PROP_VALUE_(TypeTag, PropTag) \
472  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p::value
473 
485 #define GET_PROP_TYPE(TypeTag, PropTagName) \
486  ::Ewoms::Properties::GetProperty<TypeTag, PTAG(PropTagName)>::p::type
487 #define GET_PROP_TYPE_(TypeTag, PropTag) \
489  ::Ewoms::Properties::GetProperty<TypeTag, PropTag>::p::type
490 
492 #if !defined NO_PROPERTY_INTROSPECTION
493 
510 #define PROP_DIAGNOSTIC(TypeTag, PropTagName) \
511  ::Ewoms::Properties::getDiagnostic<TypeTag>(#PropTagName)
512 
513 #else
514 #define PROP_DIAGNOSTIC(TypeTag, PropTagName) "Property introspection disabled by macro NO_PROPERTY_INTROSPECTION."
515 #endif
516 
518 // some serious template kung fu. Don't look at it too closely, it
519 // might damage your brain!
521 
523 
524 namespace PTag {}
525 namespace TTag {}
526 
527 #if !defined NO_PROPERTY_INTROSPECTION
528 
529 namespace TTag
530 {
531 template <class EffTypeTag>
532 struct TypeTagInfo
533 {};
534 }
535 
536 namespace PTag
537 {
538 template <class EffTypeTagName>
539 struct SpliceInfo
540 {};
541 }
542 
543 template <class EffTypeTagName, class PropTagName>
544 struct PropertyInfo
545 {};
546 
547 class PropertyRegistryKey
548 {
549 public:
550  PropertyRegistryKey()
551  {}
552 
553  PropertyRegistryKey(const std::string &effTypeTagName,
554  const std::string &propertyKind,
555  const std::string &propertyName,
556  const std::string &propertyValue,
557  const std::string &fileDefined,
558  int lineDefined)
559  : effTypeTagName_(effTypeTagName)
560  , propertyKind_(propertyKind)
561  , propertyName_(propertyName)
562  , propertyValue_(propertyValue)
563  , fileDefined_(fileDefined)
564  , lineDefined_(lineDefined)
565  {
566  }
567 
568  // copy constructor
569  PropertyRegistryKey(const PropertyRegistryKey &v)
570  : effTypeTagName_(v.effTypeTagName_)
571  , propertyKind_(v.propertyKind_)
572  , propertyName_(v.propertyName_)
573  , propertyValue_(v.propertyValue_)
574  , fileDefined_(v.fileDefined_)
575  , lineDefined_(v.lineDefined_)
576  {}
577 
578  const std::string &effTypeTagName() const
579  { return effTypeTagName_; }
580  const std::string &propertyKind() const
581  { return propertyKind_; }
582  const std::string &propertyName() const
583  { return propertyName_; }
584  const std::string &propertyValue() const
585  { return propertyValue_; }
586  const std::string &fileDefined() const
587  { return fileDefined_; }
588  int lineDefined() const
589  { return lineDefined_; }
590 
591 private:
592  std::string effTypeTagName_;
593  std::string propertyKind_;
594  std::string propertyName_;
595  std::string propertyValue_;
596  std::string fileDefined_;
597  int lineDefined_;
598 };
599 
600 
601 template <class TypeTag, class PropertyTag>
602 struct GetProperty;
603 
604 class TypeTagRegistry
605 {
606 public:
607  struct SpliceRegistryEntryBase {
608  virtual ~SpliceRegistryEntryBase() {};
609  virtual std::string propertyName() const = 0;
610  };
611 
612  template <class TypeTag, class PropTag>
613  struct SpliceRegistryEntry : public SpliceRegistryEntryBase
614  {
615  virtual std::string propertyName() const
616  { return PropertyInfo<typename GetProperty<TypeTag, PropTag>::template GetEffectiveTypeTag_<TypeTag>::type, PropTag>::propertyName; }
617  };
618 
619  typedef std::list<SpliceRegistryEntryBase*> SpliceList;
620  typedef std::map<std::string, SpliceList> SpliceListMap;
621 
622  typedef std::list<std::string> ChildrenList;
623  typedef std::map<std::string, ChildrenList> ChildrenListMap;
624 
625  // end of recursion. the last argument is not a child, but 'void'
626  // which is required for the macro magic...
627  template <class TypeTag, class DummyChild>
628  static void addChildren()
629  {}
630 
631  // the last argument is not a child, but 'void' which is required
632  // for the macro magic...
633  template <class TypeTag, class Child1, class Child2, typename ... RemainingChildren>
634  static void addChildren()
635  {
636  std::string typeTagName = Opm::className<TypeTag>();
637  children_[typeTagName].push_front(Opm::className<Child1>());
638  addChildren<TypeTag, Child2, RemainingChildren...>();
639  }
640 
641  // end of recursion. the last argument is not a child, but 'void'
642  // which is required for the macro magic...
643  template <class TypeTag>
644  static void addSplices()
645  { }
646 
647  // the last argument is not a child, but 'void' which is required
648  // for the macro magic...
649  template <class TypeTag, class Splice1, typename ... RemainingSplices>
650  static void addSplices()
651  {
652  std::string typeTagName = Opm::className<TypeTag>();
653 
654  SpliceRegistryEntry<TypeTag, Splice1> *tmp = new SpliceRegistryEntry<TypeTag, Splice1>;
655 
656  splices_[typeTagName].push_front(tmp);
657  addSplices<TypeTag, RemainingSplices...>();
658  }
659 
660  static const SpliceList &splices(const std::string &typeTagName)
661  { return splices_[typeTagName]; }
662 
663  static const ChildrenList &children(const std::string &typeTagName)
664  { return children_[typeTagName]; }
665 
666 private:
667  static SpliceListMap splices_;
668  static ChildrenListMap children_;
669 };
670 
671 TypeTagRegistry::SpliceListMap TypeTagRegistry::splices_;
672 TypeTagRegistry::ChildrenListMap TypeTagRegistry::children_;
673 
674 class PropertyRegistry
675 {
676 public:
677  typedef std::map<std::string, PropertyRegistryKey> KeyList;
678  typedef std::map<std::string, KeyList> KeyListMap;
679 
680  static void addKey(const PropertyRegistryKey &key)
681  {
682  keys_[key.effTypeTagName()][key.propertyName()] = key;
683  }
684 
685  static const std::string &getSpliceTypeTagName(const std::string &typeTagName,
686  const std::string &propertyName)
687  {
688  const auto &keyIt = keys_.find(typeTagName);
689  const auto &keyEndIt = keys_.end();
690  if (keyIt == keyEndIt)
691  OPM_THROW(std::runtime_error,
692  "Unknown type tag key '" << typeTagName << "'");
693 
694  // check whether the propery is defined for the type tag
695  // currently checked
696  const auto &propIt = keyIt->second.find(propertyName);
697  const auto &propEndIt = keyIt->second.end();
698  if (propIt != propEndIt)
699  return propIt->second.propertyValue();
700 
701  // if not, check all children
702  typedef TypeTagRegistry::ChildrenList ChildrenList;
703  const ChildrenList &children = TypeTagRegistry::children(typeTagName);
704  ChildrenList::const_iterator ttagIt = children.begin();
705  for (; ttagIt != children.end(); ++ttagIt) {
706  const auto &tmp = getSpliceTypeTagName(*ttagIt, propertyName);
707  if (tmp != "")
708  return tmp;
709  }
710 
711  // if the property was not defined on a given type tag, return
712  // the empty string.
713  static std::string tmp("");
714  return tmp;
715  }
716 
717  static const PropertyRegistryKey &getKey(const std::string &effTypeTagName,
718  const std::string &propertyName)
719  {
720  return keys_[effTypeTagName][propertyName];
721  }
722 
723  static const KeyList &getKeys(const std::string &effTypeTagName)
724  {
725  return keys_[effTypeTagName];
726  }
727 
728 private:
729  static KeyListMap keys_;
730 };
731 PropertyRegistry::KeyListMap PropertyRegistry::keys_;
732 
733 #endif // !defined NO_PROPERTY_INTROSPECTION
734 
735 struct PropertyUndefined { };
736 class PropertyExplicitlyUnset {};
737 
738 template <class RealTypeTag,
739  class EffectiveTypeTag,
740  class PropertyTag>
741 struct Property : public PropertyUndefined
742 {};
743 
744 template <class EffectiveTypeTag,
745  class PropertyTag>
746 struct PropertyUnset : public PropertyUndefined
747 {};
748 
749 template <class Tree, class PropertyTag>
750 struct propertyExplicitlyUnset
751 {
752  const static bool value =
753  std::is_base_of<PropertyExplicitlyUnset,
754  PropertyUnset<typename Tree::SelfType,
755  PropertyTag>
756  >::value;
757 };
758 
759 template <class Tree, class PropertyTag>
760 class propertyExplicitlyUnsetOnTree
761 {
762  static const bool explicitlyUnset = propertyExplicitlyUnset<Tree, PropertyTag>::value;
763 
764  template <class ChildTuple>
765  struct unsetOnAllChildren
766  { static const bool value = true; };
767 
768  template <class Child, class ... RemainingChildren>
769  struct unsetOnAllChildren<std::tuple<Child, RemainingChildren...> >
770  { static const bool value =
771  propertyExplicitlyUnsetOnTree<Child, PropertyTag>::value
772  && unsetOnAllChildren<std::tuple<RemainingChildren...> >::value; };
773 
774 public:
775  static const bool value =
776  (explicitlyUnset || (!Tree::isLeaf && unsetOnAllChildren<typename Tree::ChildrenTuple>::value));
777 };
778 
779 template <class PropertyTag>
780 struct propertyExplicitlyUnsetOnTree<void, PropertyTag>
781 {
782  const static bool value = std::true_type::value;
783 };
784 
785 template <class RealTypeTag, class Tree, class PropertyTag>
786 struct propertyDefinedOnSelf
787 {
788  const static bool value =
789  ! std::is_base_of<PropertyUndefined,
790  Property<RealTypeTag,
791  typename Tree::SelfType,
792  PropertyTag> >::value;
793 };
794 
795 // template class to revert the order or a std::tuple's
796 // arguments. This is required to make the properties of children
797 // defined on the right overwrite the properties of the previous
798 // children. See https://sydius.me/2011/07/reverse-tuple-in-c/
799 template<typename... Args>
800 class RevertedTuple
801 {
802 private:
803  template<unsigned int N, typename... All>
804  struct RevertedTupleOuter
805  {
806  template<typename Head, typename... Tail>
807  struct RevertedTupleInner: RevertedTupleOuter<N-1, Head, All...>::template RevertedTupleInner<Tail...> { };
808  };
809 
810  template<typename... All>
811  struct RevertedTupleOuter<0, All...>
812  {
813  template<typename... Tail>
814  struct RevertedTupleInner {
815  typedef std::tuple<All...> type;
816  };
817  };
818 
819 public:
820  typedef typename RevertedTupleOuter<sizeof...(Args)>::template RevertedTupleInner<Args...>::type type;
821 };
822 
823 template <class SelfT,
824  typename ... Children>
825 class TypeTag
826 {
827 public:
828  typedef SelfT SelfType;
829 
830  typedef typename RevertedTuple<Children...>::type ChildrenTuple;
831  static const bool isLeaf = std::is_same<ChildrenTuple, std::tuple<> >::value;
832 };
833 
834 namespace PTag {
835 // this class needs to be located in the PTag namespace for reasons
836 // you don't really want to know...
837 template <class TypeTag>
838 struct Splices
839 {
840  typedef typename std::tuple<> tuple;
841 };
842 } // namespace PTag
843 
844 template <class TypeTag, class PropertyTag>
845 struct GetProperty
846 {
847  // find the type tag for which the property is defined
848  template <class CurTree, bool directlyDefined =
849  propertyDefinedOnSelf<TypeTag,
850  CurTree,
851  PropertyTag>::value>
852  struct GetEffectiveTypeTag_
853  { typedef typename CurTree::SelfType type; };
854 
855  template <class ...Elements>
856  struct SearchTypeTagList_;
857 
858  template <class EffectiveTypeTag, class ...Elements>
859  struct SearchTypeTagList_FirstThenRemaining_;
860 
861  template <class ...SpliceList>
862  struct SearchSpliceList_;
863 
864  template <class EffectiveTypeTag, class ...Splices>
865  struct SearchSpliceList_FirstThenRemaining_;
866 
867  // find the first type tag in a tuple for which the property is
868  // defined
869  template <class TypeTagTuple>
870  struct SearchTypeTagTuple_
871  { typedef void type; };
872 
873  template <class ...TypeTagList>
874  struct SearchTypeTagTuple_<std::tuple<TypeTagList...> >
875  { typedef typename SearchTypeTagList_<TypeTagList...>::type type; };
876 
877  template <class ...Elements>
878  struct SearchTypeTagList_
879  { typedef void type; };
880 
881  template <class FirstElement, class ...RemainingElements>
882  struct SearchTypeTagList_<FirstElement, RemainingElements...>
883  {
884  typedef typename SearchTypeTagList_FirstThenRemaining_<
885  typename GetEffectiveTypeTag_<FirstElement>::type,
886  RemainingElements...>::type type;
887  };
888 
889  template <class EffectiveTypeTag, class ...Elements>
890  struct SearchTypeTagList_FirstThenRemaining_
891  { typedef EffectiveTypeTag type; };
892 
893  template <class ...RemainingElements>
894  struct SearchTypeTagList_FirstThenRemaining_<void, RemainingElements...>
895  { typedef typename SearchTypeTagList_<RemainingElements...>::type type; };
896 
897  // find the first type tag in a tuple of splices for which the
898  // property is defined
899  template <class SpliceTuple>
900  struct SearchSpliceTuple_
901  { typedef void type; };
902 
903  template <class ...SpliceList>
904  struct SearchSpliceTuple_<std::tuple<SpliceList...> >
905  { typedef typename SearchSpliceList_<SpliceList...>::type type; };
906 
907  template <class ...SpliceList>
908  struct SearchSpliceList_
909  { typedef void type; };
910 
911  template <class FirstSplice, class ...RemainingSplices>
912  struct SearchSpliceList_<FirstSplice, RemainingSplices...>
913  {
914  typedef typename SearchSpliceList_FirstThenRemaining_<
915  typename GetEffectiveTypeTag_<typename GetProperty<TypeTag, FirstSplice>::p::type>::type,
916  RemainingSplices...>::type type;
917  };
918 
919  template <class EffectiveTypeTag, class ...Splices>
920  struct SearchSpliceList_FirstThenRemaining_
921  { typedef EffectiveTypeTag type; };
922 
923  template <class ...RemainingSplices>
924  struct SearchSpliceList_FirstThenRemaining_<void, RemainingSplices...>
925  { typedef typename SearchSpliceList_<RemainingSplices...>::type type; };
926 
927  // find the splice or the child type tag for which the property is defined
928  template <class CurTree,
929  class SpliceTypeTag = typename SearchSpliceTuple_< typename PTag::Splices<CurTree>::tuple >::type >
930  struct SearchSplicesThenChildren_
931  { typedef SpliceTypeTag type; };
932 
933  template <class CurTree>
934  struct SearchSplicesThenChildren_<CurTree, void>
935  { typedef typename SearchTypeTagTuple_<typename CurTree::ChildrenTuple>::type type; };
936 
937  template <class CurTree>
938  struct GetEffectiveTypeTag_<CurTree, /*directlyDefined = */false>
939  { typedef typename SearchSplicesThenChildren_<CurTree>::type type; };
940 
941 public:
942  typedef Property<TypeTag, typename GetEffectiveTypeTag_<TypeTag>::type, PropertyTag> p;
943 };
944 
945 #if !defined NO_PROPERTY_INTROSPECTION
946 int myReplaceAll_(std::string &s,
947  const std::string &pattern,
948  const std::string &replacement)
949 {
950  size_t pos;
951  int i = 0;
952  while ( (pos = s.find(pattern)) != s.npos) {
953  s.replace(pos, pattern.size(), replacement);
954  ++i;
955  };
956  return i;
957 }
958 
959 std::string canonicalTypeTagNameToName_(const std::string &canonicalName)
960 {
961  std::string result(canonicalName);
962  myReplaceAll_(result, "Ewoms::Properties::TTag::", "TTAG(");
963  myReplaceAll_(result, "::", "");
964  result += ")";
965  return result;
966 }
967 
968 inline bool getDiagnostic_(const std::string &typeTagName,
969  const std::string &propTagName,
970  std::string &result,
971  const std::string indent)
972 {
973  const PropertyRegistryKey *key = 0;
974 
975  const PropertyRegistry::KeyList &keys =
976  PropertyRegistry::getKeys(typeTagName);
977  PropertyRegistry::KeyList::const_iterator it = keys.begin();
978  for (; it != keys.end(); ++it) {
979  if (it->second.propertyName() == propTagName) {
980  key = &it->second;
981  break;
982  };
983  }
984 
985  if (key) {
986  std::ostringstream oss;
987  oss << indent
988  << key->propertyKind() << " "
989  << key->propertyName() << " defined on '"
990  << canonicalTypeTagNameToName_(key->effTypeTagName()) << "' at "
991  << key->fileDefined() << ":" << key->lineDefined() << "\n";
992  result = oss.str();
993  return true;
994  }
995 
996  // print properties defined on children
997  typedef TypeTagRegistry::ChildrenList ChildrenList;
998  const ChildrenList &children = TypeTagRegistry::children(typeTagName);
999  ChildrenList::const_iterator ttagIt = children.begin();
1000  std::string newIndent = indent + " ";
1001  for (; ttagIt != children.end(); ++ttagIt) {
1002  if (getDiagnostic_(*ttagIt, propTagName, result, newIndent)) {
1003  result.insert(0, indent + "Inherited from " + canonicalTypeTagNameToName_(typeTagName) + "\n");
1004  return true;
1005  }
1006  }
1007 
1008  return false;
1009 }
1010 
1011 template <class TypeTag>
1012 const std::string getDiagnostic(std::string propTagName)
1013 {
1014  std::string result;
1015 
1016  std::string TypeTagName(Opm::className<TypeTag>());
1017 
1018  propTagName.replace(0, strlen("PTag("), "");
1019  int n = propTagName.length();
1020  propTagName.replace(n - 1, 1, "");
1021  //TypeTagName.replace(0, strlen("Ewoms::Properties::TTag::"), "");
1022 
1023  return result;
1024 }
1025 
1026 inline void print_(const std::string &rootTypeTagName,
1027  const std::string &curTypeTagName,
1028  const std::string &splicePropName,
1029  std::ostream &os,
1030  const std::string indent,
1031  std::set<std::string> &printedProperties)
1032 {
1033  if (indent == "") {
1034  os << indent << "###########\n";
1035  os << indent << "# Properties\n";
1036  os << indent << "###########\n";
1037  os << indent << "Properties for " << canonicalTypeTagNameToName_(curTypeTagName) << ":";
1038  }
1039  else if (splicePropName != "")
1040  os << indent << "Inherited from splice " << splicePropName << " (set to " << canonicalTypeTagNameToName_(curTypeTagName) << "):";
1041  else
1042  os << indent << "Inherited from " << canonicalTypeTagNameToName_(curTypeTagName) << ":";
1043  const PropertyRegistry::KeyList &keys =
1044  PropertyRegistry::getKeys(curTypeTagName);
1045  PropertyRegistry::KeyList::const_iterator it = keys.begin();
1046  bool somethingPrinted = false;
1047  for (; it != keys.end(); ++it) {
1048  const PropertyRegistryKey &key = it->second;
1049  if (printedProperties.count(key.propertyName()) > 0)
1050  continue; // property already printed
1051  if (!somethingPrinted) {
1052  os << "\n";
1053  somethingPrinted = true;
1054  }
1055  os << indent << " "
1056  << key.propertyKind() << " " << key.propertyName();
1057  if (key.propertyKind() != "opaque") {
1058  std::string s(key.propertyValue());
1059  myReplaceAll_(s, "typename ", "");
1060  if (myReplaceAll_(s, "::Ewoms::Properties::TTag::", "TTAG("))
1061  s += ')';
1062  myReplaceAll_(s, "::Ewoms::Properties::PTag::", "");
1063  myReplaceAll_(s, "::Ewoms::Properties::GetProperty<", "GET_PROP(");
1064  myReplaceAll_(s, ">::p::", ")::");
1065  myReplaceAll_(s, "GET_PROP(TypeTag, Scalar)::type", "Scalar");
1066 
1067  os << " = '" << s << "'";
1068  }
1069  os << " defined at " << key.fileDefined()
1070  << ":" << key.lineDefined()
1071  << "\n";
1072  printedProperties.insert(key.propertyName());
1073  };
1074  if (!somethingPrinted)
1075  os << " (none)\n";
1076  // print properties defined on splices or children
1077  std::string newIndent = indent + " ";
1078 
1079  // first, iterate over the splices, ...
1080  typedef TypeTagRegistry::SpliceList SpliceList;
1081  const SpliceList &splices = TypeTagRegistry::splices(curTypeTagName);
1082  SpliceList::const_iterator spliceIt = splices.begin();
1083  for (; spliceIt != splices.end(); ++ spliceIt) {
1084  const auto &spliceTypeTagName = PropertyRegistry::getSpliceTypeTagName(rootTypeTagName,
1085  (*spliceIt)->propertyName());
1086  print_(rootTypeTagName, spliceTypeTagName, (*spliceIt)->propertyName(), os, newIndent, printedProperties);
1087  }
1088 
1089  // ... then, over the children
1090  typedef TypeTagRegistry::ChildrenList ChildrenList;
1091  const ChildrenList &children = TypeTagRegistry::children(curTypeTagName);
1092  ChildrenList::const_iterator ttagIt = children.begin();
1093  for (; ttagIt != children.end(); ++ttagIt) {
1094  print_(rootTypeTagName, *ttagIt, /*splicePropName=*/"", os, newIndent, printedProperties);
1095  }
1096 }
1097 
1098 template <class TypeTag>
1099 void printValues(std::ostream &os = std::cout)
1100 {
1101  std::set<std::string> printedProps;
1102  print_(Opm::className<TypeTag>(), Opm::className<TypeTag>(), /*splicePropertyName=*/"", os, /*indent=*/"", printedProps);
1103 }
1104 #else // !defined NO_PROPERTY_INTROSPECTION
1105 template <class TypeTag>
1106 void printValues(std::ostream &os = std::cout)
1107 {
1108  std::cout <<
1109  "The eWoms property system was compiled with the macro\n"
1110  "NO_PROPERTY_INTROSPECTION defined.\n"
1111  "No diagnostic messages this time, sorry.\n";
1112 }
1113 
1114 template <class TypeTag>
1115 const std::string getDiagnostic(std::string propTagName)
1116 {
1117  std::string result;
1118  result =
1119  "The eWoms property system was compiled with the macro\n"
1120  "NO_PROPERTY_INTROSPECTION defined.\n"
1121  "No diagnostic messages this time, sorry.\n";
1122  return result;
1123 }
1124 
1125 #endif // !defined NO_PROPERTY_INTROSPECTION
1126 
1128 
1129 } // namespace Properties
1130 } // namespace Ewoms
1131 
1132 #endif
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:543
STL namespace.
Definition: baseauxiliarymodule.hh:35