10 #include "Teko_StratimikosFactory.hpp"
12 #include "Teuchos_Time.hpp"
13 #include "Teuchos_AbstractFactoryStd.hpp"
15 #include "Thyra_DefaultPreconditioner.hpp"
17 #include "Teko_InverseLibrary.hpp"
18 #include "Teko_Preconditioner.hpp"
20 #include "Teko_InverseLibrary.hpp"
21 #include "Teko_ReorderedLinearOp.hpp"
23 #ifdef TEKO_HAVE_EPETRA
24 #include "Teko_InverseFactoryOperator.hpp"
25 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
26 #include "Teko_StridedEpetraOperator.hpp"
27 #include "Teko_BlockedEpetraOperator.hpp"
28 #include "Thyra_EpetraLinearOp.hpp"
29 #include "EpetraExt_RowMatrixOut.h"
34 using Teuchos::ParameterList;
40 class StratimikosFactoryPreconditioner :
public Thyra::DefaultPreconditioner<double> {
42 StratimikosFactoryPreconditioner() : iter_(0) {}
44 inline void incrIter() { iter_++; }
45 inline std::size_t getIter() {
return iter_; }
48 StratimikosFactoryPreconditioner(
const StratimikosFactoryPreconditioner &);
55 class TekoFactoryBuilder
56 :
public Teuchos::AbstractFactory<Thyra::PreconditionerFactoryBase<double> > {
58 TekoFactoryBuilder(
const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> &builder,
59 const Teuchos::RCP<Teko::RequestHandler> &rh)
60 : builder_(builder), requestHandler_(rh) {}
61 Teuchos::RCP<Thyra::PreconditionerFactoryBase<double> > create()
const {
62 return Teuchos::rcp(
new StratimikosFactory(builder_, requestHandler_));
66 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builder_;
67 Teuchos::RCP<Teko::RequestHandler> requestHandler_;
71 #ifdef TEKO_HAVE_EPETRA
75 : epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())) {}
79 : epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())) {
80 setRequestHandler(rh);
83 #endif // TEKO_HAVE_EPETRA
86 const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> &builder,
87 const Teuchos::RCP<Teko::RequestHandler> &rh)
89 #ifdef TEKO_HAVE_EPETRA
90 epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())),
93 setRequestHandler(rh);
98 const Thyra::LinearOpSourceBase<double> & )
const {
99 using Teuchos::outArg;
101 TEUCHOS_ASSERT(
false);
133 return Teuchos::rcp(
new StratimikosFactoryPreconditioner());
137 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
138 Thyra::PreconditionerBase<double> *prec,
const Thyra::ESupportSolveUse supportSolveUse)
const {
139 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
141 #ifdef TEKO_HAVE_EPETRA
142 if (epetraFwdOpViewExtractor_->isCompatible(*fwdOp))
143 initializePrec_Epetra(fwdOpSrc, prec, supportSolveUse);
150 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
151 Thyra::PreconditionerBase<double> *prec,
const Thyra::ESupportSolveUse
153 using Teuchos::implicit_cast;
156 using Teuchos::rcp_dynamic_cast;
157 using Thyra::LinearOpBase;
159 Teuchos::Time totalTimer(
""), timer(
"");
160 totalTimer.start(
true);
162 const RCP<Teuchos::FancyOStream> out = this->getOStream();
163 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
165 bool mediumVerbosity =
166 (out.get() && implicit_cast<
int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
168 Teuchos::OSTab tab(out);
170 *out <<
"\nEntering Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
172 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
175 StratimikosFactoryPreconditioner &defaultPrec =
176 Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
177 Teuchos::RCP<LinearOpBase<double> > prec_Op = defaultPrec.getNonconstUnspecifiedPrecOp();
180 const bool startingOver = (prec_Op == Teuchos::null);
183 invLib_ = Teuchos::null;
184 invFactory_ = Teuchos::null;
186 if (mediumVerbosity) *out <<
"\nCreating the initial Teko Operator object...\n";
191 invLib_ = Teko::InverseLibrary::buildFromParameterList(
192 paramList_->sublist(
"Inverse Factory Library"), builder_);
193 invLib_->setRequestHandler(reqHandler_);
196 invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>(
"Inverse Type"));
200 Teuchos::OSTab(out).o() <<
"> Creation time = " << timer.totalElapsedTime() <<
" sec\n";
203 if (mediumVerbosity) *out <<
"\nComputing the preconditioner ...\n";
206 std::string reorderType = paramList_->get<std::string>(
"Reorder Type");
207 if (reorderType !=
"") {
208 Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > blkFwdOp =
209 Teuchos::rcp_dynamic_cast<
const Thyra::BlockedLinearOpBase<double> >(fwdOp,
true);
211 Teko::LinearOp blockedFwdOp = Teko::buildReorderedLinearOp(*brm, blkFwdOp);
213 if (prec_Op == Teuchos::null) {
214 Teko::ModifiableLinearOp reorderedPrec =
Teko::buildInverse(*invFactory_, blockedFwdOp);
217 Teko::ModifiableLinearOp reorderedPrec =
223 if (prec_Op == Teuchos::null)
233 Teuchos::OSTab(out).o() <<
"=> Preconditioner construction time = " << timer.totalElapsedTime()
237 defaultPrec.initializeUnspecified(prec_Op);
238 defaultPrec.incrIter();
241 if (out.get() && implicit_cast<
int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
242 *out <<
"\nTotal time in Teko::StratimikosFactory = " << totalTimer.totalElapsedTime()
245 *out <<
"\nLeaving Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
248 #ifdef TEKO_HAVE_EPETRA
249 void StratimikosFactory::initializePrec_Epetra(
250 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
251 Thyra::PreconditionerBase<double> *prec,
const Thyra::ESupportSolveUse
253 using Teuchos::implicit_cast;
254 using Teuchos::outArg;
257 using Teuchos::rcp_dynamic_cast;
259 Teuchos::Time totalTimer(
""), timer(
"");
260 totalTimer.start(
true);
262 const RCP<Teuchos::FancyOStream> out = this->getOStream();
263 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
265 bool mediumVerbosity =
266 (out.get() && implicit_cast<
int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
268 Teuchos::OSTab tab(out);
270 *out <<
"\nEntering Teko::StratimikosFactory::initializePrec_Epetra(...) ...\n";
272 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
274 TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get() == NULL);
275 TEUCHOS_TEST_FOR_EXCEPT(prec == NULL);
281 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
282 Thyra::EOpTransp epetraFwdOpTransp;
283 Thyra::EApplyEpetraOpAs epetraFwdOpApplyAs;
284 Thyra::EAdjointEpetraOp epetraFwdOpAdjointSupport;
285 double epetraFwdOpScalar;
286 epetraFwdOpViewExtractor_->getEpetraOpView(
287 fwdOp, outArg(epetraFwdOp), outArg(epetraFwdOpTransp), outArg(epetraFwdOpApplyAs),
288 outArg(epetraFwdOpAdjointSupport), outArg(epetraFwdOpScalar));
290 StratimikosFactoryPreconditioner &defaultPrec =
291 Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
294 RCP<Thyra::EpetraLinearOp> epetra_precOp =
295 rcp_dynamic_cast<Thyra::EpetraLinearOp>(defaultPrec.getNonconstUnspecifiedPrecOp(),
true);
298 Teuchos::RCP<Teko::Epetra::InverseFactoryOperator> teko_precOp;
299 if (epetra_precOp != Teuchos::null)
304 const bool startingOver = (teko_precOp == Teuchos::null);
307 invLib_ = Teuchos::null;
308 invFactory_ = Teuchos::null;
312 *out <<
"\nCreating the initial Teko::Epetra::InverseFactoryOperator object...\n";
316 std::stringstream ss;
317 ss << paramList_->get<std::string>(
"Strided Blocking");
320 while (not ss.eof()) {
324 TEUCHOS_ASSERT(num > 0);
326 decomp_.push_back(num);
330 invLib_ = Teko::InverseLibrary::buildFromParameterList(
331 paramList_->sublist(
"Inverse Factory Library"), builder_);
332 invLib_->setRequestHandler(reqHandler_);
335 invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>(
"Inverse Type"));
342 Teuchos::OSTab(out).o() <<
"> Creation time = " << timer.totalElapsedTime() <<
" sec\n";
345 if (mediumVerbosity) *out <<
"\nComputing the preconditioner ...\n";
349 bool writeBlockOps = paramList_->get<
bool>(
"Write Block Operator");
351 teko_precOp->initInverse();
353 if (decomp_.size() == 1) {
354 teko_precOp->rebuildInverseOperator(epetraFwdOp);
358 std::stringstream ss;
359 ss <<
"block-" << defaultPrec.getIter() <<
"_00.mm";
360 EpetraExt::RowMatrixToMatrixMarketFile(
361 ss.str().c_str(), *rcp_dynamic_cast<
const Epetra_CrsMatrix>(epetraFwdOp));
364 Teuchos::RCP<Epetra_Operator> wrappedFwdOp =
365 buildWrappedEpetraOperator(epetraFwdOp, teko_precOp->getNonconstForwardOp(), *out);
369 std::stringstream ss;
370 ss <<
"block-" << defaultPrec.getIter();
373 Teuchos::RCP<Teko::Epetra::BlockedEpetraOperator> stridedJac =
375 if (stridedJac != Teuchos::null) {
379 TEUCHOS_ASSERT(
false);
382 teko_precOp->rebuildInverseOperator(wrappedFwdOp);
389 Teuchos::OSTab(out).o() <<
"=> Preconditioner construction time = " << timer.totalElapsedTime()
394 epetra_precOp = rcp(
new Thyra::EpetraLinearOp);
396 epetra_precOp->initialize(teko_precOp, epetraFwdOpTransp, Thyra::EPETRA_OP_APPLY_APPLY_INVERSE,
397 Thyra::EPETRA_OP_ADJOINT_UNSUPPORTED);
400 defaultPrec.initializeUnspecified(
401 Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp));
402 defaultPrec.incrIter();
405 if (out.get() && implicit_cast<
int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
406 *out <<
"\nTotal time in Teko::StratimikosFactory = " << totalTimer.totalElapsedTime()
408 if (mediumVerbosity) *out <<
"\nLeaving Teko::StratimikosFactory::initializePrec(...) ...\n";
410 #endif // TEKO_HAVE_EPETRA
413 Thyra::PreconditionerBase<double> * ,
414 Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > * ,
415 Thyra::ESupportSolveUse *
417 TEUCHOS_TEST_FOR_EXCEPT(
true);
423 TEUCHOS_TEST_FOR_EXCEPT(paramList.get() == NULL);
426 paramList_ = paramList;
434 Teuchos::RCP<ParameterList> _paramList = paramList_;
435 paramList_ = Teuchos::null;
444 using Teuchos::implicit_cast;
446 using Teuchos::rcp_implicit_cast;
447 using Teuchos::tuple;
449 static RCP<const ParameterList> validPL;
451 if (is_null(validPL)) {
452 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(
new Teuchos::ParameterList());
454 pl->set(
"Test Block Operator",
false,
455 "If Stratiikos/Teko is used to break an operator into its parts,\n"
456 "then setting this parameter to true will compare applications of the\n"
457 "segregated operator to the original operator.");
458 pl->set(
"Write Block Operator",
false,
459 "Write out the segregated operator to disk with the name \"block-?_xx\"");
460 pl->set(
"Strided Blocking",
"1",
461 "Assuming that the user wants Strided blocking, break the operator into\n"
462 "blocks. The syntax can be thought to be associated with the solution\n"
463 "vector. For example if your variables are [u v w p T], and we want [u v w]\n"
464 "blocked together, and p and T separate then the relevant string is \"3 1 1\".\n"
465 "Meaning put the first 3 unknowns per node together and separate the v and w\n"
467 pl->set(
"Reorder Type",
"",
468 "This specifies how the blocks are reordered for use in the preconditioner.\n"
469 "For example, assume the linear system is generated from 3D Navier-Stokes\n"
470 "with an energy equation, yielding the unknowns [u v w p T]. If the\n"
471 "\"Strided Blocking\" string is \"3 1 1\", then setting this parameter to\n"
472 "\"[2 [0 1]]\" will reorder the blocked operator so its nested with the\n"
473 "velocity and pressure forming an inner two-by-two block, and then the\n"
474 "temperature unknowns forming a two-by-two system with the velocity-pressure\n"
476 std::string defaultInverseType =
"";
477 #if defined(Teko_ENABLE_Amesos)
478 defaultInverseType =
"Amesos";
479 #elif defined(Teko_ENABLE_Amesos2)
480 defaultInverseType =
"Amesos2";
482 pl->set(
"Inverse Type", defaultInverseType,
483 "The type of inverse operator the user wants. This can be one of the defaults\n"
484 "from Stratimikos, or a Teko preconditioner defined in the\n"
485 "\"Inverse Factory Library\".");
486 pl->sublist(
"Inverse Factory Library",
false,
"Definition of Teko preconditioners.");
494 #ifdef TEKO_HAVE_EPETRA
498 Teuchos::RCP<Epetra_Operator> StratimikosFactory::buildWrappedEpetraOperator(
499 const Teuchos::RCP<const Epetra_Operator> &Jac,
const Teuchos::RCP<Epetra_Operator> &wrapInput,
500 std::ostream &out)
const {
501 Teuchos::RCP<Epetra_Operator> wrappedOp = wrapInput;
533 if (wrappedOp == Teuchos::null) {
535 std::vector<std::vector<int> > vars;
536 buildStridedVectors(*Jac, decomp_, vars);
540 std::string reorderType = paramList_->get<std::string>(
"Reorder Type");
541 if (reorderType !=
"") {
552 if (paramList_->get<
bool>(
"Test Block Operator")) {
554 ->testAgainstFullOperator(600, 1e-14);
556 out <<
"Teko: Tested operator correctness: " << (result ?
"passed" :
"FAILED!") << std::endl;
561 #endif // TEKO_HAVE_EPETRA
564 std::ostringstream oss;
565 oss <<
"Teko::StratimikosFactory";
569 #ifdef TEKO_HAVE_EPETRA
570 void StratimikosFactory::buildStridedVectors(
const Epetra_Operator &Jac,
571 const std::vector<int> &decomp,
572 std::vector<std::vector<int> > &vars)
const {
573 const Epetra_Map &rangeMap = Jac.OperatorRangeMap();
577 for (std::size_t i = 0; i < decomp.size(); i++) numVars += decomp[i];
580 TEUCHOS_ASSERT((rangeMap.NumMyElements() % numVars) == 0);
581 TEUCHOS_ASSERT((rangeMap.NumGlobalElements() % numVars) == 0);
583 int *globalIds = rangeMap.MyGlobalElements();
585 vars.resize(decomp.size());
586 for (
int i = 0; i < rangeMap.NumMyElements();) {
588 for (std::size_t d = 0; d < decomp.size(); d++) {
590 int current = decomp[d];
591 for (
int v = 0; v < current; v++, i++) vars[d].push_back(globalIds[i]);
595 #endif // TEKO_HAVE_EPETRA
597 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder &builder,
598 const std::string &stratName) {
599 TEUCHOS_TEST_FOR_EXCEPTION(
600 builder.getValidParameters()->sublist(
"Preconditioner Types").isParameter(stratName),
602 "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
603 "\" because it is already included in builder!");
605 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy =
606 Teuchos::rcp(
new Stratimikos::DefaultLinearSolverBuilder(builder));
609 Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder =
610 Teuchos::rcp(
new TekoFactoryBuilder(builderCopy, Teuchos::null));
611 builder.setPreconditioningStrategyFactory(tekoFactoryBuilder, stratName);
614 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder &builder,
615 const Teuchos::RCP<Teko::RequestHandler> &rh,
616 const std::string &stratName) {
617 TEUCHOS_TEST_FOR_EXCEPTION(
618 builder.getValidParameters()->sublist(
"Preconditioner Types").isParameter(stratName),
620 "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
621 "\" because it is already included in builder!");
623 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy =
624 Teuchos::rcp(
new Stratimikos::DefaultLinearSolverBuilder(builder));
628 Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder =
629 Teuchos::rcp(
new TekoFactoryBuilder(builderCopy, rh));
630 builder.setPreconditioningStrategyFactory(tekoFactoryBuilder, stratName);
bool applySupportsConj(Thyra::EConj conj) const
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void initializePrec(const Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > &fwdOp, Thyra::PreconditionerBase< double > *prec, const Thyra::ESupportSolveUse supportSolveUse) const
void uninitializePrec(Thyra::PreconditionerBase< double > *prec, Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > *fwdOp, Thyra::ESupportSolveUse *supportSolveUse) const
bool applyTransposeSupportsConj(Thyra::EConj conj) const
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
void initializePrec_Thyra(const Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > &fwdOp, Thyra::PreconditionerBase< double > *prec, const Thyra::ESupportSolveUse supportSolveUse) const
A single Epetra wrapper for all operators constructed from an inverse operator.
bool isCompatible(const Thyra::LinearOpSourceBase< double > &fwdOp) const
Teuchos::RCP< Thyra::PreconditionerBase< double > > createPrec() const
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
Teuchos::RCP< const BlockReorderManager > blockedReorderFromString(std::string &reorder)
Convert a string to a block reorder manager object.
This class takes a blocked linear op and represents it in a flattened form.
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const ¶mList)
Tear about a user specified Epetra_Operator (CrsMatrix) using a vector of vectors of GIDs for each bl...
std::string description() const
virtual void WriteBlocks(const std::string &prefix) const