MueLu  Version of the Day
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 
51 #include <Teuchos_TypeNameTraits.hpp>
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  const std::string typeName = Teuchos::TypeNameTraits<T>::name();
96  TEUCHOS_TEST_FOR_EXCEPTION(data_ == NULL, Teuchos::bad_any_cast,
97  "Error, cast to type Data<" << typeName << "> failed since the content is NULL");
98  TEUCHOS_TEST_FOR_EXCEPTION(data_->type() != typeid(T), Teuchos::bad_any_cast,
99  "Error, cast to type Data<" << typeName << "> failed since the actual underlying type is "
100  "\'" << data_->typeName() << "!");
101 
102  Data<T>* data = dynamic_cast<Data<T>*>(data_);
103  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
104  "Error, cast to type Data<" << typeName << "> failed but should not have and the actual underlying type is "
105  "\'" << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
106  return data->data_;
107  }
108  };
109 
110 
111  public:
112  typedef std::map<const FactoryBase*,int> request_container;
113 
114  private:
116  mutable
118  bool available_;
121  int count_;
122 
124 
125  public:
127 
128 
130  VariableContainer() : data_(NULL), datah_(NULL), available_(false), keep_(false), count_(0) { }
132  delete data_; data_ = NULL;
133  delete datah_; datah_ = NULL;
134  }
135 
137 
139 
140 
142  template<typename T>
143  void SetData(const T& entry) {
144  delete data_;
145  delete datah_;
146  data_ = new Data<T>(entry);
147  datah_ = NULL;
148  available_ = true;
149  }
150 
153  template<typename T>
154  const T& GetData() const {
155  return Getter<T>::get(data_, datah_);
156  }
157 
160  template<typename T>
161  T& GetData() {
162  return Getter<T>::get(data_, datah_);
163  }
164 
165  std::string GetTypeName() {
166  if (data_ == NULL)
167  return std::string("");
168  return data_->typeName();
169  }
170 
172  // if SetData has been called before
173  bool IsAvailable() const { return available_; }
174 
176 
178 
179 
181  void Request(const FactoryBase* reqFactory) {
182  request_container::iterator it = requests_.find(reqFactory);
183  if (it == requests_.end())
184  requests_[reqFactory] = 1;
185  else
186  (it->second)++;
187  count_++; // increment request counter
188  }
189 
191  void Release(const FactoryBase* reqFactory) {
192  request_container::iterator it = requests_.find(reqFactory);
193  TEUCHOS_TEST_FOR_EXCEPTION(it == requests_.end(), Exceptions::RuntimeError, "MueLu::VariableContainer::Release(): "
194  "cannot call Release if factory has not been requested before by factory " << reqFactory);
195  if (--(it->second) == 0)
196  requests_.erase(it);
197  count_--;
198  }
199 
201  int NumRequests(const FactoryBase* reqFactory) const {
202  request_container::const_iterator it = requests_.find(reqFactory);
203  return (it != requests_.end()) ? it->second : 0;
204  }
205 
207  int NumAllRequests() const { return count_; }
208 
210  bool IsRequested(const FactoryBase* reqFactory) const { return (NumRequests(reqFactory) > 0); }
211 
213  bool IsRequested() const { return (count_ > 0); }
214 
215  const request_container& Requests() const { return requests_; }
217 
219 
220 
222  bool IsKept(KeepType keep) const { return keep_ & keep; }
223 
225  void AddKeepFlag(KeepType keep = UserData) { keep_ |= keep; }
226 
228  void RemoveKeepFlag(KeepType keep = UserData) { keep_ = keep_ & (keep_ ^ keep); }
229 
231  KeepType GetKeepFlag() const { return keep_; }
232 
234  };
235 
236 
237  template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
238  struct VariableContainer::Getter<Teuchos::RCP<Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > > {
239  typedef Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> Operator;
240  typedef Xpetra::Matrix <Scalar,LocalOrdinal,GlobalOrdinal,Node> Matrix;
241 
242  static Teuchos::RCP<Operator>& get(DataBase* data_, DataBase*& datah_) {
243  typedef Teuchos::RCP<Operator> TO;
244  typedef Teuchos::RCP<Matrix> TM;
245 
246  const std::string typeTOName = Teuchos::TypeNameTraits<TO>::name();
247  const std::string typeTMName = Teuchos::TypeNameTraits<TM>::name();
248  TEUCHOS_TEST_FOR_EXCEPTION(data_ == NULL, Teuchos::bad_any_cast,
249  "Error, cast to type Data<" << typeTOName << "> failed since the content is NULL");
250  if (data_->type() == typeid(TO)) {
251  Data<TO>* data = dynamic_cast<Data<TO>*>(data_);
252  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
253  "Error, cast to type Data<" << typeTOName << "> failed but should not have and the actual underlying type is "
254  "\'" << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
255  return data->data_;
256  }
257 
258  TEUCHOS_TEST_FOR_EXCEPTION(data_->type() != typeid(TM), Teuchos::bad_any_cast,
259  "Error, cast to type Data<" << typeTMName << "> failed since the actual underlying type is "
260  "\'" << data_->typeName() << "!");
261  Data<TM>* data = dynamic_cast<Data<TM>*>(data_);
262  TEUCHOS_TEST_FOR_EXCEPTION(!data, std::logic_error,
263  "Error, cast to type Data<" << typeTMName << "> failed but should not have and the actual underlying type is "
264  "\'" << data_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
265  if (datah_ == NULL)
266  datah_ = new Data<TO>(Teuchos::rcp_dynamic_cast<Operator>(data->data_));
267  Data<TO>* datah = dynamic_cast<Data<TO>*>(datah_);
268  TEUCHOS_TEST_FOR_EXCEPTION(!datah, std::logic_error,
269  "Error, cast to type Data<" << typeTOName << "> failed but should not have and the actual underlying type is "
270  "\'" << datah_->typeName() << "! The problem might be related to incompatible RTTI systems in static and shared libraries!");
271  return datah->data_;
272  }
273  };
274 
275 }
276 
277 #endif /* MUELU_VARIABLECONTAINER_HPP */
virtual std::string typeName() const =0
VariableContainer()
Default constructor.
void AddKeepFlag(KeepType keep=UserData)
Adds a keep flag to the flag combination.
int NumRequests(const FactoryBase *reqFactory) const
Return the number of times the data has been requested by a specific factory.
short KeepType
void SetData(const T &entry)
Store data in container class and set the "Available" status true.
User data are always kept. This flag is set automatically when Level::Set("data", data) is used...
void RemoveKeepFlag(KeepType keep=UserData)
Removes a keep flag to the flag combination.
Namespace for MueLu classes and methods.
int count_
number of requests by all factories
bool IsKept(KeepType keep) const
Returns true if at least one keep flag is set.
void Request(const FactoryBase *reqFactory)
Request data.
bool IsRequested(const FactoryBase *reqFactory) const
Returns true, if data is requested by reqFactory.
bool available_
is data available?
std::map< const FactoryBase *, int > request_container
const std::type_info & type() const
Base class for factories (e.g., R, P, and A_coarse).
request_container requests_
requesting factories
const request_container & Requests() const
int NumAllRequests() const
Returns the number of times the data has been requested.
void Release(const FactoryBase *reqFactory)
Release data.
KeepType GetKeepFlag() const
Returns the keep flag combination.
bool IsAvailable() const
Returns true if data is available, i.e.
static T & get(DataBase *data_, DataBase *&datah_)
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.
bool IsRequested() const
Returns true, if data is requested by at least one factory.