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
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
63#endif
64
65namespace 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
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
MueLu::DefaultNode Node
Exception throws to report invalid user entry.
RCP< FactoryManagerBase > GetFactoryManager(int levelID) const
static void AddNonSerializableDataToHierarchy(HierarchyManager &HM, Hierarchy &H, const ParameterList &nonSerialList)
Add non-serializable data to Hierarchy.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
RCP< Level > & GetLevel(const int levelID=0)
Retrieve a certain level from hierarchy.
void AddNewLevel()
Add a new level at the end of the hierarchy.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
static const NoFactory * get()
static void SetMueLuOStream(const Teuchos::RCP< Teuchos::FancyOStream > &mueluOStream)
std::string tolower(const std::string &str)
Namespace for MueLu classes and methods.
bool IsParamMuemexVariable(const std::string &name)
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....
bool IsParamValidVariable(const std::string &name)