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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_VARIABLECONTAINER_HPP
47 #define MUELU_VARIABLECONTAINER_HPP
48 
49 #include <map>
50 
52 
53 #include <Xpetra_Matrix.hpp>
54 #include <Xpetra_Operator.hpp>
55 
56 #include "MueLu_ConfigDefs.hpp"
57 #include "MueLu_BaseClass.hpp"
58 
59 #include "MueLu_Exceptions.hpp"
61 #include "MueLu_KeepType.hpp"
62 
63 namespace MueLu {
64 
73 class VariableContainer : public BaseClass {
74  private:
75  // Motivated by Teuchos_any.hpp
76  class DataBase {
77  public:
78  virtual ~DataBase() {}
79  virtual const std::type_info& type() const = 0;
80  virtual std::string typeName() const = 0;
81  };
82 
83  template <typename T>
84  class Data : public DataBase {
85  public:
86  Data(const T& data)
87  : data_(data) {}
88  const std::type_info& type() const { return typeid(T); }
89  std::string typeName() const { return Teuchos::TypeNameTraits<T>::name(); }
90  T data_;
91  };
92 
93  template <typename T>
94  struct Getter {
95  static T& get(DataBase* data_, DataBase*& /* datah_ */) {
96  if ((data_ == NULL) || (data_->type() != typeid(T))) // NVR added guard to avoid determining typeName unless we will use it
97  {
98  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
100  "Error, cast to type Data<" << typeName << "> failed since the content is NULL");
101 
103  "Error, cast to type Data<" << typeName << "> failed since the actual underlying type is "
104  "\'"
105  << data_->typeName() << "!");
106  }
107 
108  Data<T>* data = dynamic_cast<Data<T>*>(data_);
109  if (!data) // NVR added guard to avoid determining typeName unless we will use it
110  {
111  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
112  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
113  "Error, cast to type Data<" << typeName << "> failed but should not have and the actual underlying type is "
114  "\'"
115  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
116  }
117  return data->data_;
118  }
119  };
120 
121  template <typename T>
122  struct Checker {
123  static bool check(DataBase* data_, DataBase*& /* datah_ */) {
124  if ((data_ == NULL) || (data_->type() != typeid(T))) // NVR added guard to avoid determining typeName unless we will use it
125  {
126  return false;
127  }
128 
129  Data<T>* data = dynamic_cast<Data<T>*>(data_);
130  if (!data) // NVR added guard to avoid determining typeName unless we will use it
131  {
132  return false;
133  }
134  return true;
135  }
136  };
137 
138  public:
139  typedef std::map<const FactoryBase*, int> request_container;
140 
141  private:
143  mutable DataBase* datah_;
144  bool available_;
147  int count_;
148 
150 
151  public:
153 
154 
157  : data_(NULL)
158  , datah_(NULL)
159  , available_(false)
160  , keep_(false)
161  , count_(0) {}
163  delete data_;
164  data_ = NULL;
165  delete datah_;
166  datah_ = NULL;
167  }
168 
170 
172 
173 
175  template <typename T>
176  void SetData(const T& entry) {
177  delete data_;
178  delete datah_;
179  data_ = new Data<T>(entry);
180  datah_ = NULL;
181  available_ = true;
182  }
183 
186  template <typename T>
187  const T& GetData() const {
188  return Getter<T>::get(data_, datah_);
189  }
190 
193  template <typename T>
194  T& GetData() {
195  return Getter<T>::get(data_, datah_);
196  }
197 
200  template <typename T>
201  bool CheckType() {
202  return Checker<T>::check(data_, datah_);
203  }
204 
205  std::string GetTypeName() {
206  if (data_ == NULL)
207  return std::string("");
208  return data_->typeName();
209  }
210 
212  // if SetData has been called before
213  bool IsAvailable() const { return available_; }
214 
216 
218 
219 
221  void Request(const FactoryBase* reqFactory) {
222  request_container::iterator it = requests_.find(reqFactory);
223  if (it == requests_.end())
224  requests_[reqFactory] = 1;
225  else
226  (it->second)++;
227  count_++; // increment request counter
228  }
229 
231  void Release(const FactoryBase* reqFactory) {
232  request_container::iterator it = requests_.find(reqFactory);
234  "MueLu::VariableContainer::Release(): "
235  "cannot call Release if factory has not been requested before by factory "
236  << reqFactory);
237  if (--(it->second) == 0)
238  requests_.erase(it);
239  count_--;
240  }
241 
243  int NumRequests(const FactoryBase* reqFactory) const {
244  request_container::const_iterator it = requests_.find(reqFactory);
245  return (it != requests_.end()) ? it->second : 0;
246  }
247 
249  int NumAllRequests() const { return count_; }
250 
252  bool IsRequested(const FactoryBase* reqFactory) const { return (NumRequests(reqFactory) > 0); }
253 
255  bool IsRequested() const { return (count_ > 0); }
256 
257  const request_container& Requests() const { return requests_; }
259 
261 
262 
264  bool IsKept(KeepType keep) const { return keep_ & keep; }
265 
267  void AddKeepFlag(KeepType keep = UserData) { keep_ |= keep; }
268 
270  void RemoveKeepFlag(KeepType keep = UserData) { keep_ = keep_ & (keep_ ^ keep); }
271 
273  KeepType GetKeepFlag() const { return keep_; }
274 
276 };
277 
278 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
279 struct VariableContainer::Getter<Teuchos::RCP<Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> > > {
282 
284  typedef Teuchos::RCP<Operator> TO;
285  typedef Teuchos::RCP<Matrix> TM;
286 
287  if (data_ == NULL) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
288  {
290  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed since the content is NULL");
291  }
292  if (data_->type() == typeid(TO)) {
293  Data<TO>* data = dynamic_cast<Data<TO>*>(data_);
294  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
295  {
296  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
297  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed but should not have and the actual underlying type is "
298  "\'"
299  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
300  }
301  return data->data_;
302  }
303 
304  if (data_->type() != typeid(TM)) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
305  {
307  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed since the actual underlying type is "
308  "\'"
309  << data_->typeName() << "!");
310  }
311  Data<TM>* data = dynamic_cast<Data<TM>*>(data_);
312  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
313  {
314  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
315  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed but should not have and the actual underlying type is "
316  "\'"
317  << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
318  }
319  if (datah_ == NULL)
320  datah_ = new Data<TO>(Teuchos::rcp_dynamic_cast<Operator>(data->data_));
321  Data<TO>* datah = dynamic_cast<Data<TO>*>(datah_);
322 
323  if (!datah) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
324  {
325  TEUCHOS_TEST_FOR_EXCEPTION(!datah, std::logic_error,
326  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed but should not have and the actual underlying type is "
327  "\'"
328  << datah_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
329  }
330  return datah->data_;
331  }
332 };
333 
334 } // namespace MueLu
335 
336 #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)