MueLu  Version of the Day
MueLu_HierarchyUtils_def.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_HIERARCHYUTILS_DEF_HPP
47 #define MUELU_HIERARCHYUTILS_DEF_HPP
48 
49 #include "Teuchos_ScalarTraits.hpp"
50 
51 #include <Xpetra_Matrix.hpp>
52 #include <Xpetra_Operator.hpp>
53 
56 #include "MueLu_SmootherBase.hpp"
57 #include "MueLu_SmootherFactory.hpp"
58 #include "MueLu_FactoryManager.hpp"
59 
60 //TODO/FIXME: DeclareInput(, **this**) cannot be used here
61 #ifdef HAVE_MUELU_INTREPID2
62 #include "Kokkos_DynRankView.hpp"
63 #endif
64 
65 namespace MueLu {
66 
67 
68  // Adds the following non-serializable data (A,P,R,Nullspace,Coordinates) from level-specific sublist nonSerialList,
69  // calling AddNewLevel as appropriate.
70  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
72  typedef typename Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType,
73  LocalOrdinal, GlobalOrdinal, Node> realvaluedmultivector_type;
74 
75  for (ParameterList::ConstIterator nonSerialEntry = nonSerialList.begin(); nonSerialEntry != nonSerialList.end(); nonSerialEntry++) {
76  const std::string& levelName = nonSerialEntry->first;
77  // Check for match of the form "level X" where X is a positive integer
78  if (nonSerialList.isSublist(levelName) && levelName.find("level ") == 0 && levelName.size() > 6) {
79  int levelID = strtol(levelName.substr(6).c_str(), 0, 0);
80  if (levelID > 0)
81  {
82  // Do enough level adding so we can be sure to add the data to the right place
83  for (int i = H.GetNumLevels(); i <= levelID; i++)
84  H.AddNewLevel();
85  }
86  RCP<Level> level = H.GetLevel(levelID);
87 
88  RCP<FactoryManager> M = Teuchos::rcp_dynamic_cast<FactoryManager>(HM.GetFactoryManager(levelID));
89  TEUCHOS_TEST_FOR_EXCEPTION(M.is_null(), Exceptions::InvalidArgument, "MueLu::Utils::AddNonSerializableDataToHierarchy: cannot get FactoryManager");
90 
91  // Grab the level sublist & loop over parameters
92  const ParameterList& levelList = nonSerialList.sublist(levelName);
93  for (ParameterList::ConstIterator levelListEntry = levelList.begin(); levelListEntry != levelList.end(); levelListEntry++) {
94  const std::string& name = levelListEntry->first;
95  TEUCHOS_TEST_FOR_EXCEPTION(name != "A" && name != "P" && name != "R" && name != "K" && name != "M" && name != "Mdiag" &&
96  name != "Nullspace" && name != "Coordinates" && name != "pcoarsen: element to node map" &&
97  name != "Node Comm" && name != "DualNodeID2PrimalNodeID" && name != "Primal interface DOF map" &&
99  std::string("MueLu::Utils::AddNonSerializableDataToHierarchy: parameter list contains unknown data type(") + name + ")");
100 
101  if (name == "A") {
102  level->Set(name, Teuchos::getValue<RCP<Matrix > > (levelListEntry->second),NoFactory::get());
103  M->SetFactory(name, NoFactory::getRCP()); // TAW: not sure about this: be aware that this affects all levels
104  // However, A is accessible through NoFactory anyway, so it should
105  // be fine here.
106  }
107  else if(name == "P" || name == "R" || name == "K" || name == "M") {
108  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
109  level->Set(name, Teuchos::getValue<RCP<Matrix > > (levelListEntry->second), NoFactory::get());
110  }
111  else if (name == "Mdiag")
112  {
113  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
114  level->Set(name, Teuchos::getValue<RCP<Vector > > (levelListEntry->second), NoFactory::get());
115  }
116  else if (name == "Nullspace")
117  {
118  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
119  level->Set(name, Teuchos::getValue<RCP<MultiVector > >(levelListEntry->second), NoFactory::get());
120  //M->SetFactory(name, NoFactory::getRCP()); // TAW: generally it is a bad idea to overwrite the factory manager data here
121  // One should do this only in very special cases
122  }
123  else if(name == "Coordinates") //Scalar of Coordinates MV is always double
124  {
125  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
126  level->Set(name, Teuchos::getValue<RCP<realvaluedmultivector_type> >(levelListEntry->second), NoFactory::get());
127  //M->SetFactory(name, NoFactory::getRCP()); // TAW: generally it is a bad idea to overwrite the factory manager data here
128  }
129  else if(name == "Node Comm")
130  {
131  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
132  level->Set(name, Teuchos::getValue<RCP<const Teuchos::Comm<int> > >(levelListEntry->second), NoFactory::get());
133  }
134  else if(name == "DualNodeID2PrimalNodeID")
135  {
136  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
137  level->Set(name, Teuchos::getValue<RCP<std::map<LO, LO>>>(levelListEntry->second), NoFactory::get());
138  }
139  else if(name == "Primal interface DOF map")
140  {
141  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
142  level->Set(name, Teuchos::getValue<RCP<const Map>>(levelListEntry->second), NoFactory::get());
143  }
144 #ifdef HAVE_MUELU_INTREPID2
145  else if (name == "pcoarsen: element to node map")
146  {
147  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
148  level->Set(name, Teuchos::getValue<RCP<Kokkos::DynRankView<LocalOrdinal,typename Node::device_type> > >(levelListEntry->second), NoFactory::get());
149  }
150 #endif
151  else
152 #ifdef HAVE_MUELU_MATLAB
153  {
154  //Custom variable for Muemex
155  size_t typeNameStart = name.find_first_not_of(' ');
156  size_t typeNameEnd = name.find(' ', typeNameStart);
157  std::string typeName = name.substr(typeNameStart, typeNameEnd - typeNameStart);
158  std::transform(typeName.begin(), typeName.end(), typeName.begin(), ::tolower);
159  level->AddKeepFlag(name, NoFactory::get(), MueLu::UserData);
160  if(typeName == "matrix")
161  level->Set(name, Teuchos::getValue<RCP<Matrix> >(levelListEntry->second), NoFactory::get());
162  else if(typeName == "multivector")
163  level->Set(name, Teuchos::getValue<RCP<MultiVector> >(levelListEntry->second), NoFactory::get());
164  else if(typeName == "map")
165  level->Set(name, Teuchos::getValue<RCP<Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > >(levelListEntry->second), NoFactory::get());
166  else if(typeName == "ordinalvector")
167  level->Set(name, Teuchos::getValue<RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node> > >(levelListEntry->second), NoFactory::get());
168  else if(typeName == "scalar")
169  level->Set(name, Teuchos::getValue<Scalar>(levelListEntry->second), NoFactory::get());
170  else if(typeName == "double")
171  level->Set(name, Teuchos::getValue<double>(levelListEntry->second), NoFactory::get());
172  else if(typeName == "complex")
173  level->Set(name, Teuchos::getValue<std::complex<double> >(levelListEntry->second), NoFactory::get());
174  else if(typeName == "int")
175  level->Set(name, Teuchos::getValue<int>(levelListEntry->second), NoFactory::get());
176  else if(typeName == "string")
177  level->Set(name, Teuchos::getValue<std::string>(levelListEntry->second), NoFactory::get());
178  }
179 #else
180  {
181  throw std::runtime_error("Invalid non-serializable data on list");
182  }
183 #endif
184  }
185  } else if (nonSerialList.isSublist(levelName) && levelName.find("user data") != std::string::npos) {
186  // So far only put data on level 0
187  int levelID = 0;
188  RCP<Level> level = H.GetLevel(levelID);
189 
190  RCP<FactoryManager> M = Teuchos::rcp_dynamic_cast<FactoryManager>(HM.GetFactoryManager(levelID));
191  TEUCHOS_TEST_FOR_EXCEPTION(M.is_null(), Exceptions::InvalidArgument, "MueLu::Utils::AddNonSerializableDataToHierarchy: cannot get FactoryManager");
192 
193  // Grab the user data sublist & loop over parameters
194  const ParameterList& userList = nonSerialList.sublist(levelName);
195  for (ParameterList::ConstIterator userListEntry = userList.begin(); userListEntry != userList.end(); userListEntry++) {
196  const std::string& name = userListEntry->first;
197  TEUCHOS_TEST_FOR_EXCEPTION(name != "P" && name != "R" && name != "K" && name != "M" && name != "Mdiag" &&
198  name != "Nullspace" && name != "Coordinates" && name != "pcoarsen: element to node map" &&
199  name != "Node Comm" && name != "DualNodeID2PrimalNodeID" && name != "Primal interface DOF map" &&
200  name != "output stream" &&
202  std::string("MueLu::Utils::AddNonSerializableDataToHierarchy: user data parameter list contains unknown data type (") + name + ")");
203  if( name == "P" || name == "R" || name == "K" || name == "M") {
204  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
205  level->Set(name, Teuchos::getValue<RCP<Matrix > > (userListEntry->second), NoFactory::get());
206  } else if (name == "Mdiag") {
207  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
208  level->Set(name, Teuchos::getValue<RCP<Vector > >(userListEntry->second), NoFactory::get());
209  } else if (name == "Nullspace") {
210  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
211  level->Set(name, Teuchos::getValue<RCP<MultiVector > >(userListEntry->second), NoFactory::get());
212  //M->SetFactory(name, NoFactory::getRCP()); // TAW: generally it is a bad idea to overwrite the factory manager data here
213  // One should do this only in very special cases
214  } else if(name == "Coordinates") {//Scalar of Coordinates MV is always double
215  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
216  level->Set(name, Teuchos::getValue<RCP<realvaluedmultivector_type> >(userListEntry->second), NoFactory::get());
217  level->print(std::cout, MueLu::VERB_EXTREME);
218  }
219  else if(name == "Node Comm") {
220  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
221  level->Set(name, Teuchos::getValue<RCP<const Teuchos::Comm<int> > >(userListEntry->second), NoFactory::get());
222  }
223  else if(name == "DualNodeID2PrimalNodeID")
224  {
225  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
226  level->Set(name, Teuchos::getValue<RCP<std::map<LO, LO>>>(userListEntry->second), NoFactory::get());
227  }
228  else if(name == "Primal interface DOF map")
229  {
230  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
231  level->Set(name, Teuchos::getValue<RCP<const Map>>(userListEntry->second), NoFactory::get());
232  }
233 #ifdef HAVE_MUELU_INTREPID2
234  else if (name == "pcoarsen: element to node map")
235  {
236  level->AddKeepFlag(name,NoFactory::get(),MueLu::UserData);
237  level->Set(name, Teuchos::getValue<RCP<Kokkos::DynRankView<LocalOrdinal,typename Node::device_type> > >(userListEntry->second), NoFactory::get());
238  }
239 #endif
240  else if (name == "output stream")
241  {
242  H.SetMueLuOStream(Teuchos::getValue<RCP<Teuchos::FancyOStream> >(userListEntry->second));
243  }
244  else {
245  //Custom variable
246  size_t typeNameStart = name.find_first_not_of(' ');
247  size_t typeNameEnd = name.find(' ', typeNameStart);
248  std::string typeName = name.substr(typeNameStart, typeNameEnd - typeNameStart);
249  size_t varNameStart = name.find_first_not_of(' ', typeNameEnd);
250  std::string varName = name.substr(varNameStart, name.size());
251  std::transform(typeName.begin(), typeName.end(), typeName.begin(), ::tolower);
252  level->AddKeepFlag(varName, NoFactory::get(), MueLu::UserData);
253  if(typeName == "matrix")
254  level->Set(varName, Teuchos::getValue<RCP<Matrix> >(userListEntry->second), NoFactory::get());
255  else if(typeName == "multivector")
256  level->Set(varName, Teuchos::getValue<RCP<MultiVector> >(userListEntry->second), NoFactory::get());
257  else if(typeName == "vector")
258  level->Set(varName, Teuchos::getValue<RCP<Vector> >(userListEntry->second), NoFactory::get());
259  else if(typeName == "map")
260  level->Set(varName, Teuchos::getValue<RCP<Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > >(userListEntry->second), NoFactory::get());
261  else if(typeName == "ordinalvector")
262  level->Set(varName, Teuchos::getValue<RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node> > >(userListEntry->second), NoFactory::get());
263  else if(typeName == "scalar")
264  level->Set(varName, Teuchos::getValue<Scalar>(userListEntry->second), NoFactory::get());
265  else if(typeName == "double")
266  level->Set(varName, Teuchos::getValue<double>(userListEntry->second), NoFactory::get());
267  else if(typeName == "complex")
268  level->Set(varName, Teuchos::getValue<std::complex<double> >(userListEntry->second), NoFactory::get());
269  else if(typeName == "int")
270  level->Set(varName, Teuchos::getValue<int>(userListEntry->second), NoFactory::get());
271  else if(typeName == "string")
272  level->Set(varName, Teuchos::getValue<std::string>(userListEntry->second), NoFactory::get());
273  else if(typeName == "array<go>")
274  level->Set(varName, Teuchos::getValue<Array<GlobalOrdinal> > (userListEntry->second), NoFactory::get());
275  else if(typeName == "array<lo>")
276  level->Set(varName, Teuchos::getValue<Array<LocalOrdinal> >(userListEntry->second), NoFactory::get());
277  else if(typeName == "arrayrcp<lo>")
278  level->Set(varName, Teuchos::getValue<ArrayRCP<LocalOrdinal> >(userListEntry->second), NoFactory::get());
279  else if(typeName == "arrayrcp<go>")
280  level->Set(varName, Teuchos::getValue<ArrayRCP<GlobalOrdinal> >(userListEntry->second), NoFactory::get());
281  else
282  throw std::runtime_error("Invalid non-serializable data on list");
283  }
284  }
285  }
286  }
287  }
288 } // namespace MueLu
289 
290 #define MUELU_HIERARCHY_UTILS_SHORT
291 #endif // MUELU_HIERARCHYHELPERS_DEF_HPP
This class specifies the default factory that should generate some data on a Level if the data does n...
MueLu::DefaultLocalOrdinal LocalOrdinal
RCP< Level > & GetLevel(const int levelID=0)
Retrieve a certain level from hierarchy.
static void AddNonSerializableDataToHierarchy(HierarchyManager &HM, Hierarchy &H, const ParameterList &nonSerialList)
Add non-serializable data to Hierarchy.
void AddNewLevel()
Add a new level at the end of the hierarchy.
User data are always kept. This flag is set automatically when Level::Set("data", data) is used...
std::string tolower(const std::string &str)
Namespace for MueLu classes and methods.
bool IsParamMuemexVariable(const std::string &name)
RCP< FactoryManagerBase > GetFactoryManager(int levelID) const
MueLu::DefaultNode Node
static const NoFactory * get()
MueLu::DefaultGlobalOrdinal GlobalOrdinal
static void SetMueLuOStream(const Teuchos::RCP< Teuchos::FancyOStream > &mueluOStream)
bool IsParamValidVariable(const std::string &name)
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
Exception throws to report invalid user entry.
static const RCP< const NoFactory > getRCP()
Static Get() functions.