Teko Version of the Day
Loading...
Searching...
No Matches
Teko_InverseLibrary.cpp
1// @HEADER
2// *****************************************************************************
3// Teko: A package for block and physics based preconditioning
4//
5// Copyright 2010 NTESS and the Teko contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#include "Teko_InverseLibrary.hpp"
11
12#include "Teko_SolveInverseFactory.hpp"
13#include "Teko_PreconditionerInverseFactory.hpp"
14#include "Teko_BlockPreconditionerFactory.hpp"
15
16#include "Teko_NeumannSeriesPreconditionerFactory.hpp"
17#include "Teuchos_AbstractFactoryStd.hpp"
18#include "Teko_Utilities.hpp"
19
20#include <algorithm>
21
22using Teuchos::RCP;
23using Teuchos::rcp;
24
25namespace Teko {
26
30void addToStratimikosBuilder(const RCP<Stratimikos::DefaultLinearSolverBuilder>& builder) {
31 typedef Thyra::PreconditionerFactoryBase<double> PrecFactory;
32
33 RCP<const Teuchos::ParameterList> parameters = builder->getValidParameters();
34
35 if (!parameters->sublist("Preconditioner Types").isSublist("Neumann Series")) {
36 RCP<const Teuchos::AbstractFactory<Thyra::PreconditionerFactoryBase<double> > > factory;
37
38 factory = Teuchos::abstractFactoryStd<PrecFactory,
39 Teko::NeumannSeriesPreconditionerFactory<double> >();
40 builder->setPreconditioningStrategyFactory(factory, "Neumann Series");
41 }
42}
43
44InverseLibrary::InverseLibrary() {
45 Teko_DEBUG_SCOPE("InverseLibrary::InverseLibrary", 10);
46
47 defaultBuilder_ = Teuchos::rcp(new Stratimikos::DefaultLinearSolverBuilder());
48 addToStratimikosBuilder(defaultBuilder_);
49
50 // setup some valid Stratimikos parameters
52
53 // set valid solve factory names
54 stratValidSolver_.push_back("Belos");
55 stratValidSolver_.push_back("Amesos");
56 stratValidSolver_.push_back("Amesos2");
57 stratValidSolver_.push_back("AztecOO");
58
59 // set valid preconditioner factory name
60 stratValidPrecond_.push_back("ML");
61 stratValidPrecond_.push_back("Ifpack");
62 stratValidPrecond_.push_back("Neumann Series");
63 stratValidPrecond_.push_back("MueLu");
64 stratValidPrecond_.push_back("Ifpack2");
65
66 // set valid Teko preconditioner factory names
68
69 Teko_DEBUG_MSG_BEGIN(10) DEBUG_STREAM << "Loaded \"block\" preconditioners = ";
70 for (std::size_t i = 0; i < blockValidPrecond_.size(); i++)
71 DEBUG_STREAM << blockValidPrecond_[i] << ", ";
72 DEBUG_STREAM << std::endl;
73 Teko_DEBUG_MSG_END()
74}
75
76InverseLibrary::InverseLibrary(const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder>& strat)
77 : defaultBuilder_(strat) {
78 Teko_DEBUG_SCOPE("InverseLibrary::InverseLibrary", 10);
79
80 RCP<Teuchos::ParameterList> pl =
81 rcp(new Teuchos::ParameterList(*defaultBuilder_->getValidParameters()));
82 Teuchos::ParameterList lst(pl->sublist("Linear Solver Types"));
83 Teuchos::ParameterList pft(pl->sublist("Preconditioner Types"));
84
85 Teuchos::ParameterList::ConstIterator itr;
86
87 // set valid solve factory names
88 for (itr = lst.begin(); itr != lst.end(); ++itr) stratValidSolver_.push_back(itr->first);
89
90 Teko_DEBUG_MSG_BEGIN(10) DEBUG_STREAM << "Loaded \"Stratimikos\" solvers = ";
91 for (std::size_t i = 0; i < stratValidSolver_.size(); i++)
92 DEBUG_STREAM << stratValidSolver_[i] << ", ";
93 DEBUG_STREAM << std::endl;
94 Teko_DEBUG_MSG_END()
95
96 // set valid prec factory names
97 for (itr = pft.begin(); itr != pft.end(); ++itr) stratValidPrecond_.push_back(itr->first);
98
99 Teko_DEBUG_MSG_BEGIN(10) DEBUG_STREAM << "Loaded \"Stratimikos\" preconditioners = ";
100 for (std::size_t i = 0; i < stratValidPrecond_.size(); i++)
101 DEBUG_STREAM << stratValidPrecond_[i] << ", ";
102 DEBUG_STREAM << std::endl;
103 Teko_DEBUG_MSG_END()
104
105 // set valid Teko preconditioner factory names
106 PreconditionerFactory::getPreconditionerFactoryNames(blockValidPrecond_);
107
108 Teko_DEBUG_MSG_BEGIN(10) DEBUG_STREAM << "Loaded \"block\" preconditioners = ";
109 for (std::size_t i = 0; i < blockValidPrecond_.size(); i++)
110 DEBUG_STREAM << blockValidPrecond_[i] << ", ";
111 DEBUG_STREAM << std::endl;
112 Teko_DEBUG_MSG_END()
113}
114
116void InverseLibrary::addInverse(const std::string& label, const Teuchos::ParameterList& pl) {
117 // strip out the label
118 const std::string type = pl.get<std::string>("Type");
119
120 // copy the parameter list so we can modify it
121 Teuchos::ParameterList settingsList;
122 settingsList.set(type, pl);
123 settingsList.sublist(type).remove("Type");
124
125 // is this a Stratimikos preconditioner or solver
126 if (std::find(stratValidPrecond_.begin(), stratValidPrecond_.end(), type) !=
127 stratValidPrecond_.end()) {
128 // this is a Stratimikos preconditioner factory
129 addStratPrecond(label, type, settingsList);
130 } else if (std::find(stratValidSolver_.begin(), stratValidSolver_.end(), type) !=
131 stratValidSolver_.end()) {
132 // this is a Stratimikos preconditioner factory
133 addStratSolver(label, type, settingsList);
134 } else if (std::find(blockValidPrecond_.begin(), blockValidPrecond_.end(), type) !=
135 blockValidPrecond_.end()) {
136 // this is a Teko preconditioner factory
137 addBlockPrecond(label, type, settingsList);
138 } else {
139 Teuchos::FancyOStream& os = *Teko::getOutputStream();
140 os << "ERROR: Could not find inverse type \"" << type << "\" required by inverse name \""
141 << label << "\"" << std::endl;
142 TEUCHOS_ASSERT(false);
143 }
144}
145
147void InverseLibrary::addStratSolver(const std::string& label, const std::string& type,
148 const Teuchos::ParameterList& pl) {
149 // add some additional parameters onto the list
150 RCP<Teuchos::ParameterList> stratList = rcp(new Teuchos::ParameterList());
151 stratList->set("Linear Solver Type", type);
152 stratList->set("Linear Solver Types", pl);
153 stratList->set("Preconditioner Type", "None");
154
155 stratSolver_[label] = stratList;
156}
157
159void InverseLibrary::addStratPrecond(const std::string& label, const std::string& type,
160 const Teuchos::ParameterList& pl) {
161 // add some additional parameters onto the list
162 RCP<Teuchos::ParameterList> stratList = rcp(new Teuchos::ParameterList());
163 stratList->set("Preconditioner Type", type);
164 stratList->set("Preconditioner Types", pl);
165
166 stratPrecond_[label] = stratList;
167}
168
170void InverseLibrary::addBlockPrecond(const std::string& label, const std::string& type,
171 const Teuchos::ParameterList& pl) {
172 // add some additional parameters onto the list
173 RCP<Teuchos::ParameterList> blockList = rcp(new Teuchos::ParameterList());
174 blockList->set("Preconditioner Type", type);
175 blockList->set("Preconditioner Settings", pl.sublist(type));
176
177 // add the Teko preconditioner parameter list into the library
178 blockPrecond_[label] = blockList;
179}
180
188Teuchos::RCP<const Teuchos::ParameterList> InverseLibrary::getParameterList(
189 const std::string& label) const {
190 std::map<std::string, RCP<const Teuchos::ParameterList> >::const_iterator itr;
191
192 // check preconditioners
193 itr = stratPrecond_.find(label);
194 if (itr != stratPrecond_.end()) return itr->second;
195
196 // check solvers
197 itr = stratSolver_.find(label);
198 if (itr != stratSolver_.end()) return itr->second;
199
200 // check solvers
201 itr = blockPrecond_.find(label);
202 if (itr != blockPrecond_.end()) return itr->second;
203
204 return Teuchos::null;
205}
206
208Teuchos::RCP<InverseFactory> InverseLibrary::getInverseFactory(const std::string& label) const {
209 Teko_DEBUG_SCOPE("InverseLibrary::getInverseFactory", 10);
210
211 std::map<std::string, RCP<const Teuchos::ParameterList> >::const_iterator itr;
212
213 bool isStratSolver = false, isStratPrecond = false, isBlockPrecond = false;
214
215 // is this a Stratimikos solver?
216 itr = stratPrecond_.find(label);
217 isStratPrecond = itr != stratPrecond_.end();
218
219 // is this a Stratimikos preconditioner?
220 if (not isStratPrecond) {
221 itr = stratSolver_.find(label);
222 isStratSolver = itr != stratSolver_.end();
223 }
224
225 // must be a "block" preconditioner
226 if (not(isStratSolver || isStratPrecond)) {
227 itr = blockPrecond_.find(label);
228 isBlockPrecond = itr != blockPrecond_.end();
229 }
230
231 Teko_DEBUG_MSG("Inverse \"" << label << "\" is of type "
232 << "strat prec = " << isStratPrecond << ", "
233 << "strat solv = " << isStratSolver << ", "
234 << "block prec = " << isBlockPrecond,
235 3);
236
237 // Must be one of Strat solver, strat preconditioner, block preconditioner
238 if (not(isStratSolver || isStratPrecond || isBlockPrecond)) {
239 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
240
241 *out << "InverseLibrary::getInverseFactory could not find \"" << label << "\" ... aborting\n";
242 *out << "Choose one of: " << std::endl;
243
244 *out << " Stratimikos preconditioners = ";
245 for (itr = stratPrecond_.begin(); itr != stratPrecond_.end(); ++itr)
246 *out << " \"" << itr->first << "\"\n";
247 *out << std::endl;
248
249 *out << " Stratimikos solvers = ";
250 for (itr = stratSolver_.begin(); itr != stratSolver_.end(); ++itr)
251 *out << " \"" << itr->first << "\"\n";
252 *out << std::endl;
253
254 *out << " Block preconditioners = ";
255 for (itr = blockPrecond_.begin(); itr != blockPrecond_.end(); ++itr)
256 *out << " \"" << itr->first << "\"\n";
257 *out << std::endl;
258
259 TEUCHOS_ASSERT(isStratSolver || isStratPrecond || isBlockPrecond);
260 }
261
262 RCP<const Teuchos::ParameterList> pl = itr->second;
263
264 // build inverse factory
265 if (isStratPrecond) {
266 // remove required parameters
267 RCP<Teuchos::ParameterList> plCopy = rcp(new Teuchos::ParameterList(*pl));
268 std::string type = plCopy->get<std::string>("Preconditioner Type");
269 RCP<Teuchos::ParameterList> xtraParams;
270 if (plCopy->sublist("Preconditioner Types").sublist(type).isParameter("Required Parameters")) {
271 xtraParams = rcp(new Teuchos::ParameterList(
272 plCopy->sublist("Preconditioner Types").sublist(type).sublist("Required Parameters")));
273 plCopy->sublist("Preconditioner Types").sublist(type).remove("Required Parameters");
274 }
275
276 // print some debuggin info
277 Teko_DEBUG_MSG_BEGIN(10);
278 DEBUG_STREAM << "Printing parameter list: " << std::endl;
279 Teko_DEBUG_PUSHTAB();
280 plCopy->print(DEBUG_STREAM);
281 Teko_DEBUG_POPTAB();
282
283 if (xtraParams != Teuchos::null) {
284 DEBUG_STREAM << "Printing extra parameters: " << std::endl;
285 Teko_DEBUG_PUSHTAB();
286 xtraParams->print(DEBUG_STREAM);
287 Teko_DEBUG_POPTAB();
288 }
289 Teko_DEBUG_MSG_END();
290
291 // Stratimikos::DefaultLinearSolverBuilder strat;
292 // addToStratimikosBuilder(strat);
293 defaultBuilder_->setParameterList(plCopy);
294
295 // try to build a preconditioner factory
296 RCP<Thyra::PreconditionerFactoryBase<double> > precFact =
297 defaultBuilder_->createPreconditioningStrategy(type);
298
299 // string must map to a preconditioner
300 RCP<Teko::PreconditionerInverseFactory> precInvFact =
301 rcp(new PreconditionerInverseFactory(precFact, xtraParams, getRequestHandler()));
302 precInvFact->setupParameterListFromRequestHandler();
303 return precInvFact;
304 } else if (isStratSolver) {
305 RCP<Teuchos::ParameterList> solveList = rcp(new Teuchos::ParameterList(*pl));
306 std::string type = solveList->get<std::string>("Linear Solver Type");
307
308 // get preconditioner name, remove "Use Preconditioner" parameter
309 Teuchos::ParameterList& solveSettings = solveList->sublist("Linear Solver Types").sublist(type);
310 std::string precKeyWord = "Use Preconditioner";
311 std::string precName = "None";
312 if (solveSettings.isParameter(precKeyWord)) {
313 precName = solveSettings.get<std::string>(precKeyWord);
314 solveSettings.remove(precKeyWord);
315 }
316
317 // build Thyra preconditioner factory
318 RCP<Thyra::PreconditionerFactoryBase<double> > precFactory;
319 if (precName != "None") {
320 // we will manually set the preconditioner, so set this to null
321 solveList->set<std::string>("Preconditioner Type", "None");
322
323 // build inverse that preconditioner corresponds to
324 RCP<PreconditionerInverseFactory> precInvFactory =
325 Teuchos::rcp_dynamic_cast<PreconditionerInverseFactory>(getInverseFactory(precName));
326
327 // extract preconditioner factory from preconditioner _inverse_ factory
328 precFactory = precInvFactory->getPrecFactory();
329 }
330
331 // Stratimikos::DefaultLinearSolverBuilder strat;
332 // addToStratimikosBuilder(strat);
333 defaultBuilder_->setParameterList(solveList);
334
335 // try to build a solver factory
336 RCP<Thyra::LinearOpWithSolveFactoryBase<double> > solveFact =
337 defaultBuilder_->createLinearSolveStrategy(type);
338 if (precFactory != Teuchos::null) solveFact->setPreconditionerFactory(precFactory, precName);
339
340 // if its around, build a InverseFactory
341 return rcp(new SolveInverseFactory(solveFact));
342 } else if (isBlockPrecond) {
343 try {
344 std::string type = pl->get<std::string>("Preconditioner Type");
345 const Teuchos::ParameterList& settings = pl->sublist("Preconditioner Settings");
346
347 // build preconditioner factory from the string
348 RCP<PreconditionerFactory> precFact = PreconditionerFactory::buildPreconditionerFactory(
349 type, settings, Teuchos::rcpFromRef(*this));
350
351 TEUCHOS_ASSERT(precFact != Teuchos::null);
352
353 // return the inverse factory object
354 return rcp(new PreconditionerInverseFactory(precFact, getRequestHandler()));
355 } catch (std::exception& e) {
356 RCP<Teuchos::FancyOStream> out = Teko::getOutputStream();
357
358 *out << "Teko: \"getInverseFactory\" failed, Parameter List =\n";
359 pl->print(*out);
360
361 *out << "*** THROWN EXCEPTION ***\n";
362 *out << e.what() << std::endl;
363 *out << "************************\n";
364
365 throw e;
366 }
367 }
368
369 TEUCHOS_ASSERT(false);
370 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
371}
372
374void InverseLibrary::PrintAvailableInverses(std::ostream& os) const {
375 std::map<std::string, Teuchos::RCP<const Teuchos::ParameterList> >::const_iterator itr;
376
377 os << "Stratimikos Solvers: " << std::endl;
378 os << "********************************" << std::endl;
379 for (itr = stratSolver_.begin(); itr != stratSolver_.end(); ++itr) {
380 os << "name = \"" << itr->first << "\"" << std::endl;
381 itr->second->print(os);
382 os << std::endl;
383 }
384
385 os << "Stratimikos Preconditioners: " << std::endl;
386 os << "********************************" << std::endl;
387 for (itr = stratPrecond_.begin(); itr != stratPrecond_.end(); ++itr) {
388 os << "name = \"" << itr->first << "\"" << std::endl;
389 itr->second->print(os);
390 os << std::endl;
391 }
392
393 os << "Teko Preconditioners: " << std::endl;
394 os << "********************************" << std::endl;
395 for (itr = blockPrecond_.begin(); itr != blockPrecond_.end(); ++itr) {
396 os << "name = \"" << itr->first << "\"" << std::endl;
397 itr->second->print(os);
398 os << std::endl;
399 }
400}
401
411RCP<InverseLibrary> InverseLibrary::buildFromParameterList(const Teuchos::ParameterList& pl,
412 bool useStratDefaults) {
413 // build from Stratimikos or allocate a new inverse library
414 RCP<InverseLibrary> invLib;
415 if (useStratDefaults)
416 invLib = InverseLibrary::buildFromStratimikos();
417 else
418 invLib = rcp(new InverseLibrary());
419
420 // to convert the void* like entry
421 Teuchos::ParameterList* temp = 0;
422
423 // loop over all entries in parameter list
424 Teuchos::ParameterList::ConstIterator itr;
425 for (itr = pl.begin(); itr != pl.end(); ++itr) {
426 // get current entry
427 std::string label = itr->first;
428 Teuchos::ParameterList& list = itr->second.getValue(temp);
429
430 // add to library
431 invLib->addInverse(label, list);
432 }
433
434 return invLib;
435}
436
447RCP<InverseLibrary> InverseLibrary::buildFromParameterList(
448 const Teuchos::ParameterList& pl,
449 const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder>& strat) {
450 // if strat is set to null, use the defaults
451 if (strat == Teuchos::null) return buildFromParameterList(pl, true);
452
453 // build from Stratimikos or allocate a new inverse library
454 RCP<InverseLibrary> invLib = InverseLibrary::buildFromStratimikos(strat);
455
456 // to convert the void* like entry
457 Teuchos::ParameterList* temp = 0;
458
459 // loop over all entries in parameter list
460 Teuchos::ParameterList::ConstIterator itr;
461 for (itr = pl.begin(); itr != pl.end(); ++itr) {
462 // get current entry
463 std::string label = itr->first;
464 Teuchos::ParameterList& list = itr->second.getValue(temp);
465
466 // add to library
467 invLib->addInverse(label, list);
468 }
469
470 return invLib;
471}
472
481Teuchos::RCP<InverseLibrary> InverseLibrary::buildFromStratimikos() {
482 RCP<InverseLibrary> invLib = rcp(new InverseLibrary());
483
484 // get default inveres in Stratimikos
485 RCP<Stratimikos::DefaultLinearSolverBuilder> strat = invLib->defaultBuilder_;
486 RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList(*strat->getValidParameters()));
487 Teuchos::ParameterList lst(pl->sublist("Linear Solver Types"));
488 Teuchos::ParameterList pft(pl->sublist("Preconditioner Types"));
489
490 Teuchos::ParameterList::ConstIterator itr;
491 Teuchos::ParameterList* temp = 0;
492
493 // loop over all entries in solver list
494 for (itr = lst.begin(); itr != lst.end(); ++itr) {
495 // get current entry
496 std::string label = itr->first;
497 Teuchos::ParameterList& list = itr->second.getValue(temp);
498 list.set("Type", label);
499
500 // add to library
501 invLib->addInverse(label, list);
502 }
503
504 // loop over all entries in preconditioner list
505 for (itr = pft.begin(); itr != pft.end(); ++itr) {
506 // get current entry
507 std::string label = itr->first;
508 Teuchos::ParameterList& list = itr->second.getValue(temp);
509 list.set("Type", label);
510
511 // add to library
512 invLib->addInverse(label, list);
513 }
514
515 return invLib;
516}
517
527Teuchos::RCP<InverseLibrary> InverseLibrary::buildFromStratimikos(
528 const Stratimikos::DefaultLinearSolverBuilder& strat) {
529 RCP<InverseLibrary> invLib = rcp(new InverseLibrary());
530
531 // get default inveres in Stratimikos
532 RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList(*strat.getValidParameters()));
533 Teuchos::ParameterList lst(pl->sublist("Linear Solver Types"));
534 Teuchos::ParameterList pft(pl->sublist("Preconditioner Types"));
535
536 Teuchos::ParameterList::ConstIterator itr;
537 Teuchos::ParameterList* temp = 0;
538
539 // loop over all entries in solver list
540 for (itr = lst.begin(); itr != lst.end(); ++itr) {
541 // get current entry
542 std::string label = itr->first;
543 Teuchos::ParameterList& list = itr->second.getValue(temp);
544 list.set("Type", label);
545
546 // add to library
547 invLib->addInverse(label, list);
548 }
549
550 // loop over all entries in preconditioner list
551 for (itr = pft.begin(); itr != pft.end(); ++itr) {
552 // get current entry
553 std::string label = itr->first;
554 Teuchos::ParameterList& list = itr->second.getValue(temp);
555 list.set("Type", label);
556
557 // add to library
558 invLib->addInverse(label, list);
559 }
560
561 return invLib;
562}
563
573Teuchos::RCP<InverseLibrary> InverseLibrary::buildFromStratimikos(
574 const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder>& strat) {
575 RCP<InverseLibrary> invLib = rcp(new InverseLibrary(strat));
576
577 // get default inveres in Stratimikos
578 RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList(*strat->getValidParameters()));
579 Teuchos::ParameterList lst(pl->sublist("Linear Solver Types"));
580 Teuchos::ParameterList pft(pl->sublist("Preconditioner Types"));
581
582 Teuchos::ParameterList::ConstIterator itr;
583 Teuchos::ParameterList* temp = 0;
584
585 // loop over all entries in solver list
586 for (itr = lst.begin(); itr != lst.end(); ++itr) {
587 // get current entry
588 std::string label = itr->first;
589 Teuchos::ParameterList& list = itr->second.getValue(temp);
590 list.set("Type", label);
591
592 // add to library
593 invLib->addInverse(label, list);
594 }
595
596 // loop over all entries in preconditioner list
597 for (itr = pft.begin(); itr != pft.end(); ++itr) {
598 // get current entry
599 std::string label = itr->first;
600 Teuchos::ParameterList& list = itr->second.getValue(temp);
601 list.set("Type", label);
602
603 // add to library
604 invLib->addInverse(label, list);
605 }
606
607 return invLib;
608}
609
610} // end namespace Teko
static Teuchos::RCP< PreconditionerFactory > buildPreconditionerFactory(const std::string &name, const Teuchos::ParameterList &settings, const Teuchos::RCP< const InverseLibrary > &invLib=Teuchos::null)
Builder function for creating preconditioner factories (yes this is a factory factory).
static void getPreconditionerFactoryNames(std::vector< std::string > &names)
Get the names of the block preconditioner factories.
virtual Teuchos::RCP< RequestHandler > getRequestHandler() const =0
Get the request handler with pointers to the appropriate callbacks.