Stratimikos Version of the Day
Loading...
Searching...
No Matches
Stratimikos_LinearSolverBuilder_def.hpp
1// @HEADER
2// *****************************************************************************
3// Stratimikos: Thyra-based strategies for linear solvers
4//
5// Copyright 2006 NTESS and the Stratimikos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef STRATIMIKOS_LINEARSOLVERBUILDER_DEF_HPP
11#define STRATIMIKOS_LINEARSOLVERBUILDER_DEF_HPP
12
13//#define THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
14
15#include "Stratimikos_InternalConfig.h"
16#include "Thyra_DelayedLinearOpWithSolveFactory.hpp"
17#include "Teuchos_AbstractFactoryStd.hpp"
18#include "Teuchos_CommandLineProcessor.hpp"
19#include "Teuchos_XMLParameterListHelpers.hpp"
20#include "Teuchos_GlobalMPISession.hpp"
21
22#ifdef HAVE_STRATIMIKOS_AMESOS2
23# include "Thyra_Amesos2LinearOpWithSolveFactory.hpp"
24#endif
25#ifdef HAVE_STRATIMIKOS_BELOS
26# include "Thyra_BelosLinearOpWithSolveFactory.hpp"
27#endif
28#if defined(HAVE_STRATIMIKOS_IFPACK2) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
29# include "Thyra_Ifpack2PreconditionerFactory.hpp"
30# include "Tpetra_CrsMatrix.hpp"
31#endif
32
33
34namespace {
35
36
37const std::string LinearSolverType_name = "Linear Solver Type";
38const std::string LinearSolverTypes_name = "Linear Solver Types";
39const std::string PreconditionerType_name = "Preconditioner Type";
40const std::string PreconditionerTypes_name = "Preconditioner Types";
41const std::string None_name = "None";
42const std::string EnableDelayedSolverConstruction_name = "Enable Delayed Solver Construction";
43const bool EnableDelayedSolverConstruction_default = false;
44
45
46} // namespace
47
48
49namespace Stratimikos {
50
51
52// Constructors/Initializers/Accessors
53
54
55template<class Scalar>
57 const std::string &paramsXmlFileName_in,
58 const std::string &extraParamsXmlString_in,
59 const std::string &paramsUsedXmlOutFileName_in,
60 const std::string &paramsXmlFileNameOption_in,
61 const std::string &extraParamsXmlStringOption_in,
62 const std::string &paramsUsedXmlOutFileNameOption_in,
63 const bool &replaceDuplicateFactories_in
64 )
65 :paramsXmlFileName_(paramsXmlFileName_in)
66 ,extraParamsXmlString_(extraParamsXmlString_in)
67 ,paramsUsedXmlOutFileName_(paramsUsedXmlOutFileName_in)
68 ,paramsXmlFileNameOption_(paramsXmlFileNameOption_in)
69 ,extraParamsXmlStringOption_(extraParamsXmlStringOption_in)
70 ,paramsUsedXmlOutFileNameOption_(paramsUsedXmlOutFileNameOption_in)
71 ,replaceDuplicateFactories_(replaceDuplicateFactories_in)
72 ,enableDelayedSolverConstruction_(EnableDelayedSolverConstruction_default)
73{
74 this->initializeDefaults();
75}
76
77
78template<class Scalar>
80{
81#ifdef TEUCHOS_DEBUG
82 // Validate that we read the parameters correctly!
83 if (nonnull(paramList_)) {
84 paramList_->validateParameters(*this->getValidParameters());
85 }
86#endif
87}
88
89
90template<class Scalar>
92 const RCP<const AbstractFactory<Thyra::LinearOpWithSolveFactoryBase<Scalar> > >
93 &solveStrategyFactory,
94 const std::string &solveStrategyName,
95 const bool makeDefault
96 )
97{
98 const int existingNameIdx =
99 this->getAndAssertExistingFactoryNameIdx("setLinearSolveStrategyFactory()",
100 validLowsfNames_(), solveStrategyName);
101 if (existingNameIdx >= 0) {
102 validLowsfNames_[existingNameIdx] = solveStrategyName;
103 lowsfArray_[existingNameIdx] = solveStrategyFactory;
104 }
105 else {
106 validLowsfNames_.push_back(solveStrategyName);
107 lowsfArray_.push_back(solveStrategyFactory);
108 }
109 validParamList_ = Teuchos::null;
110 if (makeDefault) {
111 setDefaultLinearSolveStrategyFactoryName(solveStrategyName);
112 }
113}
114
115
116template<class Scalar>
118 const std::string &solveStrategyName)
119{
120 defaultLOWSF_ = solveStrategyName;
121}
122
123
124template<class Scalar>
126 const RCP<const AbstractFactory<Thyra::PreconditionerFactoryBase<Scalar>>>
127 &precStrategyFactory,
128 const std::string &precStrategyName,
129 const bool makeDefault
130 )
131{
132 const int existingNameIdx =
133 this->getAndAssertExistingFactoryNameIdx("setPreconditioningStrategyFactory()",
134 validPfNames_(), precStrategyName);
135 if (existingNameIdx >= 0) {
136 validPfNames_[existingNameIdx] = precStrategyName;
137 pfArray_[existingNameIdx-1] = precStrategyFactory; // We offset by -1 since "None" is first!
138 }
139 else {
140 validPfNames_.push_back(precStrategyName);
141 pfArray_.push_back(precStrategyFactory);
142 }
143 validParamList_ = Teuchos::null;
144 if (makeDefault) {
145 setDefaultPreconditioningStrategyFactoryName(precStrategyName);
146 }
147}
148
149
150template<class Scalar>
152 const std::string &precStrategyName)
153{
154 defaultPF_ = precStrategyName;
155}
156
157
158template<class Scalar>
159void LinearSolverBuilder<Scalar>::setupCLP( Teuchos::CommandLineProcessor *clp )
160{
161 TEUCHOS_TEST_FOR_EXCEPT(clp==NULL);
162 clp->setOption(
163 paramsXmlFileNameOption().c_str(),&paramsXmlFileName_
164 ,"Name of an XML file containing parameters for linear solver "
165 "options to be appended first."
166 );
167 clp->setOption(
168 extraParamsXmlStringOption().c_str(),&extraParamsXmlString_
169 ,"An XML string containing linear solver parameters to be appended second."
170 );
171 clp->setOption(
172 paramsUsedXmlOutFileNameOption().c_str(),&paramsUsedXmlOutFileName_
173 ,"Name of an XML file that can be written with the parameter list after it "
174 "has been used on completion of this program."
175 );
176}
177
178
179template<class Scalar>
181{
182 using Teuchos::parameterList;
183 using Teuchos::ptr;
184 using Teuchos::updateParametersFromXmlFile;
185 using Teuchos::updateParametersFromXmlString;
186 using std::endl;
187
188 if (!paramList_.get()) {
189 paramList_ = parameterList("LinearSolverBuilder");
190 }
191 if (paramsXmlFileName().length()) {
192 if (out) {
193 *out << endl << "Reading parameters from XML file \""
194 << paramsXmlFileName() << "\" ..." << endl;
195 }
196 updateParametersFromXmlFile (paramsXmlFileName (), paramList_.ptr());
197 }
198 if (extraParamsXmlString().length()) {
199 if (out) {
200 *out << endl << "Appending extra parameters from the XML string \""
201 << extraParamsXmlString() << "\" ..." << endl;
202 }
203 updateParametersFromXmlString (extraParamsXmlString (), paramList_.ptr());
204 }
205 setParameterList(paramList_);
206}
207
208
209template<class Scalar>
211 const Thyra::LinearOpWithSolveFactoryBase<Scalar> &/* lowsFactory */,
212 const std::string &outputXmlFileName
213 ) const
214{
215 justInTimeInitialize();
216 const std::string xmlOutputFile =
217 ( outputXmlFileName.length() ? outputXmlFileName : paramsUsedXmlOutFileName() );
218 if (xmlOutputFile.length()) {
219 Teuchos::writeParameterListToXmlFile(*paramList_, xmlOutputFile);
220 }
221}
222
223
224template<class Scalar>
225std::string
227{
228 justInTimeInitialize();
229 return lowsfValidator_->getStringValue(*paramList_, LinearSolverType_name,
230 defaultLOWSF_);
231}
232
233
234template<class Scalar>
235std::string
237{
238 justInTimeInitialize();
239 return pfValidator_->getStringValue(*paramList_, PreconditionerType_name,
240 defaultPF_);
241}
242
243
244// Overridden from ParameterListAcceptor
245
246
247template<class Scalar>
249 RCP<Teuchos::ParameterList> const& paramList
250 )
251{
252 TEUCHOS_TEST_FOR_EXCEPT(is_null(paramList));
253 paramList->validateParameters(*this->getValidParameters());
254 paramList_ = paramList;
255 enableDelayedSolverConstruction_ = paramList_->get(
256 EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default );
257}
258
259
260template<class Scalar>
261RCP<Teuchos::ParameterList>
266
267
268template<class Scalar>
269RCP<Teuchos::ParameterList>
271{
272 RCP<Teuchos::ParameterList> _paramList = paramList_;
273 paramList_ = Teuchos::null;
274 return _paramList;
275}
276
277
278template<class Scalar>
279RCP<const Teuchos::ParameterList>
281{
282 return paramList_;
283}
284
285
286template<class Scalar>
287RCP<const Teuchos::ParameterList>
289{
290 using Teuchos::rcp_implicit_cast;
291 typedef Teuchos::ParameterEntryValidator PEV;
292 if (is_null(validParamList_)) {
293 RCP<Teuchos::ParameterList>
294 validParamList = Teuchos::rcp(new Teuchos::ParameterList);
295 // Linear Solver Types
296 lowsfValidator_ = Teuchos::rcp(
297 new Teuchos::StringToIntegralParameterEntryValidator<int>(
298 validLowsfNames_,LinearSolverType_name
299 )
300 );
301 validParamList->set(
302 LinearSolverType_name, defaultLOWSF_,
303 (std::string("Determines the type of linear solver that will be used.\n")
304 + "The parameters for each solver type are specified in the sublist \""
305 + LinearSolverTypes_name + "\"").c_str(),
306 rcp_implicit_cast<const PEV>(lowsfValidator_)
307 );
308 Teuchos::ParameterList &linearSolverTypesSL = validParamList->sublist(
309 LinearSolverTypes_name,false,
310 "Sublists for each of the linear solver types set using the parameter\n"
311 "\"" + LinearSolverType_name + "\". Note that the options for each\n"
312 "linear solver type given below will only be used if linear solvers\n"
313 "of that type are created. It is fine to list parameter sublists for\n"
314 "linear solver types that are not used."
315 );
316 for( int i = 0; i < static_cast<int>(lowsfArray_.size()); ++i ) {
317 const std::string
318 &lsname = validLowsfNames_[i];
319 const RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
320 lowsf = lowsfArray_[i]->create();
321 linearSolverTypesSL.sublist(lsname).setParameters(*lowsf->getValidParameters()
322 ).disableRecursiveValidation();
323 }
324 // Preconditioner Type
325 pfValidator_ = Teuchos::rcp(
326 new Teuchos::StringToIntegralParameterEntryValidator<int>(
327 validPfNames_, PreconditionerType_name ) );
328 validParamList->set(
329 PreconditionerType_name, defaultPF_,
330 (std::string("Determines the type of preconditioner that will be used.\n")
331 + "This option is only meaningful for linear solvers that accept preconditioner"
332 + " factory objects!\n"
333 + "The parameters for each preconditioner are specified in the sublist \""
334 + PreconditionerTypes_name + "\"").c_str(),
335 rcp_implicit_cast<const PEV>(pfValidator_)
336 );
337 Teuchos::ParameterList &precTypesSL = validParamList->sublist(
338 PreconditionerTypes_name,false,
339 "Sublists for each of the preconditioner types set using the parameter\n"
340 "\"" + PreconditionerType_name + "\". Note that the options for each\n"
341 "preconditioner type given below will only be used if preconditioners\n"
342 "of that type are created. It is fine to list parameter sublists for\n"
343 "preconditioner types that are not used."
344 );
345 for( int i = 0; i < static_cast<int>(pfArray_.size()); ++i ) {
346 const std::string
347 &pfname = validPfNames_[i+1]; // "None" is the 0th entry!
348 const RCP<Thyra::PreconditionerFactoryBase<Scalar> >
349 pf = pfArray_[i]->create();
350 precTypesSL.sublist(pfname).setParameters(*pf->getValidParameters()
351 ).disableRecursiveValidation();
352 }
353 //
354 validParamList->set(
355 EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default,
356 "When this option is set to true, the linear solver factory will be wrapped\n"
357 "in a delayed evaluation Decorator factory object. This results in a delay\n"
358 "in the creation of a linear solver (and the associated preconditioner) until\n"
359 "the first solve is actually performed. This helps in cases where it is not\n"
360 "known a-priori if a linear solve will be needed on a given linear operator and\n"
361 "therefore can significantly improve performance for some types of algorithms\n"
362 "such as NOX and LOCA."
363 );
364 //
365 validParamList_ = validParamList;
366 }
367 return validParamList_;
368}
369
370
371// Overridden from LinearSolverBuilderBase.
372
373
374template<class Scalar>
375RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
377 const std::string &linearSolveStrategyName
378 ) const
379{
380 justInTimeInitialize();
381
382 // Get the name of the linear solve strategy
383#ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
384 std::cout << "\nEntering LinearSolverBuilder"
385 << "::createLinearSolveStrategy(...) ...\n";
386 std::cout << "\nlinearSolveStrategyName = \""
387 << linearSolveStrategyName << "\"\n";
388 std::cout << "\nlinearSolveStrategyName.length() = "
389 << linearSolveStrategyName.length() << "\n";
390 std::cout << "\ndefaultLOWSF_ = \"" << defaultLOWSF_ << "\"\n";
391 std::cout << "\nthis->getLinearSolveStrategyName() = \""
392 << this->getLinearSolveStrategyName() << "\"\n";
393#endif
394 const std::string
395 lsname = ( linearSolveStrategyName.length()
396 ? linearSolveStrategyName
397 : this->getLinearSolveStrategyName() );
398#ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
399 std::cout << "\nlsname = \"" << lsname << "\"\n";
400#endif
401
402 // Get the index of this linear solver strategy (this will validate!)
403 const int
404 ls_idx = lowsfValidator_->getIntegralValue(lsname, LinearSolverType_name);
405
406 // Create the uninitialized LOWSFB object
407 RCP<Thyra::LinearOpWithSolveFactoryBase<Scalar> >
408 lowsf = lowsfArray_[ls_idx]->create();
409
410 // First, set the preconditioner factory and its parameters
411 if(lowsf->acceptsPreconditionerFactory()) {
412 const std::string &pfName = this->getPreconditionerStrategyName();
413 RCP<Thyra::PreconditionerFactoryBase<Scalar> >
414 pf = this->createPreconditioningStrategy(pfName);
415 if(pf.get())
416 lowsf->setPreconditionerFactory(pf,pfName);
417 }
418
419 // Now set the parameters for the linear solver (some of which might
420 // override some preconditioner factory parameters).
421 lowsf->setParameterList(
422 sublist(sublist(paramList_, LinearSolverTypes_name), lsname));
423 //
424 if (enableDelayedSolverConstruction_) {
425 return Teuchos::rcp(
426 new Thyra::DelayedLinearOpWithSolveFactory<Scalar>(lowsf)
427 );
428 }
429
430 return lowsf;
431
432}
433
434
435template<class Scalar>
436RCP<Thyra::PreconditionerFactoryBase<Scalar> >
438 const std::string &preconditioningStrategyName
439 ) const
440{
441 justInTimeInitialize();
442
443 // Get the name of the preconditioning strategy
444 const std::string
445 pfname = ( preconditioningStrategyName.length()
446 ? preconditioningStrategyName
447 : this->getPreconditionerStrategyName() );
448 RCP<Thyra::PreconditionerFactoryBase<Scalar> >
449 pf = Teuchos::null;
450
451 // Get the index of this preconditioning strategy (this will validate!)
452 const int
453 pf_idx = pfValidator_->getIntegralValue(pfname, PreconditionerType_name);
454 if( pf_idx != 0 ) {
455 pf = pfArray_[pf_idx-1]->create(); // We offset by -1 since "None" is first!
456 pf->setParameterList(
457 sublist(sublist(paramList_, PreconditionerTypes_name), pfname));
458 }
459
460 return pf;
461
462}
463
464
465// private
466
467template<class Scalar>
469{
470
471 using Teuchos::rcp;
472 using Teuchos::abstractFactoryStd;
473
474 defaultLOWSF_ = "";
475 defaultPF_ = None_name;
476 validLowsfNames_.resize(0);
477 validPfNames_.resize(0);
478 validPfNames_.push_back(None_name); // This will offset everything!
479
480 //
481 // Linear Solvers
482 //
483
484#ifdef HAVE_STRATIMIKOS_AMESOS2
485 setLinearSolveStrategyFactory(
486 abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<Scalar>,
487 Thyra::Amesos2LinearOpWithSolveFactory<Scalar>>(),
488 "Amesos2", true
489 );
490#endif
491
492#ifdef HAVE_STRATIMIKOS_BELOS
493 setLinearSolveStrategyFactory(
494 abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<Scalar>,
496 "Belos", true
497 );
498#endif
499
500 // Note: Above, the last LOWSF object set will be the default!
501 // (unless we have only one processor, see below:)
502
503#ifdef HAVE_STRATIMIKOS_AMESOS2
504 if (Teuchos::GlobalMPISession::getNProc() == 1) {
505 setDefaultLinearSolveStrategyFactoryName("Amesos2");
506 }
507#endif
508
509 //
510 // Preconditioners
511 //
512
513#if defined(HAVE_STRATIMIKOS_IFPACK2) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
514 setPreconditioningStrategyFactory(
515 abstractFactoryStd<Thyra::PreconditionerFactoryBase<Scalar>,
516 Thyra::Ifpack2PreconditionerFactory<Tpetra::CrsMatrix<Scalar>>>(),
517 "Ifpack2", true
518 );
519#endif
520
521 // Note: Above, the last PF object set will be the default!
522
523}
524
525
526template<class Scalar>
527void LinearSolverBuilder<Scalar>::justInTimeInitialize() const
528{
529 paramList_.assert_not_null();
530 if (is_null(validParamList_)) {
531 // Create the validators
532 this->getValidParameters();
533 }
534}
535
536
537template<class Scalar>
538int LinearSolverBuilder<Scalar>::getAndAssertExistingFactoryNameIdx(
539 const std::string &setFunctionName, const Teuchos::ArrayView<std::string> namesArray,
540 const std::string &name) const
541{
542 const int existingNameIdx =
543 LinearSolverBuilderHelpers::existingNameIndex(namesArray, name);
544 TEUCHOS_TEST_FOR_EXCEPTION(
545 (!replaceDuplicateFactories_ && existingNameIdx >= 0), std::logic_error,
546 "ERROR: "<<setFunctionName<<": the name='"<<name<<"' already exists"
547 << " at index="<<existingNameIdx<<"!\n"
548 << "\n"
549 << "TIP: To allow duplicates, change the property replaceDuplicateFactories from"
550 << " false to true by calling <thisObject>.replaceDuplicateFactories(true)"
551 << " where <thisObject> is of type Stratimikos::LinearSolverBuilder<Scalar>!");
552 return existingNameIdx;
553}
554
555
556//
557// Explicit instantiation macro
558//
559// Must be expanded from within the Stratimikos namespace!
560//
561
562
563#define STRATIMIKOS_LINEARSOLVERBUILDER_INSTANT(SCALAR) \
564 \
565 template class LinearSolverBuilder<SCALAR >;
566
567
568
569} // namespace Stratimikos
570
571#endif // STRATIMIKOS_LINEARSOLVERBUILDER_DEF_HPP
Concrete subclass of Thyra::LinearSolverBuilderBase for creating Thyra::LinearOpWithSolveFactoryBase ...
void setLinearSolveStrategyFactory(const RCP< const AbstractFactory< Thyra::LinearOpWithSolveFactoryBase< Scalar > > > &solveStrategyFactory, const std::string &solveStrategyName, const bool makeDefault=false)
Set a new linear solver strategy factory object.
RCP< Thyra::PreconditionerFactoryBase< Scalar > > createPreconditioningStrategy(const std::string &preconditioningStrategyName) const
RCP< const ParameterList > getParameterList() const
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.
RCP< const ParameterList > getValidParameters() const
LinearSolverBuilder(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", const bool &replaceDuplicateFactories=true)
Construct with default parameters.
RCP< Thyra::LinearOpWithSolveFactoryBase< Scalar > > createLinearSolveStrategy(const std::string &linearSolveStrategyName) const
std::string getPreconditionerStrategyName() const
Get the name of the preconditioner strategy that will be created on the next call to this->createPrec...
void setParameterList(RCP< ParameterList > const &paramList)
void setDefaultLinearSolveStrategyFactoryName(const std::string &solveStrategyName)
Set the default linear solver factory name.
void setupCLP(Teuchos::CommandLineProcessor *clp)
Setup the command-line processor to read in the needed data to extra the parameters from.
void readParameters(std::ostream *out)
Force the parameters to be read from a file and/or an extra XML string.
void setPreconditioningStrategyFactory(const RCP< const AbstractFactory< Thyra::PreconditionerFactoryBase< Scalar > > > &precStrategyFactory, const std::string &precStrategyName, const bool makeDefault=false)
Set a new preconditioner strategy factory object.
void writeParamsFile(const Thyra::LinearOpWithSolveFactoryBase< Scalar > &lowsFactory, const std::string &outputXmlFileName="") const
Write the parameters list for a LinearOpWithSolveFactoryBase object to a file after the parameters ar...
LinearOpWithSolveFactoryBase subclass implemented in terms of Belos.

Generated for Stratimikos by doxygen 1.9.8