MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_Level.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_LEVEL_HPP
11 #define MUELU_LEVEL_HPP
12 
13 #include <algorithm> // for swap
14 #include <map> // for _Rb_tree_const_iterator, etc
15 #include <ostream> // for basic_ostream, etc
16 #include <string> // for char_traits, string, etc
17 #include <utility> // for pair
18 
19 #include <Teuchos_Describable.hpp> // for operator<<
20 #include <Teuchos_FancyOStream.hpp> // for FancyOStream
21 #include <Teuchos_RCPDecl.hpp> // for RCP
22 #include <Teuchos_RCP.hpp> // for RCP::operator->, etc
23 #include <Teuchos_TestForException.hpp> // for TEUCHOS_TEST_FOR_EXCEPTION
24 
25 #include <Xpetra_Map.hpp> // for UnderlyingLib definition
26 
27 #include "MueLu_BoostGraphviz.hpp"
28 #include "MueLu_Exceptions.hpp" // for RuntimeError
30 #include "MueLu_KeepType.hpp"
31 #include "MueLu_NoFactory.hpp"
32 #include "MueLu_Utilities.hpp"
34 #include "MueLu_VerbosityLevel.hpp" // for MsgType::Default, VerbLevel
35 
36 namespace MueLu {
37 
63 class Level : public BaseClass {
64  public:
66 
68 
69  Level();
70 
71  Level(RCP<FactoryManagerBase>& factoryManager);
72 
74  virtual ~Level();
75 
77 
79  RCP<Level> Build();
82 
84 
86 
89  int GetLevelID() const;
90 
92  void SetLevelID(int levelID);
93 
96 
99  void SetPreviousLevel(const RCP<Level>& previousLevel);
101 
103 
104  // Users should not use this method.
106  void SetFactoryManager(const RCP<const FactoryManagerBase>& factoryManager);
107 
109  // Users should not use this method
112 
114 
119  template <class T>
120  void Set(const std::string& ename, const T& entry, const FactoryBase* factory = NoFactory::get()) {
121  const FactoryBase* fac = GetFactory(ename, factory);
122 
123  if (fac == NoFactory::get()) {
124  // Any data set with a NoFactory gets UserData keep flag by default
126  }
127 
128  // Store entry only if data have been requested (or any keep flag)
129  if (IsRequested(ename, factory) || GetKeepFlag(ename, factory) != 0) {
130  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(factory, ename), Exceptions::RuntimeError, "" + ename + " not found in");
131  map_[factory][ename]->SetData(entry);
132 
133  } else {
134  GetOStream(Runtime1) << "Level::Set: Not storing \"" << ename << "\" generated by factory " << factory->ShortClassName() << "[" << factory->GetID() << "]"
135  << " on level " << toString(GetLevelID()) << ", as it has not been requested and no keep flags were set for it" << std::endl;
136  }
137  } // Set
138 
140 
143 
145 
153  template <class T>
154  T& Get(const std::string& ename, const FactoryBase* factory = NoFactory::get()) {
155  const FactoryBase* fac = GetFactory(ename, factory);
156  /* printf("(l=%d) getting \"%20s\" generated by %10p [actually, generated by %p (%43s)]\n",
157  levelID_, ename.c_str(), factory, fac, fac->description().c_str());*/
158 
159  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(fac, ename), Exceptions::RuntimeError, "\"" + ename + "\" generated by factory \"" + fac->description() + "\" not found on level " + toString(GetLevelID()) + ".");
160 
161  if (!IsAvailable(ename, fac)) {
162  TEUCHOS_TEST_FOR_EXCEPTION(NumRequests(fac, ename) < 1 && GetKeepFlag(ename, fac) == 0, Exceptions::RuntimeError,
163  "\"" << ename << "\" has not been requested (counter = " << NumRequests(fac, ename) << ", "
164  "KeepFlag = "
165  << GetKeepFlag(ename, fac) << "). " << std::endl
166  << "Generating factory:" << *fac << " NoFactory = " << NoFactory::get());
167  fac->CallBuild(*this);
168  Release(*fac);
169  }
170 
172  "MueLu::Level::Get(): factory did not produce expected output on level " << GetLevelID()
173  << ". The data \"" << ename << "\" has not been generated by " << *fac);
174 
175  return map_[fac][ename]->template GetData<T>();
176  }
177 
179  template <class T>
180  void Get(const std::string& ename, T& rValue, const FactoryBase* factory = NoFactory::get()) {
181  rValue = Get<T>(ename, factory);
182  }
183 
184  template <class T>
185  bool IsType(const std::string& ename, const FactoryBase* factory = NoFactory::get()) {
186  const FactoryBase* fac = GetFactory(ename, factory);
187 
188  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(fac, ename), Exceptions::RuntimeError, "\"" + ename + "\" generated by factory \"" + fac->description() + "\" not found on level " + toString(GetLevelID()) + ".");
189 
190  if (!IsAvailable(ename, fac)) {
191  TEUCHOS_TEST_FOR_EXCEPTION(NumRequests(fac, ename) < 1 && GetKeepFlag(ename, fac) == 0, Exceptions::RuntimeError,
192  "\"" << ename << "\" has not been requested (counter = " << NumRequests(fac, ename) << ", "
193  "KeepFlag = "
194  << GetKeepFlag(ename, fac) << "). " << std::endl
195  << "Generating factory:" << *fac << " NoFactory = " << NoFactory::get());
196  fac->CallBuild(*this);
197  Release(*fac);
198  }
199 
201  "MueLu::Level::Get(): factory did not produce expected output on level " << GetLevelID()
202  << ". The data \"" << ename << "\" has not been generated by " << *fac);
203 
204  return map_[fac][ename]->template CheckType<T>();
205  }
206 
213  std::string GetTypeName(const std::string& ename, const FactoryBase* factory = NoFactory::get());
214 
216 
218 
219 
221  // This method is intented to be used by user drivers for printing, debugging or to keep some computed data for a next run of the setup phase.
222  //
223  // This method is an alias for: AddKeepFlag(ename, factory, MueLu::Keep)
224  // See also the description of KeepEnum for more information.
225  //
226  // To undo a keep request, one can use:
227  // - Delete(ename, factory) to delete the data and remove the "Keep" flag
228  // - or RemoveKeepFlag(ename, factory, MueLu::Keep) to go back to previous condition (data are kept only if internal MueLu logic need so).
229  //
230  // Note: Level variables tagged using this methods are also keep on the levels built using this.Build().
231  // This means that is you request to keep a specific variable on a fine level, all the coarser level that are created automatically during the setup phase will also retain the same variable.
232  void Keep(const std::string& ename, const FactoryBase* factory) { AddKeepFlag(ename, factory, MueLu::Keep); } // Note: do not add default value for input parameter 'factory'
233 
235  // Special cases:
236  // - If entry (ename, factory) does not exist, nothing is done.
237  // - If entry exists but counter !=, entry cannot be desallocated before counter set to 0 (using Release()) so an exeption is thrown.
238  void Delete(const std::string& ename, const FactoryBase* factory);
239 
241  void Clear();
242 
245  void ExpertClear();
246 
250  bool IsKept(const std::string& ename, const FactoryBase* factory, KeepType keep) const { return GetKeepFlag(ename, factory) & keep; }
251 
256  void AddKeepFlag(const std::string& ename, const FactoryBase* factory = NoFactory::get(), KeepType keep = MueLu::Keep); // TODO: remove default value for input parameter 'factory'?
257 
261  void RemoveKeepFlag(const std::string& ename, const FactoryBase* factory, KeepType keep = MueLu::All);
262 
264  KeepType GetKeepFlag(const std::string& ename, const FactoryBase* factory) const;
265 
267 
270 
271 
273  void Request(const FactoryBase& factory);
274 
276  void Release(const FactoryBase& factory);
277 
279  void DeclareInput(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy = NoFactory::get());
280 
282  void DeclareDependencies(const FactoryBase* factory, bool bRequestOnly = false, bool bReleaseOnly = false);
283 
285  void Request(const std::string& ename, const FactoryBase* factory = NoFactory::get(), const FactoryBase* requestedBy = NoFactory::get());
286 
288  void Release(const std::string& ename, const FactoryBase* factory = NoFactory::get(), const FactoryBase* requestedBy = NoFactory::get());
289 
291 
293 
294 
296  bool IsAvailable(const std::string& ename, const FactoryBase* factory = NoFactory::get()) const;
297 
299  bool IsRequested(const std::string& ename, const FactoryBase* factory = NoFactory::get()) const;
300 
302 
304 
306  std::string description() const;
307 
309  // TODO: print only shows requested variables. check if we also list kept factories with ref counter=0?
310  void print(std::ostream& out, const VerbLevel verbLevel = Default) const;
311 
312 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
313  void UpdateGraph(std::map<const FactoryBase*, BoostVertex>& vindices,
314  std::map<std::pair<BoostVertex, BoostVertex>, std::string>& edges,
315  BoostProperties& dp,
316  BoostGraph& graph) const;
317 #endif
318 
320 
323  UNDEF };
325 
326  void setlib(Xpetra::UnderlyingLib lib2) { lib_ = lib2; }
328 
329  void SetComm(RCP<const Teuchos::Comm<int> > const& comm) { comm_ = comm; }
331 
332  private:
334  Level(const Level& source);
335 
337  //
338  // If factory == NULL, the default factory is defined as follow:
339  // - If user data is available, it is considered as the default and the factory manager is ignored.
340  // => The default factory is then NoFactory.
341  // - Else, the factory manager is used to get the default factory.
342  //
343  // This strategy allows to use the same factory manager on the fine and coarse level without any trouble.
344  // Example :
345  //
346  // FineLevel:
347  // ----------
348  // A -> User provided
349  // Nullspace -> User provided
350  //
351  // CoarseLevel:
352  // ------------
353  // A -> RAPFactory
354  // NullSpace -> NullspaceFactory
355  //
356  const FactoryBase* GetFactory(const std::string& varname, const FactoryBase* factory) const;
357 
361 
362  using Key1 = const FactoryBase*;
363  using Key2 = const std::string;
367 
368  int levelID_; // id number associated with level
370  RCP<Level> previousLevel_; // linked list of Level
372 
374 
375 
377  bool IsKey(const FactoryBase* factory, const std::string& ename) const;
378 
379  bool IsAvailableFactory(const FactoryBase* factory) const;
380 
381  bool IsRequested(const Value& v) const;
382 
383  bool IsRequestedBy(const FactoryBase* factory, const std::string& ename, const FactoryBase* requestedBy) const;
384 
385  bool IsRequestedBy(const Value& v, const FactoryBase* requestedBy) const;
386 
387  bool IsRequestedFactory(const FactoryBase* factory) const;
388 
389  const Value& Get(const FactoryBase* factory, const std::string& ename) const;
390 
391  int NumRequests(const FactoryBase* factory, const std::string& ename) const;
392 
393  int CountRequestedFactory(const FactoryBase* factory) const;
394 
396 
397 }; // class Level
398 
399 } // namespace MueLu
400 
401 // TODO: Caps should not matter
402 
403 #endif // MUELU_LEVEL_HPP
void Keep(const std::string &ename, const FactoryBase *factory)
Request to keep variable &#39;ename&#39; generated by &#39;factory&#39; after the setup phase.
virtual ~Level()
Destructor.
RCP< const Teuchos::Comm< int > > comm_
KeepType GetKeepFlag(const std::string &ename, const FactoryBase *factory) const
Get the flag combination set for variable &#39;ename&#39; generated by &#39;factory&#39;.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
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-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
virtual void CallBuild(Level &requestedLevel) const =0
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
bool IsKept(const std::string &ename, const FactoryBase *factory, KeepType keep) const
void DeclareDependencies(const FactoryBase *factory, bool bRequestOnly=false, bool bReleaseOnly=false)
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput() to declare factory depe...
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
Xpetra::UnderlyingLib lib_
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
short KeepType
TwoKeyMap map_
const std::string Key2
RCP< Level > previousLevel_
User data are always kept. This flag is set automatically when Level::Set(&quot;data&quot;, data) is used...
void SetPreviousLevel(const RCP< Level > &previousLevel)
Definition: MueLu_Level.cpp:62
void SetFactoryManager(const RCP< const FactoryManagerBase > &factoryManager)
Set default factories (used internally by Hierarchy::SetLevel()).
Definition: MueLu_Level.cpp:69
int CountRequestedFactory(const FactoryBase *factory) const
static const NoFactory * get()
void setlib(Xpetra::UnderlyingLib lib2)
RequestMode GetRequestMode() const
Base class for factories (e.g., R, P, and A_coarse).
void Clear()
Delete all data that have been retained after the setup phase using Final flag.
bool IsRequestedBy(const FactoryBase *factory, const std::string &ename, const FactoryBase *requestedBy) const
const FactoryBase * GetFactory(const std::string &varname, const FactoryBase *factory) const
If input factory == NULL, returns the default factory. Else, return input factory.
void ExpertClear()
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
static RequestMode requestMode_
void Delete(const std::string &ename, const FactoryBase *factory)
Delete data that have been retained after the setup phase (using Keep(), AddKeepFlag(), or internal MueLu logic).
Definition: MueLu_Level.cpp:89
int levelID_
Map of a map (Key1 -&gt; SubMap)
std::string GetTypeName(const std::string &ename, const FactoryBase *factory=NoFactory::get())
GetTypeName returns type string of variable stored using ename and factory.
Definition: MueLu_Level.cpp:77
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
std::string description() const
Return a simple one-line description of this object.
Xpetra::UnderlyingLib lib()
Always keep data, even accross run. This flag is set by Level::Keep(). This flag is propagated to coa...
int NumRequests(const FactoryBase *factory, const std::string &ename) const
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
bool IsAvailableFactory(const FactoryBase *factory) const
Base class for MueLu classes.
RCP< Level > Build()
Definition: MueLu_Level.cpp:29
RCP< Level > & GetPreviousLevel()
Previous level.
Definition: MueLu_Level.cpp:60
void print(std::ostream &out, const VerbLevel verbLevel=Default) const
Printing method.
bool IsType(const std::string &ename, const FactoryBase *factory=NoFactory::get())
void SetLevelID(int levelID)
Set level number.
Definition: MueLu_Level.cpp:53
RCP< const FactoryManagerBase > factoryManager_
bool IsRequestedFactory(const FactoryBase *factory) const
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
Definition: MueLu_Level.cpp:73
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
Exception throws to report errors in the internal logical of the program.
void SetComm(RCP< const Teuchos::Comm< int > > const &comm)
Description of what is happening (more verbose)
bool IsRequested(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need has been requested. Note: this tells nothing about whether the need&#39;s value exist...
bool IsKey(const FactoryBase *factory, const std::string &ename) const
Test whether some information about (ename, factory) are stored.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
RCP< const Teuchos::Comm< int > > GetComm() const
void Get(const std::string &ename, T &rValue, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access).
virtual std::string description() const
Return a simple one-line description of this object.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.