MueLu  Version of the Day
MueLu_Factory.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_FACTORY_HPP
47 #define MUELU_FACTORY_HPP
48 
49 #include <string>
50 #include <deque> // for _Deque_iterator, operator!=
51 #include <ostream> // for operator<<, etc
52 #include "Teuchos_ENull.hpp" // for ENull::null
53 #include "Teuchos_FilteredIterator.hpp" // for FilteredIterator, etc
54 #include "Teuchos_ParameterEntry.hpp" // for ParameterEntry
55 #include "Teuchos_ParameterList.hpp" // for ParameterList, etc
56 #include "Teuchos_RCPDecl.hpp" // for RCP
57 #include "Teuchos_RCPNode.hpp" // for operator<<
58 #include "Teuchos_StringIndexedOrderedValueObjectContainer.hpp"
59 #include "Teuchos_RCP.hpp"
60 
61 #include "MueLu_ConfigDefs.hpp"
62 #include "MueLu_FactoryBase.hpp"
65 #include "MueLu_Level.hpp"
66 
67 namespace MueLu {
68 
70 
71  public:
73 
76 #ifdef HAVE_MUELU_DEBUG
77  : multipleCallCheck_(FIRSTCALL), lastLevelID_(-1)
78 #endif
79  { }
80 
82  virtual ~Factory() { }
84 
86 
89  virtual void SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
90  RCP<const FactoryBase> f = factory;
91  SetParameter(varName, ParameterEntry(f)); // parameter validation done in ParameterListAcceptorImpl
92  }
93 
95  const RCP<const FactoryBase> GetFactory(const std::string& varName) const {
96  if (!GetParameterList().isParameter(varName)&& GetValidParameterList() == Teuchos::null) {
97  // If the parameter is not on the list and there is not validator, the defaults values for 'varName' is not set.
98  // Failback by using directly the FactoryManager
99  // NOTE: call to GetValidParameterList() can be costly for classes that validate parameters.
100  // But it get called only (lazy '&&' operator) if the parameter 'varName' is not on the paramlist and
101  // the parameter 'varName' is always on the list when validator is present and 'varName' is valid (at least the default value is set).
102  return Teuchos::null;
103  }
104 
105  return GetParameterList().get< RCP<const FactoryBase> >(varName);
106  }
107 
109  RCP<ParameterList> paramList = rcp(new ParameterList(list));
110  // Remove FactoryBase entries from the list
111  // The solution would be much more elegant if ParameterList support std::list like operations
112  // In that case, we could simply write:
113  // for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++)
114  // if (paramList.isType<RCP<const FactoryBase> >(it->first))
115  // it = paramList.erase(it);
116  // else
117  // it++;
118  ParameterList::ConstIterator it = paramList->begin();
119  while (it != paramList->end()) {
120  it = paramList->begin();
121 
122  for (; it != paramList->end(); it++)
123  if (paramList->isType<RCP<const FactoryBase> >(it->first))
124  paramList->remove(it->first);
125  }
126  return paramList;
127  }
128 
129  // SetParameterList(...);
130 
131  // GetParameterList(...);
132 
134 
136  return Teuchos::null; // Teuchos::null == GetValidParameterList() not implemented == skip validation and no default values (dangerous)
137  }
138 
139  protected:
140 
141  void Input(Level& level, const std::string& varName) const {
142  level.DeclareInput(varName, GetFactory(varName).get(), this);
143  }
144  // Similar to the other Input, but we have an alias (varParamName) to the generated data name (varName)
145  void Input(Level& level, const std::string& varName, const std::string& varParamName) const {
146  level.DeclareInput(varName, GetFactory(varParamName).get(), this);
147  }
148 
149  template <class T>
150  T Get(Level& level, const std::string& varName) const {
151  return level.Get<T>(varName, GetFactory(varName).get());
152  }
153  // Similar to the other Get, but we have an alias (varParamName) to the generated data name (varName)
154  template <class T>
155  T Get(Level& level, const std::string& varName, const std::string& varParamName) const {
156  return level.Get<T>(varName, GetFactory(varParamName).get());
157  }
158 
159  template <class T>
160  void Set(Level& level, const std::string& varName, const T& data) const {
161  return level.Set<T>(varName, data, this);
162  }
163 
164  bool IsAvailable(Level& level, const std::string& varName) const {
165  return level.IsAvailable(varName, GetFactory(varName).get());
166  }
167 
168 #ifdef HAVE_MUELU_DEBUG
169  public:
170  enum multipleCallCheckEnum { ENABLED, DISABLED, FIRSTCALL };
171 
172  void EnableMultipleCallCheck() const { multipleCallCheck_ = ENABLED; }
173  void DisableMultipleCallCheck() const { multipleCallCheck_ = DISABLED; }
174  void ResetDebugData() const {
175  if (multipleCallCheck_ == FIRSTCALL && lastLevelID_ == -1)
176  return;
177 
178  multipleCallCheck_ = FIRSTCALL;
179  lastLevelID_ = -1;
180 
181  const ParameterList& paramList = GetParameterList();
182 
183  // We cannot use just FactoryManager to specify which factories call ResetDebugData().
184  // The problem is that some factories are not present in the manager, but
185  // instead are only accessible through a parameter list of some factory.
186  // For instance, FilteredAFactory is only accessible from SaPFactory but
187  // nowhere else. So we miss those, and do not reset the data, resulting
188  // in problems.
189  // Therefore, for each factory we need to go through its dependent
190  // factories, and call reset on them.
191  for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++)
192  if (paramList.isType<RCP<const FactoryBase> >(it->first)) {
193  RCP<const Factory> fact = rcp_dynamic_cast<const Factory >(paramList.get<RCP<const FactoryBase> >(it->first));
194  if (fact != Teuchos::null && fact != NoFactory::getRCP())
195  fact->ResetDebugData();
196  }
197  }
198 
199  static void EnableMultipleCheckGlobally() { multipleCallCheckGlobal_ = ENABLED; }
200  static void DisableMultipleCheckGlobally() { multipleCallCheckGlobal_ = DISABLED; }
201 
202  protected:
203  mutable multipleCallCheckEnum multipleCallCheck_;
204  static multipleCallCheckEnum multipleCallCheckGlobal_;
205  mutable int lastLevelID_;
206 #else
207  public:
208  void EnableMultipleCallCheck() const { }
209  void DisableMultipleCallCheck() const { }
210  void ResetDebugData() const { }
211  static void EnableMultipleCheckGlobally() { }
213 #endif
214  }; //class Factory
215 
216 } //namespace MueLu
217 
218 #define MUELU_FACTORY_SHORT
219 #endif //ifndef MUELU_FACTORY_HPP
virtual RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level->Get< RCP<Matrix> >("A", factory) if factory == NULL => use default factory.
T Get(Level &level, const std::string &varName, const std::string &varParamName) const
virtual ~Factory()
Destructor.
T & get(const std::string &name, T def_value)
static void DisableMultipleCheckGlobally()
RCP< ParameterList > RemoveFactoriesFromList(const ParameterList &list) const
Namespace for MueLu classes and methods.
bool IsAvailable(Level &level, const std::string &varName) const
Factory()
Constructor.
Base class for factories (e.g., R, P, and A_coarse).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
params_t::ConstIterator ConstIterator
void Input(Level &level, const std::string &varName, const std::string &varParamName) const
void DisableMultipleCallCheck() const
T Get(Level &level, const std::string &varName) const
static void EnableMultipleCheckGlobally()
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
virtual const Teuchos::ParameterList & GetParameterList() const
void SetParameter(const std::string &name, const ParameterEntry &entry)
Set a parameter directly as a ParameterEntry.
void Input(Level &level, const std::string &varName) const
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory()
virtual void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Configuration.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
void Set(Level &level, const std::string &varName, const T &data) const
void EnableMultipleCallCheck() const
void ResetDebugData() const
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
static const RCP< const NoFactory > getRCP()
Static Get() functions.