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) : data_(data) {}
87  const std::type_info& type() const { return typeid(T); }
88  std::string typeName() const { return Teuchos::TypeNameTraits<T>::name(); }
89  T data_;
90  };
91 
92  template<typename T>
93  struct Getter {
94  static T& get(DataBase* data_, DataBase*& /* datah_ */) {
95  if ((data_ == NULL) || (data_->type() != typeid(T))) // NVR added guard to avoid determining typeName unless we will use it
96  {
97  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
99  "Error, cast to type Data<" << typeName << "> failed since the content is NULL");
100 
102  "Error, cast to type Data<" << typeName << "> failed since the actual underlying type is "
103  "\'" << data_->typeName() << "!");
104  }
105 
106  Data<T>* data = dynamic_cast<Data<T>*>(data_);
107  if (!data) // NVR added guard to avoid determining typeName unless we will use it
108  {
109  const std::string typeName = Teuchos::TypeNameTraits<T>::name(); // calls Teuchos::demangleName(), which can be expensive
110  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
111  "Error, cast to type Data<" << typeName << "> failed but should not have and the actual underlying type is "
112  "\'" << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
113  }
114  return data->data_;
115  }
116  };
117 
118 
119  public:
120  typedef std::map<const FactoryBase*,int> request_container;
121 
122  private:
124  mutable
126  bool available_;
129  int count_;
130 
132 
133  public:
135 
136 
138  VariableContainer() : data_(NULL), datah_(NULL), available_(false), keep_(false), count_(0) { }
140  delete data_; data_ = NULL;
141  delete datah_; datah_ = NULL;
142  }
143 
145 
147 
148 
150  template<typename T>
151  void SetData(const T& entry) {
152  delete data_;
153  delete datah_;
154  data_ = new Data<T>(entry);
155  datah_ = NULL;
156  available_ = true;
157  }
158 
161  template<typename T>
162  const T& GetData() const {
163  return Getter<T>::get(data_, datah_);
164  }
165 
168  template<typename T>
169  T& GetData() {
170  return Getter<T>::get(data_, datah_);
171  }
172 
173  std::string GetTypeName() {
174  if (data_ == NULL)
175  return std::string("");
176  return data_->typeName();
177  }
178 
180  // if SetData has been called before
181  bool IsAvailable() const { return available_; }
182 
184 
186 
187 
189  void Request(const FactoryBase* reqFactory) {
190  request_container::iterator it = requests_.find(reqFactory);
191  if (it == requests_.end())
192  requests_[reqFactory] = 1;
193  else
194  (it->second)++;
195  count_++; // increment request counter
196  }
197 
199  void Release(const FactoryBase* reqFactory) {
200  request_container::iterator it = requests_.find(reqFactory);
201  TEUCHOS_TEST_FOR_EXCEPTION(it == requests_.end(), Exceptions::RuntimeError, "MueLu::VariableContainer::Release(): "
202  "cannot call Release if factory has not been requested before by factory " << reqFactory);
203  if (--(it->second) == 0)
204  requests_.erase(it);
205  count_--;
206  }
207 
209  int NumRequests(const FactoryBase* reqFactory) const {
210  request_container::const_iterator it = requests_.find(reqFactory);
211  return (it != requests_.end()) ? it->second : 0;
212  }
213 
215  int NumAllRequests() const { return count_; }
216 
218  bool IsRequested(const FactoryBase* reqFactory) const { return (NumRequests(reqFactory) > 0); }
219 
221  bool IsRequested() const { return (count_ > 0); }
222 
223  const request_container& Requests() const { return requests_; }
225 
227 
228 
230  bool IsKept(KeepType keep) const { return keep_ & keep; }
231 
233  void AddKeepFlag(KeepType keep = UserData) { keep_ |= keep; }
234 
236  void RemoveKeepFlag(KeepType keep = UserData) { keep_ = keep_ & (keep_ ^ keep); }
237 
239  KeepType GetKeepFlag() const { return keep_; }
240 
242  };
243 
244 
245  template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
246  struct VariableContainer::Getter<Teuchos::RCP<Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > > {
249 
251  typedef Teuchos::RCP<Operator> TO;
252  typedef Teuchos::RCP<Matrix> TM;
253 
254  if (data_ == NULL) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
255  {
257  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed since the content is NULL");
258  }
259  if (data_->type() == typeid(TO)) {
260  Data<TO>* data = dynamic_cast<Data<TO>*>(data_);
261  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
262  {
263  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
264  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TO>::name() << "> failed but should not have and the actual underlying type is "
265  "\'" << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
266  }
267  return data->data_;
268  }
269 
270  if (data_->type() != typeid(TM)) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
271  {
273  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed since the actual underlying type is "
274  "\'" << data_->typeName() << "!");
275  }
276  Data<TM>* data = dynamic_cast<Data<TM>*>(data_);
277  if (!data) // NVR added guard to avoid unnecessary call to TypeNameTraits<TO>::name(), which calls Teuchos::demangleName(), which can be expensive
278  {
279  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
280  "Error, cast to type Data<" << Teuchos::TypeNameTraits<TM>::name() << "> failed but should not have and the actual underlying type is "
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  "\'" << datah_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
292  }
293  return datah->data_;
294  }
295  };
296 
297 }
298 
299 #endif /* MUELU_VARIABLECONTAINER_HPP */
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.
const std::type_info & type() const
bool available_
is data available?
std::map< const FactoryBase *, int > request_container
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)