MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_Level.cpp
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 #include <Teuchos_TabularOutputter.hpp>
11 
12 #include "MueLu_Level.hpp"
13 
15 
16 namespace MueLu {
17 
19  : lib_(Xpetra::NotSpecified)
20  , levelID_(-1) {}
21 
23  : lib_(Xpetra::UseTpetra)
24  , levelID_(-1)
25  , factoryManager_(factoryManager) {}
26 
27 Level::~Level() = default;
28 
30  RCP<Level> newLevel = rcp(new Level());
31 
32  // Copy 'keep' status of variables
33  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
34  const FactoryBase* factory = kt->first;
35 
36  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
37  const std::string& ename = it->first;
38 
39  if (IsKept(ename, factory, MueLu::Keep)) { // MueLu::Keep is the only flag propagated
40  if (factory == NULL) // TODO: Is this possible?? Throw exception. Not supposed to use the FactoryManager here.
41  newLevel->Keep(ename, NoFactory::get());
42  else
43  newLevel->Keep(ename, factory);
44  }
45  }
46  }
47 
48  return newLevel;
49 }
50 
51 int Level::GetLevelID() const { return levelID_; }
52 
53 void Level::SetLevelID(int levelID) {
54  if (levelID_ != -1 && levelID_ != levelID)
55  GetOStream(Warnings1) << "Level::SetLevelID(): Changing an already defined LevelID (previousID=" << levelID_ << ", newID=" << levelID << ")" << std::endl;
56 
57  levelID_ = levelID;
58 }
59 
61 
62 void Level::SetPreviousLevel(const RCP<Level>& previousLevel) {
63  if (previousLevel_ != Teuchos::null && previousLevel_ != previousLevel)
64  GetOStream(Warnings1) << "Level::SetPreviousLevel(): PreviousLevel was already defined" << std::endl;
65 
66  previousLevel_ = previousLevel;
67 }
68 
70  factoryManager_ = factoryManager;
71 }
72 
74  return factoryManager_;
75 }
76 
77 std::string Level::GetTypeName(const std::string& ename, const FactoryBase* factory) {
78  const FactoryBase* fac = GetFactory(ename, factory);
79  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(fac, ename), Exceptions::RuntimeError, "\"" + ename + "\" not found");
80 
82  "MueLu::Level::GetTypeString(): Data "
83  "\"" << ename
84  << "\" generated by " << *fac << " is not available.");
85 
86  return map_[fac][ename]->GetTypeName();
87 }
88 
89 void Level::Delete(const std::string& ename, const FactoryBase* factory) { // Note: do not add default value for input parameter 'factory'
90  if (!IsKey(factory, ename))
91  return;
92 
93  // Precondition:
94  // Delete() should only be called if counter == 0
95  // Note: It better to throw an exception rather than deleting the data if counter != 0 because users are not supposed to manipulate data with counter != 0
96  TEUCHOS_TEST_FOR_EXCEPTION(IsRequested(ename, factory) == true, Exceptions::RuntimeError, "MueLu::Level::Delete(): IsRequested() == true. Ref counter != 0. You are not allowed to delete data that are still in use.");
97  // If counter == 0 and entry exists, this means that a keep flag is set. Or there is an internal logic problem.
98  TEUCHOS_TEST_FOR_EXCEPTION(GetKeepFlag(ename, factory) == 0, Exceptions::RuntimeError, "MueLu::Level::Delete(), Keep flag == 0?");
99 
100  RemoveKeepFlag(ename, factory, MueLu::All); // will delete the data if counter == 0
101 
102  // Post condition: data must have been deleted
103  TEUCHOS_TEST_FOR_EXCEPTION(IsAvailable(ename, factory) == true, Exceptions::RuntimeError, "MueLu::Level::Delete(): Internal error (Post condition). Data have not been deleted.");
104 }
105 
106 void Level::AddKeepFlag(const std::string& ename, const FactoryBase* factory, KeepType keep) {
107  if (!IsKey(factory, ename)) {
108  // If the entry does not exist, create it to store the keep flag
110  map_[factory][ename] = newVar;
111  }
112  // Set the flag
113  map_[factory][ename]->AddKeepFlag(keep);
114 }
115 
116 void Level::RemoveKeepFlag(const std::string& ename, const FactoryBase* factory, KeepType keep) {
117  // No entry = nothing to do
118  if (!IsKey(factory, ename))
119  return;
120 
121  // Remove the flag
122  Teuchos::RCP<MueLu::VariableContainer>& v = map_[factory][ename];
123  v->RemoveKeepFlag(keep);
124 
125  // Remove data if no keep flag left and counter == 0
126  if ((v->IsRequested() == false) && (v->GetKeepFlag() == 0)) {
127  v = Teuchos::null; // free data
128 
129  map_[factory].erase(ename);
130  if (map_.count(factory) == 0)
131  map_.erase(factory);
132  }
133 }
134 
135 KeepType Level::GetKeepFlag(const std::string& ename, const FactoryBase* factory) const {
136  if (!IsKey(factory, ename))
137  return false;
138 
139  return Get(factory, ename)->GetKeepFlag();
140 }
141 
142 void Level::Request(const FactoryBase& factory) {
143  RequestMode prev = requestMode_;
145  factory.CallDeclareInput(*this);
146  requestMode_ = prev;
147 }
148 
149 void Level::Release(const FactoryBase& factory) {
150  RequestMode prev = requestMode_;
152  factory.CallDeclareInput(*this);
153  requestMode_ = prev;
154 }
155 
156 void Level::DeclareInput(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
157  if (requestMode_ == REQUEST) {
158  try {
159  Request(ename, factory, requestedBy);
160 
161  } catch (Exceptions::DependencyError& e) {
162  std::ostringstream msg;
163  msg << requestedBy->ShortClassName() << "::DeclareInput: (" << e.what() << ") unable to find or generate requested data \""
164  << ename << "\" with generating factory \"" << ((factory != NULL) ? factory->ShortClassName() : "null") << "\" [" << factory << "]";
165  msg << "\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  } catch (Exceptions::RuntimeError& e) {
170  std::ostringstream msg;
171  msg << e.what() << "\n during request for data \"" << std::setw(15) << ename << "\" on level " << GetLevelID()
172  << " by factory " << std::setw(25) << requestedBy->ShortClassName() << " [" << requestedBy << "]";
173  throw Exceptions::RuntimeError(msg.str());
174  }
175 
176  } else if (requestMode_ == RELEASE) {
177  Release(ename, factory, requestedBy);
178 
179  } else
180  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareInput(): requestMode_ undefined.");
181 }
182 
183 void Level::DeclareDependencies(const FactoryBase* factory, bool bRequestOnly, bool bReleaseOnly) { // TODO: replace bReleaseOnly, bReleaseOnly by one RequestMode enum
184  if (bRequestOnly && bReleaseOnly)
185  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareDependencies(): Both bRequestOnly and bReleaseOnly set to true makes no sense.");
186 
187  if (requestMode_ == REQUEST) {
188  if (bReleaseOnly == false) Request(*factory);
189 
190  } else if (requestMode_ == RELEASE) {
191  if (bRequestOnly == false) Release(*factory);
192 
193  } else
194  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::Level::DeclareDependencies(): requestMode_ undefined.");
195 }
196 
197 void Level::Request(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
198  const FactoryBase* fac = GetFactory(ename, factory);
199  // printf("(l=%d) [%43s] requesting \"%20s\" generated by %10p [actually, generated by %p (%43s)]\n",
200  // levelID_, requestedBy->description().c_str(), ename.c_str(), factory, fac, fac->description().c_str());
201 
202  // We request factory only if necessary, i.e.
203  // - factory has not been requested before, and
204  // - we need data which is not available
205  // Let us consider an RAP factory in the reuse scenario. The factory generates "A" (coarse matrix) and
206  // "RAP graph" (pattern of A). Typically, "A" has keep flag Final, which is cleared during next Setup, but
207  // "RAP graph" has flag Keep, which is not cleared as it is part of NextRun. Therefore, during next Setup
208  // we have RAP factory with available "RAP graph" but not available "A".
209  //
210  // During the regular construction phase, we will do a single request: ("A", RAPFactory). Suppose, we used
211  // bool test = (IsRequestedFactory(fac) == false && IsAvailable(fac) == false);
212  // This is incorrect, as IsAvailable(fac) checks whether there is *any* data generated by factory, which there is
213  // ("A"), and the dependencies of the factory would not be requested despite the need for them (we need fine A, P, and
214  // R to generate Ac even if we know sparsity pattern of Ac).
215  //
216  // On the other hand,
217  // bool test = (IsRequestedFactory(fac) == false && IsAvailable(ename, fac) == false);
218  // is correct as ("A", fac) is not available (only ("RAP graph", fac) is), and dependent factories would be
219  // properly requested.
220  //
221  // This way, factory is requested only once (because of the IsRequested(fac) check), and only when one of the needed
222  // pieces of data is not availble.
223  bool test = (IsRequestedFactory(fac) == false && IsAvailable(ename, fac) == false);
224 
225  // This request must be done before calling Request(*fac) to avoid circular dependency problems.
226  if (!IsKey(fac, ename)) {
228  map_[fac][ename] = newVar;
229  }
230 
232  v->Request(requestedBy);
233 
234  // The value of IsRequestedFactory(fac) is true, due to the above request.
235  // That is why a temporary boolean "test" is used!
236  TEUCHOS_TEST_FOR_EXCEPTION(IsRequestedFactory(fac) != true, Exceptions::RuntimeError, "Level::Request(ename, factory): internal logic error.");
237 
238  if (test) {
239  // Call Request for factory dependencies.
240  // We only do that if necessary, see comments above
241  Request(*fac);
242  }
243 }
244 
245 void Level::Release(const std::string& ename, const FactoryBase* factory, const FactoryBase* requestedBy) {
246  const FactoryBase* fac = GetFactory(ename, factory);
247  // printf("(l=%d) [%43s] releasing \"%20s\" generated by %10p [actually, generated by %p (%43s)]\n",
248  // levelID_, requestedBy->description().c_str(), ename.c_str(), factory, fac, fac->description().c_str());
249 
250  // Only a factory which has requested (fac,ename) is allowed to release it again.
251  // Do not release data if it has not been requested by the factory "requestedBy"
252  // Note: when data is released (fac,ename) depends on it often happened that some
253  // of this data has (recursively) been released too often
254  if (IsRequestedBy(fac, ename, requestedBy)) {
255  // In general all data (fac,ename) depends on is released when calling Get in generating factory (fac) Build method
256  // Here we check the need to release the dependencies of some data that has been requested (by factory "requestedBy")
257  // but the corresponding Build function of factory "fac" has never been called. Therefore the dependencies
258  // have never been released. Do it now.
259  if (CountRequestedFactory(fac) == 1 && // check if factory fac is not requested by another factory
260  IsAvailableFactory(fac) == false) { // check if Build function of factory fac has been called
261  Release(*fac);
262  }
263 
264  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(fac, ename), Exceptions::RuntimeError, "\"" + ename + "\" not found. Do a request first.");
265 
267  v->Release(requestedBy);
268 
269  // Remove data if no keep flag left and counter == 0
270  if ((v->IsRequested() == false) && (v->GetKeepFlag() == 0)) {
271  v = Teuchos::null; // free data
272 
273  map_[fac].erase(ename);
274  if (map_.count(fac) == 0)
275  map_.erase(fac);
276  }
277  }
278 }
279 
281 bool Level::IsAvailable(const std::string& ename, const FactoryBase* factory) const {
282  if (!IsKey(factory, ename))
283  return false;
284  try {
285  return Get(factory, ename)->IsAvailable();
286  } catch (...) {
287  return false;
288  }
289 }
290 
292 bool Level::IsRequested(const std::string& ename, const FactoryBase* factory) const {
293  if (!IsKey(factory, ename))
294  return false;
295  try {
296  return IsRequested(Get(factory, ename));
297  } catch (...) {
298  return false;
299  }
300 }
301 
302 void Level::Clear() {
303  // TODO: needs some love, ugly as it is
304  // The ugliness is the fact that we restart both loops when we remove a single element
305  bool wasRemoved;
306  do {
307  wasRemoved = false;
308  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
309  const FactoryBase* factory = kt->first;
310 
311  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
312  // We really want a reference here, but because later we'll need to check whether the
313  // key was removed, we should copy the value
314  const std::string ename = it->first;
315 
316  // We clear all the data that
317  // a) has not been requested
318  // b) is not being kept using NextRun (e.g., we clear out Final data)
319  if (!IsKept(ename, factory, MueLu::NextRun)) {
320  RemoveKeepFlag(ename, factory, MueLu::All); // will delete the data if counter == 0
321 
322  // To prevent infinite looping, we need to check whether we have
323  // actually removed the data. In buggy code it may happen that we
324  // were unable to do that, for instance, if the data was outstanding
325  // request
326  if (IsKey(factory, ename)) {
327  GetOStream(Errors) << "Level::Clear found Internal data inconsistency" << std::endl;
329 
330  throw Exceptions::RuntimeError("Level::Clear found Internal data inconsistency");
331  }
332 
333  wasRemoved = true;
334  break;
335  }
336  }
337 
338  if (wasRemoved)
339  break;
340  }
341 
342  } while (wasRemoved == true);
343 }
344 
346  TwoKeyMap::const_iterator kt = map_.begin();
347  while (kt != map_.end()) {
348  const FactoryBase* factory = kt->first;
349 
350  SubMap::const_iterator it = kt->second.begin();
351  while (it != kt->second.end()) {
352  const std::string& ename = it->first;
353 
354  // obtain variable container
355  Teuchos::RCP<MueLu::VariableContainer>& v = map_[factory][ename];
356 
357  if (v->GetKeepFlag() == 0 ||
358  v->IsKept(MueLu::UserData) == true ||
359  v->IsKept(MueLu::Final) == true) {
360  it++;
361  v = Teuchos::null; // free data
362  map_[factory].erase(ename);
363  if (map_.count(factory) == 0) {
364  break; // last occurrence for factory has been removed. proceed with next factory
365  }
366  } else
367  it++;
368  } // end for it
369 
370  if (map_.count(factory) == 0) {
371  kt++;
372  map_.erase(factory);
373  } else
374  kt++;
375  }
376 }
377 
378 std::string Level::description() const {
379  std::ostringstream out;
380  out << BaseClass::description();
381  out << "{ levelID = " << levelID_ << "}";
382  return out.str();
383 }
384 
385 void Level::print(std::ostream& out, const VerbLevel verbLevel) const {
386  if (!(verbLevel & Debug))
387  return;
388 
389  out << "LevelID = " << GetLevelID() << std::endl;
390 
391  typedef Teuchos::TabularOutputter TTO;
392  TTO outputter(out);
393  outputter.pushFieldSpec("data name", TTO::STRING, TTO::LEFT, TTO::GENERAL, 20);
394  outputter.pushFieldSpec("gen. factory addr.", TTO::STRING, TTO::LEFT, TTO::GENERAL, 40);
395  outputter.pushFieldSpec("req", TTO::INT, TTO::LEFT, TTO::GENERAL, 3);
396  outputter.pushFieldSpec("keep", TTO::STRING, TTO::LEFT, TTO::GENERAL, 5);
397  outputter.pushFieldSpec("type", TTO::STRING, TTO::LEFT, TTO::GENERAL, 18);
398  outputter.pushFieldSpec("data", TTO::STRING, TTO::LEFT, TTO::GENERAL, 14);
399  outputter.pushFieldSpec("req'd by", TTO::STRING, TTO::LEFT, TTO::GENERAL, 20);
400  outputter.outputHeader();
401 
402  for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
403  const FactoryBase* factory = kt->first;
404 
405  for (SubMap::const_iterator it = kt->second.begin(); it != kt->second.end(); it++) {
406  const std::string& ename = it->first;
407 
408  outputter.outputField(ename); // variable name
409 
410  // NOTE: We cannot dereference the factory pointer and call factory->description() as we do not know
411  // if the factory still exist (the factory pointer is a raw pointer by design). Instead, the level
412  // should store the factory description internally as a string for debugging purpose (and in debug mode only).
413  // // factory name
414  // std::stringstream ss1;
415  // ss1 << (*kt)->description();
416  // outputter.outputField((ss1.str()).substr(0,30));
417  if (factory == 0) {
418  outputter.outputField("Null");
419  } else if (factory == NoFactory::get()) {
420  outputter.outputField("NoFactory");
421  } else {
422  std::ostringstream oss;
423  oss << factory->ShortClassName() << "[" << factory->GetID() << "]";
424 #ifdef HAVE_MUELU_DEBUG
425  oss << "(" << factory << ")";
426 #endif
427  outputter.outputField(oss.str());
428  }
429 
430  int reqcount = NumRequests(factory, ename); // request counter
431  outputter.outputField(reqcount);
432 
433  KeepType keepType = GetKeepFlag(ename, factory);
434  if (keepType != 0) {
435  std::stringstream ss;
436  if (keepType & MueLu::UserData) {
437  ss << "User";
438  }
439  if (keepType & MueLu::Keep) {
440  ss << "Keep";
441  }
442  if (keepType & MueLu::Final) {
443  ss << "Final";
444  }
445  outputter.outputField(ss.str());
446  } else {
447  outputter.outputField("No");
448  }
449 
450  if (IsAvailable(ename, factory)) {
451  std::string strType = it->second->GetTypeName();
452 
453  if (strType == "int") {
454  outputter.outputField(strType);
455  outputter.outputField(it->second->GetData<int>());
456  } else if (strType == "double") {
457  outputter.outputField(strType);
458  outputter.outputField(it->second->GetData<double>());
459  } else if (strType == "string") {
460  outputter.outputField(strType);
461  outputter.outputField(it->second->GetData<std::string>());
462  } else {
463  size_t npos = std::string::npos;
464 
465  if (strType.find("MueLu::Aggregates") != npos)
466  outputter.outputField("Aggregates");
467  else if (strType.find("MueLu::AmalgamationInfo") != npos)
468  outputter.outputField("AmalgamationInfo");
469  else if (strType.find("MueLu::Constraint") != npos)
470  outputter.outputField("Constraint");
471  else if (strType.find("MueLu::SmootherBase") != npos)
472  outputter.outputField("SmootherBase");
473  else if (strType.find("MueLu::SmootherPrototype") != npos)
474  outputter.outputField("SmootherPrototype");
475  else if (strType.find("Xpetra::Export") != npos)
476  outputter.outputField("Export");
477  else if (strType.find("Xpetra::Import") != npos)
478  outputter.outputField("Import");
479  else if (strType.find("Xpetra::Map") != npos)
480  outputter.outputField("Map");
481  else if (strType.find("Xpetra::Matrix") != npos)
482  outputter.outputField("Matrix");
483  else if (strType.find("Xpetra::MultiVector") != npos)
484  outputter.outputField("Vector");
485  else if (strType.find("Xpetra::Operator") != npos)
486  outputter.outputField("Operator");
487  else
488  outputter.outputField(strType);
489 
490  outputter.outputField("available");
491  }
492 
493  } else {
494  outputter.outputField("unknown");
495  outputter.outputField("not available");
496  }
497 
498  typedef VariableContainer::request_container container_type;
499  const container_type& requestedBy = it->second->Requests();
500  std::ostringstream ss;
501  for (container_type::const_iterator ct = requestedBy.begin(); ct != requestedBy.end(); ct++) {
502  if (ct != requestedBy.begin()) ss << ",";
503  ss << ct->first->ShortClassName() << "[" << ct->first->GetID() << "]";
504 #ifdef HAVE_MUELU_DEBUG
505  ss << "(" << ct->first << ")";
506 #endif
507 
508  if (ct->second > 1) ss << "x" << ct->second;
509  }
510  outputter.outputField(ss.str());
511 
512  outputter.nextRow();
513  }
514  } // for (TwoKeyMap::const_iterator kt = map_.begin(); kt != map_.end(); kt++) {
515 }
516 
517 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
518 void Level::UpdateGraph(std::map<const FactoryBase*, BoostVertex>& vindices,
519  std::map<std::pair<BoostVertex, BoostVertex>, std::string>& edges,
520  BoostProperties& dp,
521  BoostGraph& graph) const {
522  size_t vind = vindices.size();
523 
524  for (TwoKeyMap::const_iterator it1 = map_.begin(); it1 != map_.end(); it1++) {
525  if (vindices.find(it1->first) == vindices.end()) {
526  BoostVertex boost_vertex = boost::add_vertex(graph);
527  std::ostringstream oss;
528  oss << it1->first->ShortClassName() << "[" << it1->first->GetID() << "]";
529  boost::put("label", dp, boost_vertex, oss.str());
530  vindices[it1->first] = vind++;
531  }
532 
533  for (SubMap::const_iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++) {
534  const VariableContainer::request_container& requests = it2->second->Requests();
535  for (VariableContainer::request_container::const_iterator rit = requests.begin(); rit != requests.end(); rit++) {
536  if (vindices.find(rit->first) == vindices.end()) {
537  // requested by factory which is unknown
538  BoostVertex boost_vertex = boost::add_vertex(graph);
539  std::ostringstream oss;
540  oss << rit->first->ShortClassName() << "[" << rit->first->GetID() << "]";
541  boost::put("label", dp, boost_vertex, oss.str());
542  vindices[rit->first] = vind++;
543  }
544 
545  edges[std::pair<BoostVertex, BoostVertex>(vindices[rit->first], vindices[it1->first])] = it2->first;
546  }
547  }
548  }
549 }
550 #endif
551 
552 // 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.
553 const FactoryBase* Level::GetFactory(const std::string& ename, const FactoryBase* factory) const {
554  if (factory != NULL)
555  return factory;
556 
557  // If IgnoreUserData == false and if variable "ename" generated by NoFactory is provided by the user (MueLu::UserData),
558  // use user-provided data by default without querying the FactoryManager.
559  // When FactoryManager == null, we consider that IgnoreUserData == false.
560  if ((factoryManager_ == Teuchos::null || factoryManager_->IgnoreUserData() == false) &&
561  (IsAvailable(ename, NoFactory::get()) && IsKept(ename, NoFactory::get(), MueLu::UserData))) {
562  return NoFactory::get();
563  }
564 
565  // Query factory manager
566  TEUCHOS_TEST_FOR_EXCEPTION(factoryManager_ == null, Exceptions::RuntimeError, "MueLu::Level(" << levelID_ << ")::GetFactory(" << ename << ", " << factory << "): No FactoryManager");
567  const FactoryBase* fac = factoryManager_->GetFactory(ename).get();
568  TEUCHOS_TEST_FOR_EXCEPTION(fac == NULL, Exceptions::RuntimeError, "MueLu::Level(" << levelID_ << ")::GetFactory(" << ename << ", " << factory << "): Default factory returned by FactoryManager cannot be NULL");
569  return fac;
570 }
571 
572 bool Level::IsKey(const FactoryBase* factory, const std::string& ename) const {
573  TwoKeyMap::const_iterator it = map_.find(factory);
574  return (it != map_.end()) ? (it->second).count(ename) : false;
575 }
576 
577 bool Level::IsAvailableFactory(const FactoryBase* factory) const {
578  TwoKeyMap::const_iterator it = map_.find(factory);
579  if (it == map_.end())
580  return false;
581  for (SubMap::const_iterator sit = it->second.begin(); sit != it->second.end(); sit++) {
582  if (sit->second->IsAvailable())
583  return true;
584  }
585  return false;
586 }
587 
588 bool Level::IsRequested(const Value& v) const {
589  TEUCHOS_TEST_FOR_EXCEPTION(v->NumAllRequests() == 0 && v->GetKeepFlag() == 0, Exceptions::RuntimeError,
590  "Internal logic error: if counter == 0, the entry in countTable_ should have been deleted");
591  return v->IsRequested();
592 }
593 
594 bool Level::IsRequestedBy(const FactoryBase* factory, const std::string& ename, const FactoryBase* requestedBy) const {
595  if (!IsKey(factory, ename))
596  return false;
597 
598  return IsRequestedBy(Get(factory, ename), requestedBy);
599 }
600 
601 bool Level::IsRequestedBy(const Value& v, const FactoryBase* requestedBy) const {
602  TEUCHOS_TEST_FOR_EXCEPTION(v->NumAllRequests() == 0 && v->GetKeepFlag() == 0, Exceptions::RuntimeError,
603  "Internal logic error: if counter == 0, the entry in countTable_ should have been deleted");
604  return v->IsRequested(requestedBy);
605 }
606 
607 bool Level::IsRequestedFactory(const FactoryBase* factory) const {
608  TwoKeyMap::const_iterator it = map_.find(factory);
609  if (it == map_.end())
610  return false;
611  for (SubMap::const_iterator sit = it->second.begin(); sit != it->second.end(); sit++)
612  if (IsRequested(sit->second))
613  return true;
614  return false;
615 }
616 
617 const RCP<VariableContainer>& Level::Get(const FactoryBase* factory, const std::string& ename) const {
618  TwoKeyMap::const_iterator it = map_.find(factory);
619  TEUCHOS_TEST_FOR_EXCEPTION(it == map_.end(), Exceptions::RuntimeError, "Key (" << factory << ", *) does not exist.");
620 
621  SubMap::const_iterator sit = it->second.find(ename);
622  TEUCHOS_TEST_FOR_EXCEPTION(sit == it->second.end(), Exceptions::RuntimeError, "Key (" << factory << ", " << ename << ") does not exist.");
623 
624  return sit->second;
625 }
626 
627 int Level::NumRequests(const FactoryBase* factory, const std::string& ename) const {
628  TEUCHOS_TEST_FOR_EXCEPTION(!IsKey(factory, ename), Exceptions::RuntimeError, "\"" + ename + "\" not found. Do a request first.");
629  const Teuchos::RCP<MueLu::VariableContainer>& v = Get(factory, ename);
631  "NumRequests(): Internal logic error: if counter == 0, the entry in countTable_ should have been deleted");
632  return v->NumAllRequests();
633 }
634 
635 int Level::CountRequestedFactory(const FactoryBase* factory) const {
636  TwoKeyMap::const_iterator it = map_.find(factory);
637  if (it == map_.end())
638  return 0;
639 
640  int cnt = 0;
641  for (SubMap::const_iterator sit = it->second.begin(); sit != it->second.end(); sit++)
642  cnt += sit->second->NumAllRequests();
643 
644  return cnt;
645 }
646 
648 
649 } // namespace MueLu
650 
651 // TODO: Caps should not matter
virtual void CallDeclareInput(Level &requestedLevel) const =0
virtual ~Level()
Destructor.
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;.
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.
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.
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.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
short KeepType
KeepType GetKeepFlag() const
Returns the keep flag combination.
TwoKeyMap map_
Print additional debugging information.
RCP< Level > previousLevel_
User data are always kept. This flag is set automatically when Level::Set(&quot;data&quot;, data) is used...
void RemoveKeepFlag(KeepType keep=UserData)
Removes a keep flag to the flag combination.
int GetID() const
return unique factory id
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
void Request(const FactoryBase *reqFactory)
Request data.
int CountRequestedFactory(const FactoryBase *factory) const
static const NoFactory * get()
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
Additional warnings.
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.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void ExpertClear()
bool IsKept(KeepType keep) const
Returns true if at least one keep flag is set.
static RequestMode requestMode_
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
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 Release(const FactoryBase *reqFactory)
Release data.
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.
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)
Both UserData and Keep flags force data to be kept and reused for the next run. Do not use MueLu::Nex...
bool IsAvailableFactory(const FactoryBase *factory) const
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.
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.
Class that stores all relevant data for a variable.
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.
int NumAllRequests() const
Returns the number of times the data has been requested.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
bool IsRequested(const FactoryBase *reqFactory) const
Returns true, if data is requested by reqFactory.
virtual std::string description() const
Return a simple one-line description of this object.
Exception throws to report data dependency problems between factories.
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.