MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_VariableContainer.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_VARIABLECONTAINER_HPP
11 #define MUELU_VARIABLECONTAINER_HPP
12 
13 #include <map>
14 
16 
17 #include <Xpetra_Matrix.hpp>
18 #include <Xpetra_Operator.hpp>
19 
20 #include "MueLu_ConfigDefs.hpp"
21 #include "MueLu_BaseClass.hpp"
22 
23 #include "MueLu_Exceptions.hpp"
25 #include "MueLu_KeepType.hpp"
26 
27 namespace MueLu {
28 
37 class VariableContainer : public BaseClass {
38  private:
39  // Motivated by Teuchos_any.hpp
40  class DataBase {
41  public:
42  virtual ~DataBase() = default;
43  virtual const std::type_info& type() const = 0;
44  virtual std::string typeName() const = 0;
45  };
46 
47  template <typename T>
48  class Data : public DataBase {
49  public:
50  Data(const T& data)
51  : data_(data) {}
52  const std::type_info& type() const { return typeid(T); }
53  std::string typeName() const { return Teuchos::TypeNameTraits<T>::name(); }
54  T data_;
55  };
56 
57  template <typename T>
58  struct Getter {
59  static T& get(DataBase* data_, DataBase*& /* datah_ */) {
60  if ((data_ == NULL) || (data_->type() != typeid(T))) // NVR added guard to avoid determining typeName unless we will use it
61  {
62  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
64  "Error, cast to type Data<" << typeName << "> failed since the content is NULL");
65 
67  "Error, cast to type Data<" << typeName << "> failed since the actual underlying type is "
68  "\'"
69  << data_->typeName() << "!");
70  }
71 
72  Data<T>* data = dynamic_cast<Data<T>*>(data_);
73  if (!data) // NVR added guard to avoid determining typeName unless we will use it
74  {
75  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
76  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
77  "Error, cast to type Data<" << typeName << "> failed but should not have and the actual underlying type is "
78  "\'"
79  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
80  }
81  return data->data_;
82  }
83  };
84 
85  template <typename T>
86  struct Checker {
87  static bool check(DataBase* data_, DataBase*& /* datah_ */) {
88  if ((data_ == NULL) || (data_->type() != typeid(T))) // NVR added guard to avoid determining typeName unless we will use it
89  {
90  return false;
91  }
92 
93  Data<T>* data = dynamic_cast<Data<T>*>(data_);
94  if (!data) // NVR added guard to avoid determining typeName unless we will use it
95  {
96  return false;
97  }
98  return true;
99  }
100  };
101 
102  public:
103  typedef std::map<const FactoryBase*, int> request_container;
104 
105  private:
107  mutable DataBase* datah_;
108  bool available_;
111  int count_;
112 
114 
115  public:
117 
118 
121  : data_(NULL)
122  , datah_(NULL)
123  , available_(false)
124  , keep_(false)
125  , count_(0) {}
127  delete data_;
128  data_ = NULL;
129  delete datah_;
130  datah_ = NULL;
131  }
132 
134 
136 
137 
139  template <typename T>
140  void SetData(const T& entry) {
141  delete data_;
142  delete datah_;
143  data_ = new Data<T>(entry);
144  datah_ = NULL;
145  available_ = true;
146  }
147 
150  template <typename T>
151  const T& GetData() const {
152  return Getter<T>::get(data_, datah_);
153  }
154 
157  template <typename T>
158  T& GetData() {
159  return Getter<T>::get(data_, datah_);
160  }
161 
164  template <typename T>
165  bool CheckType() {
166  return Checker<T>::check(data_, datah_);
167  }
168 
169  std::string GetTypeName() {
170  if (data_ == NULL)
171  return std::string("");
172  return data_->typeName();
173  }
174 
176  // if SetData has been called before
177  bool IsAvailable() const { return available_; }
178 
180 
182 
183 
185  void Request(const FactoryBase* reqFactory) {
186  request_container::iterator it = requests_.find(reqFactory);
187  if (it == requests_.end())
188  requests_[reqFactory] = 1;
189  else
190  (it->second)++;
191  count_++; // increment request counter
192  }
193 
195  void Release(const FactoryBase* reqFactory) {
196  request_container::iterator it = requests_.find(reqFactory);
198  "MueLu::VariableContainer::Release(): "
199  "cannot call Release if factory has not been requested before by factory "
200  << reqFactory);
201  if (--(it->second) == 0)
202  requests_.erase(it);
203  count_--;
204  }
205 
207  int NumRequests(const FactoryBase* reqFactory) const {
208  request_container::const_iterator it = requests_.find(reqFactory);
209  return (it != requests_.end()) ? it->second : 0;
210  }
211 
213  int NumAllRequests() const { return count_; }
214 
216  bool IsRequested(const FactoryBase* reqFactory) const { return (NumRequests(reqFactory) > 0); }
217 
219  bool IsRequested() const { return (count_ > 0); }
220 
221  const request_container& Requests() const { return requests_; }
223 
225 
226 
228  bool IsKept(KeepType keep) const { return keep_ & keep; }
229 
231  void AddKeepFlag(KeepType keep = UserData) { keep_ |= keep; }
232 
234  void RemoveKeepFlag(KeepType keep = UserData) { keep_ = keep_ & (keep_ ^ keep); }
235 
237  KeepType GetKeepFlag() const { return keep_; }
238 
240 };
241 
242 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
243 struct VariableContainer::Getter<Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > > {
246 
248  typedef Teuchos::RCP<Operator> TO;
249  typedef Teuchos::RCP<Matrix> TM;
250 
251  if (data_ == NULL) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
252  {
254  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed since the content is NULL");
255  }
256  if (data_->type() == typeid(TO)) {
257  Data<TO>* data = dynamic_cast<Data<TO>*>(data_);
258  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
259  {
260  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
261  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed but should not have and the actual underlying type is "
262  "\'"
263  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
264  }
265  return data->data_;
266  }
267 
268  if (data_->type() != typeid(TM)) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
269  {
271  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed since the actual underlying type is "
272  "\'"
273  << data_->typeName() << "!");
274  }
275  Data<TM>* data = dynamic_cast<Data<TM>*>(data_);
276  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
277  {
278  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
279  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed but should not have and the actual underlying type is "
280  "\'"
281  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
282  }
283  if (datah_ == NULL)
284  datah_ = new Data<TO>(Teuchos::rcp_dynamic_cast<Operator>(data->data_));
285  Data<TO>* datah = dynamic_cast<Data<TO>*>(datah_);
286 
287  if (!datah) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
288  {
289  TEUCHOS_TEST_FOR_EXCEPTION(!datah, std::logic_error,
290  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed but should not have and the actual underlying type is "
291  "\'"
292  << datah_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
293  }
294  return datah->data_;
295  }
296 };
297 
298 } // namespace MueLu
299 
300 #endif /* MUELU_VARIABLECONTAINER_HPP */
std::map< const FactoryBase *, int > request_container
bool IsAvailable() const
Returns true if data is available, i.e.
const request_container & Requests() const
virtual std::string typeName() const =0
VariableContainer()
Default constructor.
int NumRequests(const FactoryBase *reqFactory) const
Return the number of times the data has been requested by a specific factory.
void AddKeepFlag(KeepType keep=UserData)
Adds a keep flag to the flag combination.
static T & get(DataBase *data_, DataBase *&)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
short KeepType
KeepType GetKeepFlag() const
Returns the keep flag combination.
void SetData(const T &entry)
Store data in container class and set the &quot;Available&quot; status true.
User data are always kept. This flag is set automatically when Level::Set(&quot;data&quot;, data) is used...
bool IsRequested() const
Returns true, if data is requested by at least one factory.
void RemoveKeepFlag(KeepType keep=UserData)
Removes a keep flag to the flag combination.
int count_
number of requests by all factories
void Request(const FactoryBase *reqFactory)
Request data.
static bool check(DataBase *data_, DataBase *&)
const std::type_info & type() const
bool available_
is data available?
Base class for factories (e.g., R, P, and A_coarse).
request_container requests_
requesting factories
bool IsKept(KeepType keep) const
Returns true if at least one keep flag is set.
void Release(const FactoryBase *reqFactory)
Release data.
Base class for MueLu classes.
virtual const std::type_info & type() const =0
DataBase * data_
the data itself
Exception throws to report errors in the internal logical of the program.
Class that stores all relevant data for a variable.
int NumAllRequests() const
Returns the number of times the data has been requested.
bool IsRequested(const FactoryBase *reqFactory) const
Returns true, if data is requested by reqFactory.
static std::string name()
std::string typeName(const T &t)