1 #include "Teko_StratimikosFactory.hpp"
3 #include "Teuchos_Time.hpp"
4 #include "Teuchos_AbstractFactoryStd.hpp"
6 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
7 #include "Thyra_EpetraLinearOp.hpp"
8 #include "Thyra_DefaultPreconditioner.hpp"
10 #include "Teko_InverseLibrary.hpp"
11 #include "Teko_Preconditioner.hpp"
12 #include "Teko_InverseFactoryOperator.hpp"
14 #include "Teko_InverseLibrary.hpp"
15 #include "Teko_StridedEpetraOperator.hpp"
16 #include "Teko_BlockedEpetraOperator.hpp"
17 #include "Teko_ReorderedLinearOp.hpp"
19 #include "EpetraExt_RowMatrixOut.h"
24 using Teuchos::ParameterList;
29 class StratimikosFactoryPreconditioner :
public Thyra::DefaultPreconditioner<double>{
31 StratimikosFactoryPreconditioner() : iter_(0) {}
33 inline void incrIter() { iter_++; }
34 inline std::size_t getIter() {
return iter_; }
37 StratimikosFactoryPreconditioner(
const StratimikosFactoryPreconditioner &);
44 class TekoFactoryBuilder
45 :
public Teuchos::AbstractFactory<Thyra::PreconditionerFactoryBase<double> > {
47 TekoFactoryBuilder(
const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> & builder,
48 const Teuchos::RCP<Teko::RequestHandler> & rh) : builder_(builder), requestHandler_(rh) {}
49 Teuchos::RCP<Thyra::PreconditionerFactoryBase<double> > create()
const
50 {
return Teuchos::rcp(
new StratimikosFactory(builder_,requestHandler_)); }
53 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builder_;
54 Teuchos::RCP<Teko::RequestHandler> requestHandler_;
60 :epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd()))
65 :epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd()))
71 const Teuchos::RCP<Teko::RequestHandler> & rh)
72 :epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())), builder_(builder)
81 using Teuchos::outArg;
83 TEUCHOS_ASSERT(
false);
121 Teuchos::RCP<Thyra::PreconditionerBase<double> >
124 return Teuchos::rcp(
new StratimikosFactoryPreconditioner());
129 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
130 Thyra::PreconditionerBase<double> *prec,
131 const Thyra::ESupportSolveUse supportSolveUse
134 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
136 if(epetraFwdOpViewExtractor_->isCompatible(*fwdOp))
143 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
144 Thyra::PreconditionerBase<double> *prec,
145 const Thyra::ESupportSolveUse
150 using Teuchos::rcp_dynamic_cast;
151 using Teuchos::implicit_cast;
152 using Thyra::LinearOpBase;
154 Teuchos::Time totalTimer(
""), timer(
"");
155 totalTimer.start(
true);
157 const RCP<Teuchos::FancyOStream> out = this->getOStream();
158 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
160 bool mediumVerbosity = (out.get() && implicit_cast<
int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
162 Teuchos::OSTab tab(out);
164 *out <<
"\nEntering Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
166 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
169 StratimikosFactoryPreconditioner & defaultPrec
170 = Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
171 Teuchos::RCP<LinearOpBase<double> > prec_Op = defaultPrec.getNonconstUnspecifiedPrecOp();
174 const bool startingOver = (prec_Op == Teuchos::null);
177 invLib_ = Teuchos::null;
178 invFactory_ = Teuchos::null;
181 *out <<
"\nCreating the initial Teko Operator object...\n";
186 invLib_ = Teko::InverseLibrary::buildFromParameterList(paramList_->sublist(
"Inverse Factory Library"),builder_);
187 invLib_->setRequestHandler(reqHandler_);
190 invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>(
"Inverse Type"));
194 Teuchos::OSTab(out).o() <<
"> Creation time = "<<timer.totalElapsedTime()<<
" sec\n";
198 *out <<
"\nComputing the preconditioner ...\n";
201 std::string reorderType = paramList_->get<std::string>(
"Reorder Type");
202 if(reorderType!=
"") {
204 Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > blkFwdOp =
205 Teuchos::rcp_dynamic_cast<
const Thyra::BlockedLinearOpBase<double> >(fwdOp,
true);
207 Teko::LinearOp blockedFwdOp = Teko::buildReorderedLinearOp(*brm,blkFwdOp);
209 if(prec_Op==Teuchos::null) {
210 Teko::ModifiableLinearOp reorderedPrec =
Teko::buildInverse(*invFactory_,blockedFwdOp);
214 Teko::ModifiableLinearOp reorderedPrec = Teuchos::rcp_dynamic_cast<
ReorderedLinearOp>(prec_Op,
true)->getBlockedOp();
220 if(prec_Op==Teuchos::null)
230 Teuchos::OSTab(out).o() <<
"=> Preconditioner construction time = "<<timer.totalElapsedTime()<<
" sec\n";
234 defaultPrec.initializeUnspecified( prec_Op);
235 defaultPrec.incrIter();
238 if(out.get() && implicit_cast<
int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
239 *out <<
"\nTotal time in Teko::StratimikosFactory = "<<totalTimer.totalElapsedTime()<<
" sec\n";
241 *out <<
"\nLeaving Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
245 const Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
246 Thyra::PreconditionerBase<double> *prec,
247 const Thyra::ESupportSolveUse
250 using Teuchos::outArg;
253 using Teuchos::rcp_dynamic_cast;
254 using Teuchos::implicit_cast;
256 Teuchos::Time totalTimer(
""), timer(
"");
257 totalTimer.start(
true);
259 const RCP<Teuchos::FancyOStream> out = this->getOStream();
260 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
262 bool mediumVerbosity = (out.get() && implicit_cast<
int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
264 Teuchos::OSTab tab(out);
266 *out <<
"\nEntering Teko::StratimikosFactory::initializePrec_Epetra(...) ...\n";
268 Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
270 TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL);
271 TEUCHOS_TEST_FOR_EXCEPT(prec==NULL);
277 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
278 Thyra::EOpTransp epetraFwdOpTransp;
279 Thyra::EApplyEpetraOpAs epetraFwdOpApplyAs;
280 Thyra::EAdjointEpetraOp epetraFwdOpAdjointSupport;
281 double epetraFwdOpScalar;
282 epetraFwdOpViewExtractor_->getEpetraOpView(
283 fwdOp,outArg(epetraFwdOp),outArg(epetraFwdOpTransp),outArg(epetraFwdOpApplyAs),
284 outArg(epetraFwdOpAdjointSupport),outArg(epetraFwdOpScalar)
287 StratimikosFactoryPreconditioner & defaultPrec
288 = Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
291 RCP<Thyra::EpetraLinearOp> epetra_precOp
292 = rcp_dynamic_cast<Thyra::EpetraLinearOp>(defaultPrec.getNonconstUnspecifiedPrecOp(),
true);
295 Teuchos::RCP<Teko::Epetra::InverseFactoryOperator> teko_precOp;
296 if(epetra_precOp!=Teuchos::null)
300 const bool startingOver = (teko_precOp == Teuchos::null);
303 invLib_ = Teuchos::null;
304 invFactory_ = Teuchos::null;
308 *out <<
"\nCreating the initial Teko::Epetra::InverseFactoryOperator object...\n";
312 std::stringstream ss;
313 ss << paramList_->get<std::string>(
"Strided Blocking");
316 while(not ss.eof()) {
320 TEUCHOS_ASSERT(num>0);
322 decomp_.push_back(num);
326 invLib_ = Teko::InverseLibrary::buildFromParameterList(paramList_->sublist(
"Inverse Factory Library"),builder_);
327 invLib_->setRequestHandler(reqHandler_);
330 invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>(
"Inverse Type"));
337 Teuchos::OSTab(out).o() <<
"> Creation time = "<<timer.totalElapsedTime()<<
" sec\n";
341 *out <<
"\nComputing the preconditioner ...\n";
345 bool writeBlockOps = paramList_->get<
bool>(
"Write Block Operator");
347 teko_precOp->initInverse();
349 if(decomp_.size()==1) {
350 teko_precOp->rebuildInverseOperator(epetraFwdOp);
354 std::stringstream ss;
355 ss <<
"block-" << defaultPrec.getIter() <<
"_00.mm";
356 EpetraExt::RowMatrixToMatrixMarketFile(ss.str().c_str(),*rcp_dynamic_cast<
const Epetra_CrsMatrix>(epetraFwdOp));
360 Teuchos::RCP<Epetra_Operator> wrappedFwdOp
361 = buildWrappedEpetraOperator(epetraFwdOp,teko_precOp->getNonconstForwardOp(),*out);
365 std::stringstream ss;
366 ss <<
"block-" << defaultPrec.getIter();
369 Teuchos::RCP<Teko::Epetra::BlockedEpetraOperator> stridedJac
371 if(stridedJac!=Teuchos::null) {
375 else TEUCHOS_ASSERT(
false);
378 teko_precOp->rebuildInverseOperator(wrappedFwdOp);
385 Teuchos::OSTab(out).o() <<
"=> Preconditioner construction time = "<<timer.totalElapsedTime()<<
" sec\n";
389 epetra_precOp = rcp(
new Thyra::EpetraLinearOp);
391 epetra_precOp->initialize(teko_precOp,epetraFwdOpTransp
392 ,Thyra::EPETRA_OP_APPLY_APPLY_INVERSE
393 ,Thyra::EPETRA_OP_ADJOINT_UNSUPPORTED);
396 defaultPrec.initializeUnspecified( Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp));
397 defaultPrec.incrIter();
400 if(out.get() && implicit_cast<
int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
401 *out <<
"\nTotal time in Teko::StratimikosFactory = "<<totalTimer.totalElapsedTime()<<
" sec\n";
403 *out <<
"\nLeaving Teko::StratimikosFactory::initializePrec(...) ...\n";
408 Thyra::PreconditionerBase<double> * ,
409 Teuchos::RCP<
const Thyra::LinearOpSourceBase<double> > * ,
410 Thyra::ESupportSolveUse *
413 TEUCHOS_TEST_FOR_EXCEPT(
true);
421 Teuchos::RCP<Teuchos::ParameterList>
const& paramList
424 TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL);
427 paramList_ = paramList;
432 Teuchos::RCP<Teuchos::ParameterList>
439 Teuchos::RCP<Teuchos::ParameterList>
442 Teuchos::RCP<ParameterList> _paramList = paramList_;
443 paramList_ = Teuchos::null;
448 Teuchos::RCP<const Teuchos::ParameterList>
455 Teuchos::RCP<const Teuchos::ParameterList>
460 using Teuchos::tuple;
461 using Teuchos::implicit_cast;
462 using Teuchos::rcp_implicit_cast;
464 static RCP<const ParameterList> validPL;
466 if(is_null(validPL)) {
468 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(
new Teuchos::ParameterList());
470 pl->set(
"Test Block Operator",
false,
471 "If Stratiikos/Teko is used to break an operator into its parts,\n"
472 "then setting this parameter to true will compare applications of the\n"
473 "segregated operator to the original operator.");
474 pl->set(
"Write Block Operator",
false,
475 "Write out the segregated operator to disk with the name \"block-?_xx\"");
476 pl->set(
"Strided Blocking",
"1",
477 "Assuming that the user wants Strided blocking, break the operator into\n"
478 "blocks. The syntax can be thought to be associated with the solution\n"
479 "vector. For example if your variables are [u v w p T], and we want [u v w]\n"
480 "blocked together, and p and T separate then the relevant string is \"3 1 1\".\n"
481 "Meaning put the first 3 unknowns per node together and separate the v and w\n"
483 pl->set(
"Reorder Type",
"",
484 "This specifies how the blocks are reordered for use in the preconditioner.\n"
485 "For example, assume the linear system is generated from 3D Navier-Stokes\n"
486 "with an energy equation, yielding the unknowns [u v w p T]. If the\n"
487 "\"Strided Blocking\" string is \"3 1 1\", then setting this parameter to\n"
488 "\"[2 [0 1]]\" will reorder the blocked operator so its nested with the\n"
489 "velocity and pressure forming an inner two-by-two block, and then the\n"
490 "temperature unknowns forming a two-by-two system with the velocity-pressure\n"
492 pl->set(
"Inverse Type",
"Amesos",
493 "The type of inverse operator the user wants. This can be one of the defaults\n"
494 "from Stratimikos, or a Teko preconditioner defined in the\n"
495 "\"Inverse Factory Library\".");
496 pl->sublist(
"Inverse Factory Library",
false,
"Definition of Teko preconditioners.");
507 Teuchos::RCP<Epetra_Operator> StratimikosFactory::buildWrappedEpetraOperator(
508 const Teuchos::RCP<const Epetra_Operator> & Jac,
509 const Teuchos::RCP<Epetra_Operator> & wrapInput,
513 Teuchos::RCP<Epetra_Operator> wrappedOp = wrapInput;
542 if(wrappedOp==Teuchos::null)
545 std::vector<std::vector<int> > vars;
546 buildStridedVectors(*Jac,decomp_,vars);
550 std::string reorderType = paramList_->get<std::string>(
"Reorder Type");
551 if(reorderType!=
"") {
563 if(paramList_->get<
bool>(
"Test Block Operator")) {
567 out <<
"Teko: Tested operator correctness: " << (result ?
"passed" :
"FAILED!") << std::endl;
575 std::ostringstream oss;
576 oss <<
"Teko::StratimikosFactory";
580 void StratimikosFactory::buildStridedVectors(
const Epetra_Operator & Jac,
581 const std::vector<int> & decomp,
582 std::vector<std::vector<int> > & vars)
const
584 const Epetra_Map & rangeMap = Jac.OperatorRangeMap();
588 for(std::size_t i=0;i<decomp.size();i++)
589 numVars += decomp[i];
592 TEUCHOS_ASSERT((rangeMap.NumMyElements() % numVars)==0);
593 TEUCHOS_ASSERT((rangeMap.NumGlobalElements() % numVars)==0);
595 int * globalIds = rangeMap.MyGlobalElements();
597 vars.resize(decomp.size());
598 for(
int i=0;i<rangeMap.NumMyElements();) {
601 for(std::size_t d=0;d<decomp.size();d++) {
603 int current = decomp[d];
604 for(
int v=0;v<current;v++,i++)
605 vars[d].push_back(globalIds[i]);
610 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder & builder,
611 const std::string & stratName)
613 TEUCHOS_TEST_FOR_EXCEPTION(builder.getValidParameters()->sublist(
"Preconditioner Types").isParameter(stratName),std::logic_error,
614 "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
"\" because it is already included in builder!");
616 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy
617 = Teuchos::rcp(
new Stratimikos::DefaultLinearSolverBuilder(builder));
620 Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder = Teuchos::rcp(
new TekoFactoryBuilder(builderCopy,Teuchos::null));
621 builder.setPreconditioningStrategyFactory(tekoFactoryBuilder,stratName);
624 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder & builder,
625 const Teuchos::RCP<Teko::RequestHandler> & rh,
626 const std::string & stratName)
628 TEUCHOS_TEST_FOR_EXCEPTION(builder.getValidParameters()->sublist(
"Preconditioner Types").isParameter(stratName),std::logic_error,
629 "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
"\" because it is already included in builder!");
631 Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy
632 = Teuchos::rcp(
new Stratimikos::DefaultLinearSolverBuilder(builder));
636 Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder = Teuchos::rcp(
new TekoFactoryBuilder(builderCopy,rh));
637 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)
void setRequestHandler(const Teuchos::RCP< Teko::RequestHandler > &rh)
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 initializePrec_Epetra(const Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > &fwdOp, Thyra::PreconditionerBase< double > *prec, const Thyra::ESupportSolveUse supportSolveUse) const
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