Stratimikos  Version of the Day
Stratimikos_DefaultLinearSolverBuilder.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Stratimikos: Thyra-based strategies for linear solvers
5 // Copyright (2006) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 //#define THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
43 
44 #include "Stratimikos_InternalConfig.h"
45 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
46 #include "Thyra_DelayedLinearOpWithSolveFactory.hpp"
47 #include "Teuchos_AbstractFactoryStd.hpp"
48 #include "Teuchos_CommandLineProcessor.hpp"
49 #include "Teuchos_XMLParameterListHelpers.hpp"
50 #include "Teuchos_GlobalMPISession.hpp"
51 
52 #ifdef HAVE_STRATIMIKOS_AMESOS
53 # include "Thyra_AmesosLinearOpWithSolveFactory.hpp"
54 #endif
55 #if defined(HAVE_STRATIMIKOS_EPETRAEXT) && defined(HAVE_STRATIMIKOS_AZTECOO)
56 # include "Thyra_AztecOOLinearOpWithSolveFactory.hpp"
57 #endif
58 #ifdef HAVE_STRATIMIKOS_BELOS
59 # include "Thyra_BelosLinearOpWithSolveFactory.hpp"
60 #endif
61 #ifdef HAVE_STRATIMIKOS_IFPACK
62 # include "Thyra_IfpackPreconditionerFactory.hpp"
63 #endif
64 #ifdef HAVE_STRATIMIKOS_ML
65 # include "Thyra_MLPreconditionerFactory.hpp"
66 #endif
67 
68 
69 namespace {
70 
71 
72 const std::string LinearSolverType_name = "Linear Solver Type";
73 const std::string LinearSolverTypes_name = "Linear Solver Types";
74 const std::string PreconditionerType_name = "Preconditioner Type";
75 const std::string PreconditionerTypes_name = "Preconditioner Types";
76 const std::string None_name = "None";
77 const std::string EnableDelayedSolverConstruction_name = "Enable Delayed Solver Construction";
78 const bool EnableDelayedSolverConstruction_default = false;
79 
80 
81 } // namespace
82 
83 
84 namespace Stratimikos {
85 
86 
87 // Constructors/Initializers/Accessors
88 
89 
91  const std::string &paramsXmlFileName_in
92  ,const std::string &extraParamsXmlString_in
93  ,const std::string &paramsUsedXmlOutFileName_in
94  ,const std::string &paramsXmlFileNameOption_in
95  ,const std::string &extraParamsXmlStringOption_in
96  ,const std::string &paramsUsedXmlOutFileNameOption_in
97  )
98  :paramsXmlFileName_(paramsXmlFileName_in)
99  ,extraParamsXmlString_(extraParamsXmlString_in)
100  ,paramsUsedXmlOutFileName_(paramsUsedXmlOutFileName_in)
101  ,paramsXmlFileNameOption_(paramsXmlFileNameOption_in)
102  ,extraParamsXmlStringOption_(extraParamsXmlStringOption_in)
103  ,paramsUsedXmlOutFileNameOption_(paramsUsedXmlOutFileNameOption_in)
104  ,enableDelayedSolverConstruction_(EnableDelayedSolverConstruction_default)
105 {
106  this->initializeDefaults();
107 }
108 
109 
111 {
112 #ifdef TEUCHOS_DEBUG
113  // Validate that we read the parameters correctly!
114  if (nonnull(paramList_)) {
115  paramList_->validateParameters(*this->getValidParameters());
116  }
117 #endif
118 }
119 
120 
122  const RCP<const AbstractFactory<Thyra::LinearOpWithSolveFactoryBase<double> > >
123  &solveStrategyFactory,
124  const std::string &solveStrategyName,
125  const bool makeDefault
126  )
127 {
128  validLowsfNames_.push_back(solveStrategyName);
129  lowsfArray_.push_back(solveStrategyFactory);
130  validParamList_ = Teuchos::null;
131  if (makeDefault) {
132  setDefaultLinearSolveStrategyFactoryName(solveStrategyName);
133  }
134 }
135 
136 
138  const std::string &solveStrategyName)
139 {
140  defaultLOWSF_ = solveStrategyName;
141 }
142 
143 
145  const RCP<const AbstractFactory<Thyra::PreconditionerFactoryBase<double> > >
146  &precStrategyFactory,
147  const std::string &precStrategyName,
148  const bool makeDefault
149  )
150 {
151  validPfNames_.push_back(precStrategyName);
152  pfArray_.push_back(precStrategyFactory);
153  validParamList_ = Teuchos::null;
154  if (makeDefault) {
156  }
157 }
158 
159 
161  const std::string &precStrategyName)
162 {
163  defaultPF_ = precStrategyName;
164 }
165 
166 
167 void DefaultLinearSolverBuilder::setupCLP( Teuchos::CommandLineProcessor *clp )
168 {
169  TEUCHOS_TEST_FOR_EXCEPT(clp==NULL);
170  clp->setOption(
171  paramsXmlFileNameOption().c_str(),&paramsXmlFileName_
172  ,"Name of an XML file containing parameters for linear solver "
173  "options to be appended first."
174  );
175  clp->setOption(
176  extraParamsXmlStringOption().c_str(),&extraParamsXmlString_
177  ,"An XML string containing linear solver parameters to be appended second."
178  );
179  clp->setOption(
180  paramsUsedXmlOutFileNameOption().c_str(),&paramsUsedXmlOutFileName_
181  ,"Name of an XML file that can be written with the parameter list after it "
182  "has been used on completion of this program."
183  );
184 }
185 
186 
188 {
189  using Teuchos::parameterList;
190  using Teuchos::ptr;
191  using Teuchos::updateParametersFromXmlFile;
192  using Teuchos::updateParametersFromXmlString;
193  using std::endl;
194 
195  if (!paramList_.get()) {
196  paramList_ = parameterList("DefaultLinearSolverBuilder");
197  }
198  if (paramsXmlFileName().length()) {
199  if (out) {
200  *out << endl << "Reading parameters from XML file \""
201  << paramsXmlFileName() << "\" ..." << endl;
202  }
203  updateParametersFromXmlFile (paramsXmlFileName (), paramList_.ptr());
204  }
205  if (extraParamsXmlString().length()) {
206  if (out) {
207  *out << endl << "Appending extra parameters from the XML string \""
208  << extraParamsXmlString() << "\" ..." << endl;
209  }
210  updateParametersFromXmlString (extraParamsXmlString (), paramList_.ptr());
211  }
212  setParameterList(paramList_);
213 }
214 
215 
217  const Thyra::LinearOpWithSolveFactoryBase<double> &lowsFactory,
218  const std::string &outputXmlFileName
219  ) const
220 {
221  justInTimeInitialize();
222  const std::string xmlOutputFile =
223  ( outputXmlFileName.length() ? outputXmlFileName : paramsUsedXmlOutFileName() );
224  if (xmlOutputFile.length()) {
225  Teuchos::writeParameterListToXmlFile(*paramList_, xmlOutputFile);
226  }
227 }
228 
229 
230 std::string
232 {
233  justInTimeInitialize();
234  return lowsfValidator_->getStringValue(*paramList_, LinearSolverType_name,
235  defaultLOWSF_);
236 }
237 
238 
239 std::string
241 {
242  justInTimeInitialize();
243  return pfValidator_->getStringValue(*paramList_, PreconditionerType_name,
244  defaultPF_);
245 }
246 
247 
248 // Overridden from ParameterListAcceptor
249 
250 
252  RCP<Teuchos::ParameterList> const& paramList
253  )
254 {
255  TEUCHOS_TEST_FOR_EXCEPT(is_null(paramList));
256  paramList->validateParameters(*this->getValidParameters());
257  paramList_ = paramList;
258  enableDelayedSolverConstruction_ = paramList_->get(
259  EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default );
260 }
261 
262 
263 RCP<Teuchos::ParameterList>
265 {
266  return paramList_;
267 }
268 
269 
270 RCP<Teuchos::ParameterList>
272 {
273  RCP<Teuchos::ParameterList> _paramList = paramList_;
274  paramList_ = Teuchos::null;
275  return _paramList;
276 }
277 
278 
279 RCP<const Teuchos::ParameterList>
281 {
282  return paramList_;
283 }
284 
285 
286 RCP<const Teuchos::ParameterList>
288 {
289  using Teuchos::rcp_implicit_cast;
290  typedef Teuchos::ParameterEntryValidator PEV;
291  if (is_null(validParamList_)) {
292  RCP<Teuchos::ParameterList>
293  validParamList = Teuchos::rcp(new Teuchos::ParameterList);
294  // Linear Solver Types
295  lowsfValidator_ = Teuchos::rcp(
296  new Teuchos::StringToIntegralParameterEntryValidator<int>(
297  validLowsfNames_,LinearSolverType_name
298  )
299  );
300  validParamList->set(
301  LinearSolverType_name, defaultLOWSF_,
302  (std::string("Determines the type of linear solver that will be used.\n")
303  + "The parameters for each solver type are specified in the sublist \""
304  + LinearSolverTypes_name + "\"").c_str(),
305  rcp_implicit_cast<const PEV>(lowsfValidator_)
306  );
307  Teuchos::ParameterList &linearSolverTypesSL = validParamList->sublist(
308  LinearSolverTypes_name,false,
309  "Sublists for each of the linear solver types set using the parameter\n"
310  "\"" + LinearSolverType_name + "\". Note that the options for each\n"
311  "linear solver type given below will only be used if linear solvers\n"
312  "of that type are created. It is fine to list parameter sublists for\n"
313  "linear solver types that are not used."
314  );
315  for( int i = 0; i < static_cast<int>(lowsfArray_.size()); ++i ) {
316  const std::string
317  &lsname = validLowsfNames_[i];
318  const RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
319  lowsf = lowsfArray_[i]->create();
320  linearSolverTypesSL.sublist(lsname).setParameters(*lowsf->getValidParameters()
321  ).disableRecursiveValidation();
322  }
323  // Preconditioner Type
324  pfValidator_ = Teuchos::rcp(
325  new Teuchos::StringToIntegralParameterEntryValidator<int>(
326  validPfNames_, PreconditionerType_name ) );
327  validParamList->set(
328  PreconditionerType_name, defaultPF_,
329  (std::string("Determines the type of preconditioner that will be used.\n")
330  + "This option is only meaningful for linear solvers that accept preconditioner"
331  + " factory objects!\n"
332  + "The parameters for each preconditioner are specified in the sublist \""
333  + PreconditionerTypes_name + "\"").c_str(),
334  rcp_implicit_cast<const PEV>(pfValidator_)
335  );
336  Teuchos::ParameterList &precTypesSL = validParamList->sublist(
337  PreconditionerTypes_name,false,
338  "Sublists for each of the preconditioner types set using the parameter\n"
339  "\"" + PreconditionerType_name + "\". Note that the options for each\n"
340  "preconditioner type given below will only be used if preconditioners\n"
341  "of that type are created. It is fine to list parameter sublists for\n"
342  "preconditioner types that are not used."
343  );
344  for( int i = 0; i < static_cast<int>(pfArray_.size()); ++i ) {
345  const std::string
346  &pfname = validPfNames_[i+1]; // "None" is the 0th entry!
347  const RCP<Thyra::PreconditionerFactoryBase<double> >
348  pf = pfArray_[i]->create();
349  precTypesSL.sublist(pfname).setParameters(*pf->getValidParameters()
350  ).disableRecursiveValidation();
351  }
352  //
353  validParamList->set(
354  EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default,
355  "When this option is set to true, the linear solver factory will be wrapped\n"
356  "in a delayed evaluation Decorator factory object. This results in a delay\n"
357  "in the creation of a linear solver (and the associated preconditioner) until\n"
358  "the first solve is actually performed. This helps in cases where it is not\n"
359  "known a-priori if a linear solve will be needed on a given linear operator and\n"
360  "therefore can significantly improve performance for some types of algorithms\n"
361  "such as NOX and LOCA."
362  );
363  //
364  validParamList_ = validParamList;
365  }
366  return validParamList_;
367 }
368 
369 
370 // Overridden from LinearSolverBuilderBase.
371 
372 
373 RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
375  const std::string &linearSolveStrategyName
376  ) const
377 {
378  justInTimeInitialize();
379 
380  // Get the name of the linear solve strategy
381 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
382  std::cout << "\nEntering DefaultLinearSolverBuilder"
383  << "::createLinearSolveStrategy(...) ...\n";
384  std::cout << "\nlinearSolveStrategyName = \""
385  << linearSolveStrategyName << "\"\n";
386  std::cout << "\nlinearSolveStrategyName.length() = "
387  << linearSolveStrategyName.length() << "\n";
388  std::cout << "\ndefaultLOWSF_ = \"" << defaultLOWSF_ << "\"\n";
389  std::cout << "\nthis->getLinearSolveStrategyName() = \""
390  << this->getLinearSolveStrategyName() << "\"\n";
391 #endif
392  const std::string
393  lsname = ( linearSolveStrategyName.length()
394  ? linearSolveStrategyName
395  : this->getLinearSolveStrategyName() );
396 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
397  std::cout << "\nlsname = \"" << lsname << "\"\n";
398 #endif
399 
400  // Get the index of this linear solver strategy (this will validate!)
401  const int
402  ls_idx = lowsfValidator_->getIntegralValue(lsname, LinearSolverType_name);
403 
404  // Create the uninitialized LOWSFB object
405  RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
406  lowsf = lowsfArray_[ls_idx]->create();
407 
408  // First, set the preconditioner factory and its parameters
409  if(lowsf->acceptsPreconditionerFactory()) {
410  const std::string &pfName = this->getPreconditionerStrategyName();
411  RCP<Thyra::PreconditionerFactoryBase<double> >
412  pf = this->createPreconditioningStrategy(pfName);
413  if(pf.get())
414  lowsf->setPreconditionerFactory(pf,pfName);
415  }
416 
417  // Now set the parameters for the linear solver (some of which might
418  // override some preconditioner factory parameters).
419  lowsf->setParameterList(
420  sublist(sublist(paramList_, LinearSolverTypes_name), lsname));
421  //
422  if (enableDelayedSolverConstruction_) {
423  return Teuchos::rcp(
424  new Thyra::DelayedLinearOpWithSolveFactory<double>(lowsf)
425  );
426  }
427 
428  return lowsf;
429 
430 }
431 
432 
433 RCP<Thyra::PreconditionerFactoryBase<double> >
435  const std::string &preconditioningStrategyName
436  ) const
437 {
438  justInTimeInitialize();
439 
440  // Get the name of the preconditioning strategy
441  const std::string
442  pfname = ( preconditioningStrategyName.length()
443  ? preconditioningStrategyName
444  : this->getPreconditionerStrategyName() );
445  RCP<Thyra::PreconditionerFactoryBase<double> >
446  pf = Teuchos::null;
447 
448  // Get the index of this preconditioning strategy (this will validate!)
449  const int
450  pf_idx = pfValidator_->getIntegralValue(pfname, PreconditionerType_name);
451  if( pf_idx != 0 ) {
452  pf = pfArray_[pf_idx-1]->create(); // We offset by -1 since "None" is first!
453  pf->setParameterList(
454  sublist(sublist(paramList_, PreconditionerTypes_name), pfname));
455  }
456 
457  return pf;
458 
459 }
460 
461 
462 // private
463 
464 
465 void DefaultLinearSolverBuilder::initializeDefaults()
466 {
467 
468  using Teuchos::rcp;
469  using Teuchos::abstractFactoryStd;
470 
471  defaultLOWSF_ = "";
472  defaultPF_ = None_name;
473  validLowsfNames_.resize(0);
474  validPfNames_.resize(0);
475  validPfNames_.push_back(None_name); // This will offset everything!
476 
477  //
478  // Linear Solvers
479  //
480 
481 #ifdef HAVE_STRATIMIKOS_BELOS
483  abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
485  "Belos", true
486  );
487 #endif
488 
489 #ifdef HAVE_STRATIMIKOS_AMESOS
491  abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
493  "Amesos", true
494  );
495 #endif
496 
497 #if defined(HAVE_STRATIMIKOS_EPETRAEXT) && defined(HAVE_STRATIMIKOS_AZTECOO)
499  abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
501  "AztecOO", true
502  );
503 #endif
504 
505 #ifdef HAVE_STRATIMIKOS_AMESOS
506  if (Teuchos::GlobalMPISession::getNProc() == 1) {
508  }
509 #endif
510 
511  // Note: ABove, the last LOWSF object set will be the default unless we are
512  // on multiple processors!
513 
514  //
515  // Preconditioners
516  //
517 
518 #ifdef HAVE_STRATIMIKOS_ML
520  abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
522  "ML", true
523  );
524 #endif
525 
526 #ifdef HAVE_STRATIMIKOS_IFPACK
528  abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
530  "Ifpack", true
531  );
532 #endif
533 
534  // Note: Above, the last PF object set will be the default!
535 
536 }
537 
538 
539 void DefaultLinearSolverBuilder::justInTimeInitialize() const
540 {
541  paramList_.assert_not_null();
542  if (is_null(validParamList_)) {
543  // Create the validators
544  this->getValidParameters();
545  }
546 }
547 
548 
549 
550 } // namespace Stratimikos
Concrete LinearOpWithSolveFactoryBase adapter subclass that uses Amesos direct solvers.
RCP< Thyra::PreconditionerFactoryBase< double > > createPreconditioningStrategy(const std::string &preconditioningStrategyName) const
void setPreconditioningStrategyFactory(const RCP< const AbstractFactory< Thyra::PreconditionerFactoryBase< double > > > &precStrategyFactory, const std::string &precStrategyName, const bool makeDefault=false)
Set a new preconditioner strategy factory object.
Concrete preconditioner factory subclass based on Ifpack.
LinearOpWithSolveFactoryBase subclass implemented in terms of AztecOO.
void setupCLP(Teuchos::CommandLineProcessor *clp)
Setup the command-line processor to read in the needed data to extra the parameters from...
void setDefaultLinearSolveStrategyFactoryName(const std::string &solveStrategyName)
Set the default linear solver factory name.
RCP< Thyra::LinearOpWithSolveFactoryBase< double > > createLinearSolveStrategy(const std::string &linearSolveStrategyName) const
Concrete preconditioner factory subclass based on ML.
void setParameterList(RCP< ParameterList > const &paramList)
void readParameters(std::ostream *out)
Force the parameters to be read from a file and/or an extra XML string.
std::string getPreconditionerStrategyName() const
Get the name of the preconditioner strategy that will be created on the next call to this->createPrec...
LinearOpWithSolveFactoryBase subclass implemented in terms of Belos.
void writeParamsFile(const Thyra::LinearOpWithSolveFactoryBase< double > &lowsFactory, const std::string &outputXmlFileName="") const
Write the parameters list for a LinearOpWithSolveFactoryBase object to a file after the parameters ar...
DefaultLinearSolverBuilder(const std::string &paramsXmlFileName="", const std::string &extraParamsXmlString="", const std::string &paramsUsedXmlOutFileName="", const std::string &paramsXmlFileNameOption="linear-solver-params-file", const std::string &extraParamsXmlStringOption="extra-linear-solver-params", const std::string &paramsUsedXmlOutFileNameOption="linear-solver-params-used-file")
Construct with default parameters.
void setLinearSolveStrategyFactory(const RCP< const AbstractFactory< Thyra::LinearOpWithSolveFactoryBase< double > > > &solveStrategyFactory, const std::string &solveStrategyName, const bool makeDefault=false)
Set a new linear solver strategy factory object.
std::string getLinearSolveStrategyName() const
Get the name of the linear solver strategy that will be created on the next call to this->createLinea...
void setDefaultPreconditioningStrategyFactoryName(const std::string &precStrategyName)
Set the default linear solver factory name.

Generated for Stratimikos by doxygen 1.8.14