MueLu Version of the Day
Loading...
Searching...
No Matches
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
63namespace MueLu {
64
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(); }
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
98 TEUCHOS_TEST_FOR_EXCEPTION(data_ == NULL, Teuchos::bad_any_cast,
99 "Error, cast to type Data<" << typeName << "> failed since the content is NULL");
100
101 TEUCHOS_TEST_FOR_EXCEPTION(data_->type() != typeid(T), Teuchos::bad_any_cast,
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
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> > > {
247 typedef Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node> Operator;
248 typedef Xpetra::Matrix <Scalar,LocalOrdinal,GlobalOrdinal,Node> Matrix;
249
250 static Teuchos::RCP<Operator>& get(DataBase* data_, DataBase*& datah_) {
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 {
256 TEUCHOS_TEST_FOR_EXCEPTION(data_ == NULL, Teuchos::bad_any_cast,
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 {
272 TEUCHOS_TEST_FOR_EXCEPTION(data_->type() != typeid(TM), Teuchos::bad_any_cast,
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 */
Base class for MueLu classes.
Exception throws to report errors in the internal logical of the program.
Base class for factories (e.g., R, P, and A_coarse).
virtual std::string typeName() const =0
virtual const std::type_info & type() const =0
const std::type_info & type() const
Class that stores all relevant data for a variable.
bool IsRequested() const
Returns true, if data is requested by at least one factory.
DataBase * data_
the data itself
std::map< const FactoryBase *, int > request_container
void RemoveKeepFlag(KeepType keep=UserData)
Removes a keep flag to the flag combination.
bool IsRequested(const FactoryBase *reqFactory) const
Returns true, if data is requested by reqFactory.
void AddKeepFlag(KeepType keep=UserData)
Adds a keep flag to the flag combination.
bool IsAvailable() const
Returns true if data is available, i.e.
void Request(const FactoryBase *reqFactory)
Request data.
KeepType GetKeepFlag() const
Returns the keep flag combination.
void SetData(const T &entry)
Store data in container class and set the "Available" status true.
bool IsKept(KeepType keep) const
Returns true if at least one keep flag is set.
const request_container & Requests() const
request_container requests_
requesting factories
bool available_
is data available?
int count_
number of requests by all factories
int NumAllRequests() const
Returns the number of times the data has been requested.
VariableContainer()
Default constructor.
void Release(const FactoryBase *reqFactory)
Release data.
int NumRequests(const FactoryBase *reqFactory) const
Return the number of times the data has been requested by a specific factory.
Namespace for MueLu classes and methods.
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....
short KeepType
static T & get(DataBase *data_, DataBase *&)