MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_ML2MueLuParameterTranslator.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 
47 #include "MueLu_ConfigDefs.hpp"
48 #if defined(HAVE_MUELU_ML) && defined(HAVE_MUELU_EPETRA)
49 #include <ml_ValidateParameters.h>
50 #include <ml_MultiLevelPreconditioner.h> // for default values
51 #include <ml_RefMaxwell.h>
52 #endif
53 
55 
56 namespace MueLu {
57 
58 
59  std::string ML2MueLuParameterTranslator::GetSmootherFactory(const Teuchos::ParameterList& paramList, Teuchos::ParameterList& adaptingParamList, const std::string& pname, const std::string& value) {
60 
61  TEUCHOS_TEST_FOR_EXCEPTION(pname != "coarse: type" && pname != "coarse: list" && pname != "smoother: type" && pname.find("smoother: list",0) != 0,
63  "MueLu::MLParameterListInterpreter::Setup(): Only \"coarse: type\", \"smoother: type\" or \"smoother: list\" (\"coarse: list\") are "
64  "supported as ML parameters for transformation of smoother/solver parameters to MueLu");
65 
66  // string stream containing the smoother/solver xml parameters
67  std::stringstream mueluss;
68 
69  // Check whether we are dealing with coarse level (solver) parameters or level smoother parameters
70  std::string mode = "smoother:";
71  if (pname.find("coarse:", 0) == 0)
72  mode = "coarse:";
73 
74  // check whether pre and/or post smoothing
75  std::string PreOrPost = "both";
76  if (paramList.isParameter(mode + " pre or post"))
77  PreOrPost = paramList.get<std::string>(mode + " pre or post");
78 
79  TEUCHOS_TEST_FOR_EXCEPTION(mode == "coarse:" && PreOrPost != "both", Exceptions::RuntimeError,
80  "MueLu::MLParameterListInterpreter::Setup(): The parameter \"coarse: pre or post\" is not supported by MueLu. "
81  "It does not make sense for direct solvers. For iterative solvers you obtain the same effect by increasing, "
82  "e.g., the number of sweeps for the coarse grid smoother. Please remove it from your parameters.");
83 
84  // select smoother type
85  std::string valuestr = value; // temporary variable
86  std::transform(valuestr.begin(), valuestr.end(), valuestr.begin(), ::tolower);
87  if ( valuestr == "jacobi" || valuestr == "gauss-seidel" || valuestr == "symmetric gauss-seidel" ) {
88  std::string my_name;
89  if ( PreOrPost == "both" ) my_name = "\"" + pname + "\"";
90  else my_name = "\"smoother: " + PreOrPost + " type\"";
91  mueluss << "<Parameter name=" << my_name << " type=\"string\" value=\"RELAXATION\"/>" << std::endl;
92 
93  } else if ( valuestr == "ifpack" ) {
94  std::string my_name = "\"" + pname + "\"";
95  if ( paramList.isParameter("smoother: ifpack type") ) {
96  if ( paramList.get<std::string>("smoother: ifpack type") == "ILU" ) {
97  mueluss << "<Parameter name=" << my_name << " type=\"string\" value=\"ILU\"/>" << std::endl;
98  adaptingParamList.remove("smoother: ifpack type",false);
99  }
100  if ( paramList.get<std::string>("smoother: ifpack type") == "ILUT" ) {
101  mueluss << "<Parameter name=" << my_name << " type\" type=\"string\" value=\"ILUT\"/>" << std::endl;
102  adaptingParamList.remove("smoother: ifpack type",false);
103  }
104  }
105 
106  } else if ( valuestr == "chebyshev" ) {
107  std::string my_name = "\"" + pname + "\"";
108  mueluss << "<Parameter name=" << my_name << " type=\"string\" value=\"CHEBYSHEV\"/>" << std::endl;
109 
110  } else if (valuestr.length() > strlen("amesos") && valuestr.substr(0, strlen("amesos")) == "amesos") { /* catch Amesos-* */
111  std::string solverType = valuestr.substr(strlen("amesos")+1); /* ("amesos-klu" -> "klu") */
112 
113  bool valid = false;
114  const int validatorSize = 5;
115  std::string validator[validatorSize] = {"superlu", "superludist", "klu", "umfpack", "mumps"};
116  for (int i=0; i < validatorSize; i++)
117  if (validator[i] == solverType)
118  valid = true;
120  "MueLu::MLParameterListInterpreter: unknown smoother type. '" << solverType << "' not supported.");
121 
122  mueluss << "<Parameter name=\"" << pname << "\" type=\"string\" value=\"" << solverType << "\"/>" << std::endl;
123 
124  } else {
125  // TODO error message
126  std::cout << "error in " << __FILE__ << ":" << __LINE__ << " could not find valid smoother/solver" << std::endl;
127  }
128 
129  // set smoother: pre or post parameter
130  // Note that there is no "coarse: pre or post" in MueLu!
131  if ( paramList.isParameter("smoother: pre or post") && mode == "smoother:") {
132  //std::cout << "paramList" << paramList << std::endl;
133  //std::string smootherPreOrPost = paramList.get<std::string>("smoother: pre or post");
134  //std::cout << "Create pre or post parameter with " << smootherPreOrPost << std::endl;
135  mueluss << "<Parameter name=\"smoother: pre or post\" type=\"string\" value=\"" << PreOrPost << "\"/>" << std::endl;
136  adaptingParamList.remove("smoother: pre or post",false);
137  }
138 
139  // create smoother parameter list
140  if (PreOrPost != "both") {
141  mueluss << "<ParameterList name=\"smoother: " << PreOrPost << " params\">" << std::endl;
142  } else {
143  mueluss << "<ParameterList name=\"" << mode << " params\">" << std::endl;
144  }
145 
146  // relaxation based smoothers:
147 
148  if ( valuestr == "jacobi" || valuestr == "gauss-seidel" || valuestr == "symmetric gauss-seidel" ) {
149  if ( valuestr == "jacobi" ) { mueluss << "<Parameter name=\"relaxation: type\" type=\"string\" value=\"Jacobi\"/>" << std::endl; adaptingParamList.remove("relaxation: type",false); }
150  if ( valuestr == "gauss-seidel" ) { mueluss << "<Parameter name=\"relaxation: type\" type=\"string\" value=\"Gauss-Seidel\"/>" << std::endl; adaptingParamList.remove("relaxation: type",false); }
151  if ( valuestr == "symmetric gauss-seidel" ) { mueluss << "<Parameter name=\"relaxation: type\" type=\"string\" value=\"Symmetric Gauss-Seidel\"/>" << std::endl; adaptingParamList.remove("relaxation: type",false); }
152 
153  if ( paramList.isParameter("smoother: sweeps") ) { mueluss << "<Parameter name=\"relaxation: sweeps\" type=\"int\" value=\"" << paramList.get<int>("smoother: sweeps") << "\"/>" << std::endl; adaptingParamList.remove("smoother: sweeps",false); }
154  if ( paramList.isParameter("smoother: damping factor") ) { mueluss << "<Parameter name=\"relaxation: damping factor\" type=\"double\" value=\"" << paramList.get<double>("smoother: damping factor") << "\"/>" << std::endl; adaptingParamList.remove("smoother: damping factor",false); }
155  }
156 
157  // Chebyshev
158  if ( valuestr == "chebyshev") {
159  if ( paramList.isParameter("smoother: polynomial order") ) { mueluss << "<Parameter name=\"chebyshev: degree\" type=\"int\" value=\"" << paramList.get<int>("smoother: polynomial order") << "\"/>" << std::endl; adaptingParamList.remove("smoother: polynomial order",false); }
160  else { mueluss << "<Parameter name=\"chebyshev: degree\" type=\"int\" value=\"2\"/>" << std::endl; }
161  if ( paramList.isParameter("smoother: Chebyshev alpha") ) { mueluss << "<Parameter name=\"chebyshev: ratio eigenvalue\" type=\"double\" value=\"" << paramList.get<double>("smoother: Chebyshev alpha") << "\"/>" << std::endl; adaptingParamList.remove("smoother: Chebyshev alpha",false); }
162  else { mueluss << "<Parameter name=\"chebyshev: ratio eigenvalue\" type=\"double\" value=\"20\"/>" << std::endl; adaptingParamList.remove("smoother: Chebyshev alpha",false); }
163  }
164 
165  // parameters for ILU based preconditioners
166  if ( valuestr == "ifpack") {
167 
168  // add Ifpack parameters
169  if ( paramList.isParameter("smoother: ifpack overlap") ) { mueluss << "<Parameter name=\"partitioner: overlap\" type=\"int\" value=\"" << paramList.get<int>("smoother: ifpack overlap") << "\"/>" << std::endl; adaptingParamList.remove("smoother: ifpack overlap",false); }
170  if ( paramList.isParameter("smoother: ifpack level-of-fill") ) { mueluss << "<Parameter name=\"fact: level-of-fill\" type=\"int\" value=\"" << paramList.get<int>("smoother: ifpack level-of-fill") << "\"/>" << std::endl; adaptingParamList.remove("smoother: ifpack level-of-fill",false); }
171  if ( paramList.isParameter("smoother: ifpack absolute threshold") ) { mueluss << "<Parameter name=\"fact: absolute threshold\" type=\"int\" value=\"" << paramList.get<double>("smoother: ifpack absolute threshold") << "\"/>" << std::endl; adaptingParamList.remove("smoother: ifpack absolute threshold",false); }
172  if ( paramList.isParameter("smoother: ifpack relative threshold") ) { mueluss << "<Parameter name=\"fact: relative threshold\" type=\"int\" value=\"" << paramList.get<double>("smoother: ifpack relative threshold") << "\"/>" << std::endl; adaptingParamList.remove("smoother: ifpack relative threshold",false); }
173  }
174 
175  mueluss << "</ParameterList>" << std::endl;
176 
177  // max coarse level size parameter (outside of smoother parameter lists)
178  if ( paramList.isParameter("smoother: max size") ) {
179  mueluss << "<Parameter name=\"coarse: max size\" type=\"int\" value=\"" << paramList.get<int>("smoother: max size") << "\"/>" << std::endl; adaptingParamList.remove("smoother: max size",false);
180  }
181 
182  return mueluss.str();
183  }
184 
185  std::string ML2MueLuParameterTranslator::SetParameterList(const Teuchos::ParameterList & paramList_in, const std::string& defaultVals) {
186  Teuchos::ParameterList paramList = paramList_in;
187 
188  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout)); // TODO: use internal out (GetOStream())
189 
190 #if defined(HAVE_MUELU_ML) && defined(HAVE_MUELU_EPETRA)
191 
192  // TODO alternative with standard parameterlist from ML user guide?
193 
194  if (defaultVals != "") {
195  TEUCHOS_TEST_FOR_EXCEPTION(defaultVals!="SA" && defaultVals!="NSSA" && defaultVals!="refmaxwell", Exceptions::RuntimeError,
196  "MueLu::MLParameterListInterpreter: only \"SA\", \"NSSA\", and \"refmaxwell\" allowed as options for ML default parameters.");
197  Teuchos::ParameterList ML_defaultlist;
198  if (defaultVals == "refmaxwell")
199  ML_Epetra::SetDefaultsRefMaxwell(ML_defaultlist);
200  else
201  ML_Epetra::SetDefaults(defaultVals,ML_defaultlist);
202 
203  // merge user parameters with default parameters
204  MueLu::MergeParameterList(paramList_in, ML_defaultlist, true);
205  paramList = ML_defaultlist;
206  }
207 #else
208  if (defaultVals != "") {
209  // If no validator available: issue a warning and set parameter value to false in the output list
210  *out << "Warning: MueLu_ENABLE_ML=OFF and/or MueLu_ENABLE_Epetra=OFF. No ML default values available." << std::endl;
211  }
212 #endif // HAVE_MUELU_ML
213 
214  //
215  // Move smoothers/aggregation/coarse parameters to sublists
216  //
217 
218  // ML allows to have level-specific smoothers/aggregation/coarse parameters at the top level of the list or/and defined in sublists:
219  // See also: ML Guide section 6.4.1, MueLu::CreateSublists, ML_CreateSublists
220  ParameterList paramListWithSubList;
221  MueLu::CreateSublists(paramList, paramListWithSubList);
222  paramList = paramListWithSubList; // swap
223  Teuchos::ParameterList adaptingParamList = paramList; // copy of paramList which is used to removed already interpreted parameters
224 
225  //
226  // Validate parameter list
227  //
228  {
229  bool validate = paramList.get("ML validate parameter list", true); /* true = default in ML */
230  if (validate && defaultVals!="refmaxwell") {
231 
232 #if defined(HAVE_MUELU_ML) && defined(HAVE_MUELU_EPETRA)
233  // Validate parameter list using ML validator
234  int depth = paramList.get("ML validate depth", 5); /* 5 = default in ML */
235  TEUCHOS_TEST_FOR_EXCEPTION(! ML_Epetra::ValidateMLPParameters(paramList, depth), Exceptions::RuntimeError,
236  "ERROR: ML's Teuchos::ParameterList contains incorrect parameter!");
237 #else
238  // If no validator available: issue a warning and set parameter value to false in the output list
239  *out << "Warning: MueLu_ENABLE_ML=OFF and/or MueLu_ENABLE_Epetra=OFF. The parameter list cannot be validated." << std::endl;
240  paramList.set("ML validate parameter list", false);
241 
242 #endif // HAVE_MUELU_ML
243  } // if(validate)
244  } // scope
245 
246  // stringstream for concatenating xml parameter strings.
247  std::stringstream mueluss;
248 
249  // create surrounding MueLu parameter list
250  mueluss << "<ParameterList name=\"MueLu\">" << std::endl;
251 
252  // loop over all ML parameters in provided parameter list
253  for (ParameterList::ConstIterator param = paramListWithSubList.begin(); param != paramListWithSubList.end(); ++param) {
254 
255  // extract ML parameter name
256  const std::string & pname=paramListWithSubList.name(param);
257 
258  // extract corresponding (ML) value
259  // remove ParameterList specific information from result string
260  std::stringstream valuess;
261  valuess << paramList.entry(param);
262  std::string valuestr = valuess.str();
263  replaceAll(valuestr, "[unused]", "");
264  replaceAll(valuestr, "[default]", "");
265  valuestr = trim(valuestr);
266 
267  // transform ML parameter to corresponding MueLu parameter and generate XML string
268  std::string valueInterpreterStr = "\"" + valuestr + "\"";
269  std::string ret = MasterList::interpretParameterName(MasterList::ML2MueLu(pname),valueInterpreterStr);
270 
271  // add XML string
272  if (ret != "") {
273  mueluss << ret << std::endl;
274 
275  // remove parameter from ML parameter list
276  adaptingParamList.remove(pname,false);
277  }
278 
279  // special handling for energy minimization
280  // TAW: this is not optimal for symmetric problems but at least works.
281  // for symmetric problems the "energy minimization" parameter should not exist anyway...
282  if (pname == "energy minimization: enable") {
283  mueluss << "<Parameter name=\"problem: symmetric\" type=\"bool\" value=\"false\"/>" << std::endl;
284  mueluss << "<Parameter name=\"transpose: use implicit\" type=\"bool\" value=\"false\"/>" << std::endl;
285  }
286 
287  // special handling for smoothers
288  if (pname == "smoother: type") {
289 
290  mueluss << GetSmootherFactory(paramList, adaptingParamList, pname, valuestr);
291 
292  }
293 
294  // special handling for level-specific smoothers
295  if (pname.find("smoother: list (level",0) == 0) {
296  // Scan pname (ex: pname="smoother: type (level 2)")
297  std::string type, option;
298  int levelID=-1;
299  {
300  typedef Teuchos::ArrayRCP<char>::size_type size_type;
301  Teuchos::Array<char> ctype (size_type(pname.size()+1));
302  Teuchos::Array<char> coption(size_type(pname.size()+1));
303 
304  int matched = sscanf(pname.c_str(),"%s %[^(](level %d)", ctype.getRawPtr(), coption.getRawPtr(), &levelID); // use [^(] instead of %s to allow for strings with white-spaces (ex: "ifpack list")
305  type = std::string(ctype.getRawPtr());
306  option = std::string(coption.getRawPtr()); option.resize(option.size () - 1); // remove final white-space
307 
308  if (matched != 3 || (type != "smoother:")) {
309  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::CreateSublist(), Line " << __LINE__ << ". "
310  << "Error in creating level-specific sublists" << std::endl
311  << "Offending parameter: " << pname << std::endl);
312  }
313 
314  mueluss << "<ParameterList name=\"level " << levelID << "\">" << std::endl;
315  mueluss << GetSmootherFactory(paramList.sublist(pname),adaptingParamList.sublist(pname), "smoother: type", paramList.sublist(pname).get<std::string>("smoother: type"));
316  mueluss << "</ParameterList>" << std::endl;
317  }
318  }
319 
320  // special handling for coarse level
321  TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter("coarse: type"), Exceptions::RuntimeError, "MueLu::MLParameterListInterpreter::Setup(): The parameter \"coarse: type\" should not exist but being stored in \"coarse: list\" instead.");
322  if ( pname == "coarse: list" ) {
323 
324  // interpret smoother/coarse solver data.
325  // Note, that we inspect the "coarse: list" sublist to define the "coarse" smoother/solver
326  // Be aware, that MueLu::CreateSublists renames the prefix of the parameters in the "coarse: list" from "coarse" to "smoother".
327  // Therefore, we have to check the values of the "smoother" parameters
328  TEUCHOS_TEST_FOR_EXCEPTION(!paramList.sublist("coarse: list").isParameter("smoother: type"), Exceptions::RuntimeError, "MueLu::MLParameterListInterpreter::Setup(): no coarse grid solver defined.");
329  mueluss << GetSmootherFactory(paramList.sublist("coarse: list"), adaptingParamList.sublist("coarse: list"), "coarse: type", paramList.sublist("coarse: list").get<std::string>("smoother: type"));
330 
331 
332  }
333  } // for
334 
335  mueluss << "</ParameterList>" << std::endl;
336 
337  return mueluss.str();
338  }
339 
340 
341 } // namespace MueLu
static std::string SetParameterList(const Teuchos::ParameterList &paramList_in, const std::string &defaultVals)
: Interpret parameter list
const std::string & name() const
void MergeParameterList(const Teuchos::ParameterList &source, Teuchos::ParameterList &dest, bool overWrite)
: merge two parameter lists
ConstIterator end() const
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static std::string interpretParameterName(const std::string &name, const std::string &value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::string tolower(const std::string &str)
bool isParameter(const std::string &name) const
static std::string GetSmootherFactory(const Teuchos::ParameterList &paramList, Teuchos::ParameterList &adaptingParamList, const std::string &pname, const std::string &value)
: Helper function which translates ML smoother/solver paramters to MueLu XML string ...
void CreateSublists(const ParameterList &List, ParameterList &newList)
bool remove(std::string const &name, bool throwIfNotExists=true)
params_t::ConstIterator ConstIterator
ConstIterator begin() const
const ParameterEntry & entry(ConstIterator i) const
static std::string ML2MueLu(const std::string &name)
Translate ML parameter to corresponding MueLu parameter.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
Exception throws to report errors in the internal logical of the program.
void replaceAll(std::string &str, const std::string &from, const std::string &to)