MueLu  Version of the Day
MueLu_Level.cpp
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 #include <Teuchos_TabularOutputter.hpp>
47 
48 #include "MueLu_Level.hpp"
49 
51 
52 namespace MueLu {
53 
54  RCP<Level> Level::Build() {
55  RCP<Level> newLevel = rcp(new Level());
56 
57  // Copy 'keep' status of variables
58  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
59  const FactoryBase* factory = kt->first;
60 
61  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
62  const std::string& ename = it->first;
63 
64  if (IsKept(ename, factory, MueLu::Keep)) { // MueLu::Keep is the only flag propagated
65  if (factory == NULL) // TODO: Is this possible?? Throw exception. Not supposed to use the FactoryManager here.
66  newLevel->Keep(ename, NoFactory::get());
67  else
68  newLevel->Keep(ename, factory);
69  }
70  }
71  }
72 
73  return newLevel;
74  }
75 
76  int Level::GetLevelID() const { return levelID_; }
77 
78  void Level::SetLevelID(int levelID) {
79  if (levelID_ != -1 && levelID_ != levelID)
80  GetOStream(Warnings1) << "Level::SetLevelID(): Changing an already defined LevelID (previousID=" << levelID_ << ", newID=" << levelID << ")" << std::endl;
81 
82  levelID_ = levelID;
83  }
84 
85  void Level::SetPreviousLevel(const RCP<Level> & previousLevel) {
86  if (previousLevel_ != Teuchos::null && previousLevel_ != previousLevel)
87  GetOStream(Warnings1) << "Level::SetPreviousLevel(): PreviousLevel was already defined" << std::endl;
88 
89  previousLevel_ = previousLevel;
90  }
91 
92  void Level::SetFactoryManager(const RCP<const FactoryManagerBase> & factoryManager) {
93  factoryManager_ = factoryManager;
94  }
95 
96  const RCP<const FactoryManagerBase> Level::GetFactoryManager() {
97  return factoryManager_;
98  }
99 
100  void Level::AddKeepFlag(const std::string& ename, const FactoryBase* factory, KeepType keep) {
101  if (!IsKey(factory, ename)) {
102  // If the entry does not exist, create it to store the keep flag
103  Teuchos::RCP<MueLu::VariableContainer> newVar = Teuchos::rcp(new MueLu::VariableContainer);
104  map_[factory][ename] = newVar;
105  }
106  // Set the flag
107  map_[factory][ename]->AddKeepFlag(keep);
108  }
109 
110  void Level::RemoveKeepFlag(const std::string& ename, const FactoryBase* factory, KeepType keep) {
111  // No entry = nothing to do
112  if (!IsKey(factory, ename))
113  return;
114 
115  // Remove the flag
116  Teuchos::RCP<MueLu::VariableContainer>& v = map_[factory][ename];
117  v->RemoveKeepFlag(keep);
118 
119  // Remove data if no keep flag left and counter == 0
120  if ((v->IsRequested() == false) && (v->GetKeepFlag() == 0)) {
121  v = Teuchos::null; // free data
122 
123  map_[factory].erase(ename);
124  if (map_.count(factory) == 0)
125  map_.erase(factory);
126  }
127  }
128 
129  KeepType Level::GetKeepFlag(const std::string& ename, const FactoryBase* factory) const {
130  if (!IsKey(factory,ename))
131  return false;
132 
133  return Get(factory, ename)->GetKeepFlag();
134  }
135 
136  void Level::Request(const FactoryBase& factory) {
137  RequestMode prev = requestMode_;
139  factory.CallDeclareInput(*this);
140  requestMode_ = prev;
141  }
142 
143  void Level::Release(const FactoryBase& factory) {
144  RequestMode prev = requestMode_;
146  factory.CallDeclareInput(*this);
147  requestMode_ = prev;
148  }
149 
150  void Level::DeclareInput(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
151  if (requestMode_ == REQUEST) {
152  try {
153  Request(ename, factory, requestedBy);
154 
155  } catch (Exceptions::DependencyError& e) {
156  std::ostringstream msg;
157  msg << requestedBy->ShortClassName() << "::DeclareInput: (" << e.what() << ") unable to find or generate requested data \""
158  << ename << "\" with generating factory \"" << ((factory != NULL) ? factory->ShortClassName() : "null") << "\" [" << factory << "]";
159  msg << "\n during request for data \"" << std::setw(15) << ename << "\" on level " << GetLevelID()
160  << " by factory " << std::setw(25) << requestedBy->ShortClassName() << " [" << requestedBy << "]";
161  throw Exceptions::RuntimeError(msg.str());
162 
163  } catch (Exceptions::RuntimeError &e) {
164  std::ostringstream msg;
165  msg << e.what() << "\n during request for data \"" << std::setw(15) << ename << "\" on level " << GetLevelID()
166  << " by factory " << std::setw(25) << requestedBy->ShortClassName() << " [" << requestedBy << "]";
167  throw Exceptions::RuntimeError(msg.str());
168  }
169 
170  } else if (requestMode_ == RELEASE) {
171  Release(ename, factory, requestedBy);
172 
173  } else
174  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareInput(): requestMode_ undefined.");
175  }
176 
177  void Level::DeclareDependencies(const FactoryBase* factory, bool bRequestOnly, bool bReleaseOnly) { //TODO: replace bReleaseOnly, bReleaseOnly by one RequestMode enum
178  if (bRequestOnly && bReleaseOnly)
179  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareDependencies(): Both bRequestOnly and bReleaseOnly set to true makes no sense.");
180 
181  if (requestMode_ == REQUEST) {
182 
183  if (bReleaseOnly == false) Request(*factory);
184 
185  } else if (requestMode_ == RELEASE) {
186 
187  if (bRequestOnly == false) Release(*factory);
188 
189  } else TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareDependencies(): requestMode_ undefined.");
190  }
191 
192  void Level::Request(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
193  const FactoryBase* fac = GetFactory(ename, factory);
194  // printf("(l=%d) [%43s] requesting \"%20s\" generated by %10p [actually, generated by %p (%43s)]\n",
195  // levelID_, requestedBy->description().c_str(), ename.c_str(), factory, fac, fac->description().c_str());
196 
197  // We request factory only if necessary, i.e.
198  // - factory has not been requested before, and
199  // - we need data which is not available
200  // Let us consider an RAP factory in the reuse scenario. The factory generates "A" (coarse matrix) and
201  // "RAP graph" (pattern of A). Typically, "A" has keep flag Final, which is cleared during next Setup, but
202  // "RAP graph" has flag Keep, which is not cleared as it is part of NextRun. Therefore, during next Setup
203  // we have RAP factory with available "RAP graph" but not available "A".
204  //
205  // During the regular construction phase, we will do a single request: ("A", RAPFactory). Suppose, we used
206  // bool test = (IsRequestedFactory(fac) == false && IsAvailable(fac) == false);
207  // This is incorrect, as IsAvailable(fac) checks whether there is *any* data generated by factory, which there is
208  // ("A"), and the dependencies of the factory would not be requested despite the need for them (we need fine A, P, and
209  // R to generate Ac even if we know sparsity pattern of Ac).
210  //
211  // On the other hand,
212  // bool test = (IsRequestedFactory(fac) == false && IsAvailable(ename, fac) == false);
213  // is correct as ("A", fac) is not available (only ("RAP graph", fac) is), and dependent factories would be
214  // properly requested.
215  //
216  // This way, factory is requested only once (because of the IsRequested(fac) check), and only when one of the needed
217  // pieces of data is not availble.
218  bool test = (IsRequestedFactory(fac) == false && IsAvailable(ename, fac) == false);
219 
220  // This request must be done before calling Request(*fac) to avoid circular dependency problems.
221  if (!IsKey(fac, ename)) {
222  Teuchos::RCP<MueLu::VariableContainer> newVar = Teuchos::rcp(new MueLu::VariableContainer);
223  map_[fac][ename] = newVar;
224  }
225 
226  Teuchos::RCP<MueLu::VariableContainer>& v = map_[fac][ename];
227  v->Request(requestedBy);
228 
229  // The value of IsRequestedFactory(fac) is true, due to the above request.
230  // That is why a temporary boolean "test" is used!
231  TEUCHOS_TEST_FOR_EXCEPTION(IsRequestedFactory(fac) != true, Exceptions::RuntimeError, "Level::Request(ename, factory): internal logic error.");
232 
233  if (test) {
234  // Call Request for factory dependencies.
235  // We only do that if necessary, see comments above
236  Request(*fac);
237  }
238  }
239 
240  void Level::Release(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
241  const FactoryBase* fac = GetFactory(ename, factory);
242  // printf("(l=%d) [%43s] releasing \"%20s\" generated by %10p [actually, generated by %p (%43s)]\n",
243  // levelID_, requestedBy->description().c_str(), ename.c_str(), factory, fac, fac->description().c_str());
244 
245  // Only a factory which has requested (fac,ename) is allowed to release it again.
246  // Do not release data if it has not been requested by the factory "requestedBy"
247  // Note: when data is released (fac,ename) depends on it often happened that some
248  // of this data has (recursively) been released too often
249  if (IsRequestedBy(fac, ename, requestedBy)) {
250 
251  // In general all data (fac,ename) depends on is released when calling Get in generating factory (fac) Build method
252  // Here we check the need to release the dependencies of some data that has been requested (by factory "requestedBy")
253  // but the corresponding Build function of factory "fac" has never been called. Therefore the dependencies
254  // have never been released. Do it now.
255  if (CountRequestedFactory(fac) == 1 && // check if factory fac is not requested by another factory
256  IsAvailableFactory(fac) == false) { // check if Build function of factory fac has been called
257  Release(*fac);
258  }
259 
260  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(fac,ename), Exceptions::RuntimeError, "\"" + ename + "\" not found. Do a request first.");
261 
262  Teuchos::RCP<MueLu::VariableContainer>& v = map_[fac][ename];
263  v->Release(requestedBy);
264 
265  // Remove data if no keep flag left and counter == 0
266  if ((v->IsRequested() == false) && (v->GetKeepFlag() == 0)) {
267  v = Teuchos::null; // free data
268 
269  map_[fac].erase(ename);
270  if (map_.count(fac) == 0)
271  map_.erase(fac);
272  }
273  }
274  }
275 
276  void Level::Clear() {
277  // TODO: needs some love, ugly as it is
278  // The ugliness is the fact that we restart both loops when we remove a single element
279  bool wasRemoved;
280  do {
281  wasRemoved = false;
282  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
283  const FactoryBase* factory = kt->first;
284 
285  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
286  // We really want a reference here, but because later we'll need to check whether the
287  // key was removed, we should copy the value
288  const std::string ename = it->first;
289 
290  // We clear all the data that
291  // a) has not been requested
292  // b) is not being kept using NextRun (e.g., we clear out Final data)
293  if (!IsKept(ename, factory, MueLu::NextRun)) {
294  RemoveKeepFlag(ename, factory, MueLu::All); // will delete the data if counter == 0
295 
296  // To prevent infinite looping, we need to check whether we have
297  // actually removed the data. In buggy code it may happen that we
298  // were unable to do that, for instance, if the data was outstanding
299  // request
300  if (IsKey(factory, ename)) {
301  GetOStream(Errors) << "Level::Clear found Internal data inconsistency" << std::endl;
302  print(GetOStream(Errors), VERB_EXTREME);
303 
304  throw Exceptions::RuntimeError("Level::Clear found Internal data inconsistency");
305  }
306 
307  wasRemoved = true;
308  break;
309  }
310  }
311 
312  if (wasRemoved)
313  break;
314  }
315 
316  } while (wasRemoved == true);
317  }
318 
320  TwoKeyMap::const_iterator kt = map_.begin();
321  while (kt != map_.end()) {
322  const FactoryBase* factory = kt->first;
323 
324  SubMap::const_iterator it = kt->second.begin();
325  while ( it != kt->second.end()) {
326  const std::string& ename = it->first;
327 
328  // obtain variable container
329  Teuchos::RCP<MueLu::VariableContainer>& v = map_[factory][ename];
330 
331  if (v->GetKeepFlag() == 0 ||
332  v->IsKept(MueLu::UserData) == true ||
333  v->IsKept(MueLu::Final) == true) {
334  it++;
335  v = Teuchos::null; // free data
336  map_[factory].erase(ename);
337  if (map_.count(factory) == 0) {
338  break; // last occurrence for factory has been removed. proceed with next factory
339  }
340  }
341  else
342  it++;
343  } // end for it
344 
345  if (map_.count(factory) == 0) {
346  kt++;
347  map_.erase(factory);
348  } else kt++;
349  }
350  }
351 
352  std::string Level::description() const {
353  std::ostringstream out;
354  out << BaseClass::description();
355  out << "{ levelID = " << levelID_ << "}";
356  return out.str();
357  }
358 
359  void Level::print(std::ostream& out, const VerbLevel verbLevel) const {
360  if (!(verbLevel & Debug))
361  return;
362 
363  out << "LevelID = " << GetLevelID() << std::endl;
364 
365  typedef Teuchos::TabularOutputter TTO;
366  TTO outputter(out);
367  outputter.pushFieldSpec("data name", TTO::STRING, TTO::LEFT, TTO::GENERAL, 20);
368  outputter.pushFieldSpec("gen. factory addr.", TTO::STRING, TTO::LEFT, TTO::GENERAL, 40);
369  outputter.pushFieldSpec("req", TTO::INT, TTO::LEFT, TTO::GENERAL, 3);
370  outputter.pushFieldSpec("keep", TTO::STRING, TTO::LEFT, TTO::GENERAL, 5);
371  outputter.pushFieldSpec("type", TTO::STRING, TTO::LEFT, TTO::GENERAL, 18);
372  outputter.pushFieldSpec("data", TTO::STRING, TTO::LEFT, TTO::GENERAL, 14);
373  outputter.pushFieldSpec("req'd by", TTO::STRING, TTO::LEFT, TTO::GENERAL, 20);
374  outputter.outputHeader();
375 
376  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
377  const FactoryBase* factory = kt->first;
378 
379  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
380  const std::string& ename = it->first;
381 
382  outputter.outputField(ename); // variable name
383 
384  // NOTE: We cannot dereference the factory pointer and call factory->description() as we do not know
385  // if the factory still exist (the factory pointer is a raw pointer by design). Instead, the level
386  // should store the factory description internally as a string for debugging purpose (and in debug mode only).
387  // // factory name
388  // std::stringstream ss1;
389  // ss1 << (*kt)->description();
390  // outputter.outputField((ss1.str()).substr(0,30));
391  if(factory == 0) {
392  outputter.outputField("Null");
393  }
394  else if (factory == NoFactory::get()) {
395  outputter.outputField("NoFactory");
396  }
397  else {
398  std::ostringstream oss; oss << factory->ShortClassName() << "["<<factory->GetID()<<"]";
399 #ifdef HAVE_MUELU_DEBUG
400  oss<<"(" << factory <<")";
401 #endif
402  outputter.outputField(oss.str());
403  }
404 
405  int reqcount = NumRequests(factory, ename); // request counter
406  outputter.outputField(reqcount);
407 
408  KeepType keepType = GetKeepFlag(ename, factory);
409  if (keepType != 0) {
410  std::stringstream ss;
411  if (keepType & MueLu::UserData) { ss << "User"; }
412  if (keepType & MueLu::Keep) { ss << "Keep"; }
413  if (keepType & MueLu::Final) { ss << "Final"; }
414  outputter.outputField(ss.str());
415  } else {
416  outputter.outputField("No");
417  }
418 
419  if (IsAvailable(ename, factory)) {
420  std::string strType = it->second->GetTypeName();
421 
422  if (strType == "int") {
423  outputter.outputField(strType);
424  outputter.outputField(it->second->GetData<int>());
425  } else if (strType == "double") {
426  outputter.outputField(strType);
427  outputter.outputField(it->second->GetData<double>());
428  } else if (strType == "string") {
429  outputter.outputField(strType);
430  outputter.outputField(it->second->GetData<std::string>());
431  } else {
432  size_t npos = std::string::npos;
433 
434  if (strType.find("MueLu::Aggregates") != npos) outputter.outputField("Aggregates");
435  else if (strType.find("MueLu::AmalgamationInfo") != npos) outputter.outputField("AmalgamationInfo");
436  else if (strType.find("MueLu::Constraint") != npos) outputter.outputField("Constraint");
437  else if (strType.find("MueLu::Graph") != npos) outputter.outputField("Graph");
438  else if (strType.find("MueLu::SmootherBase") != npos) outputter.outputField("SmootherBase");
439  else if (strType.find("MueLu::SmootherPrototype") != npos) outputter.outputField("SmootherPrototype");
440  else if (strType.find("Xpetra::Export") != npos) outputter.outputField("Export");
441  else if (strType.find("Xpetra::Import") != npos) outputter.outputField("Import");
442  else if (strType.find("Xpetra::Map") != npos) outputter.outputField("Map");
443  else if (strType.find("Xpetra::Matrix") != npos) outputter.outputField("Matrix" );
444  else if (strType.find("Xpetra::MultiVector") != npos) outputter.outputField("Vector");
445  else if (strType.find("Xpetra::Operator") != npos) outputter.outputField("Operator");
446  else outputter.outputField(strType);
447 
448  outputter.outputField("available");
449  }
450 
451  } else {
452  outputter.outputField("unknown");
453  outputter.outputField("not available");
454  }
455 
456  typedef VariableContainer::request_container container_type;
457  const container_type& requestedBy = it->second->Requests();
458  std::ostringstream ss;
459  for (container_type::const_iterator ct = requestedBy.begin(); ct != requestedBy.end(); ct++) {
460  if (ct != requestedBy.begin()) ss << ",";
461  ss << ct->first->ShortClassName() <<"["<<ct->first->GetID()<<"]";
462 #ifdef HAVE_MUELU_DEBUG
463  ss<<"("<<ct->first<<")";
464 #endif
465 
466  if (ct->second > 1) ss << "x" << ct->second;
467  }
468  outputter.outputField(ss.str());
469 
470  outputter.nextRow();
471  }
472  } // for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
473  }
474 
475 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
476  void Level::UpdateGraph(std::map<const FactoryBase*, BoostVertex>& vindices,
477  std::map<std::pair<BoostVertex, BoostVertex>, std::string>& edges,
478  BoostProperties& dp,
479  BoostGraph& graph) const {
480  size_t vind = vindices.size();
481 
482  for (TwoKeyMap::const_iterator it1 = map_.begin(); it1 != map_.end(); it1++) {
483  if (vindices.find(it1->first) == vindices.end()) {
484  BoostVertex boost_vertex = boost::add_vertex(graph);
485  std::ostringstream oss; oss<<it1->first->ShortClassName() << "[" << it1->first->GetID() << "]";
486  boost::put("label", dp, boost_vertex, oss.str());
487  vindices[it1->first] = vind++;
488  }
489 
490  for (SubMap::const_iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++) {
491  const VariableContainer::request_container& requests = it2->second->Requests();
492  for (VariableContainer::request_container::const_iterator rit = requests.begin(); rit != requests.end(); rit++) {
493  if (vindices.find(rit->first) == vindices.end()) {
494  // requested by factory which is unknown
495  BoostVertex boost_vertex = boost::add_vertex(graph);
496  std::ostringstream oss; oss<<rit->first->ShortClassName() << "[" << rit->first->GetID() << "]";
497  boost::put("label", dp, boost_vertex, oss.str());
498  vindices[rit->first] = vind++;
499  }
500 
501  edges[std::pair<BoostVertex,BoostVertex>(vindices[rit->first], vindices[it1->first])] = it2->first;
502  }
503  }
504  }
505  }
506 #endif
507 
508  // JG Note: should the option IgnoreUserData() moved to the Factory interface or on the specific factories that are using this option? It would simplify the level class.
509  const FactoryBase* Level::GetFactory(const std::string& ename, const FactoryBase* factory) const {
510  if (factory != NULL)
511  return factory;
512 
513  // If IgnoreUserData == false and if variable "ename" generated by NoFactory is provided by the user (MueLu::UserData),
514  // use user-provided data by default without querying the FactoryManager.
515  // When FactoryManager == null, we consider that IgnoreUserData == false.
516  if ((factoryManager_ == Teuchos::null || factoryManager_->IgnoreUserData() == false) &&
517  (IsAvailable(ename, NoFactory::get()) && IsKept(ename, NoFactory::get(), MueLu::UserData))) {
518  return NoFactory::get();
519  }
520 
521  // Query factory manager
522  TEUCHOS_TEST_FOR_EXCEPTION(factoryManager_ == null, Exceptions::RuntimeError, "MueLu::Level("<< levelID_ << ")::GetFactory(" << ename << ", " << factory << "): No FactoryManager");
523  const FactoryBase* fac = factoryManager_->GetFactory(ename).get();
524  TEUCHOS_TEST_FOR_EXCEPTION(fac == NULL, Exceptions::RuntimeError, "MueLu::Level("<< levelID_ << ")::GetFactory(" << ename << ", " << factory << "): Default factory returned by FactoryManager cannot be NULL");
525  return fac;
526  }
527 
529 
530 } //namespace MueLu
531 
532 //TODO: Caps should not matter
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
virtual std::string description() const
Return a simple one-line description of this object.
Exception throws to report data dependency problems between factories.
Exception throws to report errors in the internal logical of the program.
Base class for factories (e.g., R, P, and A_coarse).
virtual void CallDeclareInput(Level &requestedLevel) const =0
int GetID() const
return unique factory id
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
const FactoryBase * GetFactory(const std::string &varname, const FactoryBase *factory) const
If input factory == NULL, returns the default factory. Else, return input factory.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
RCP< Level > Build()
Definition: MueLu_Level.cpp:54
std::string description() const
Return a simple one-line description of this object.
static RequestMode requestMode_
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
int CountRequestedFactory(const FactoryBase *factory) const
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
Definition: MueLu_Level.cpp:96
void SetLevelID(int levelID)
Set level number.
Definition: MueLu_Level.cpp:78
void print(std::ostream &out, const VerbLevel verbLevel=Default) const
Printing method.
RCP< Level > previousLevel_
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:76
void Clear()
Delete all data that have been retained after the setup phase using Final flag.
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
void ExpertClear()
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void DeclareDependencies(const FactoryBase *factory, bool bRequestOnly=false, bool bReleaseOnly=false)
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput() to declare factory depe...
bool IsRequestedFactory(const FactoryBase *factory) const
KeepType GetKeepFlag(const std::string &ename, const FactoryBase *factory) const
Get the flag combination set for variable 'ename' generated by 'factory'.
RCP< const FactoryManagerBase > factoryManager_
bool IsKept(const std::string &ename, const FactoryBase *factory, KeepType keep) const
bool IsAvailableFactory(const FactoryBase *factory) const
int NumRequests(const FactoryBase *factory, const std::string &ename) const
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.
bool IsRequestedBy(const FactoryBase *factory, const std::string &ename, const FactoryBase *requestedBy) const
void SetPreviousLevel(const RCP< Level > &previousLevel)
Definition: MueLu_Level.cpp:85
void SetFactoryManager(const RCP< const FactoryManagerBase > &factoryManager)
Set default factories (used internally by Hierarchy::SetLevel()).
Definition: MueLu_Level.cpp:92
int levelID_
Map of a map (Key1 -> SubMap)
TwoKeyMap map_
bool IsKey(const FactoryBase *factory, const std::string &ename) const
Test whether some information about (ename, factory) are stored.
static const NoFactory * get()
Class that stores all relevant data for a variable.
std::map< const FactoryBase *, int > request_container
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Final
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
@ Keep
Always keep data, even accross run. This flag is set by Level::Keep(). This flag is propagated to coa...
@ NextRun
Both UserData and Keep flags force data to be kept and reused for the next run. Do not use MueLu::Nex...
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....
@ Debug
Print additional debugging information.
@ Errors
Errors.
@ Warnings1
Additional warnings.
short KeepType