Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_StratimikosFactory.cpp
1 #include "Teko_StratimikosFactory.hpp"
2 
3 #include "Teuchos_Time.hpp"
4 #include "Teuchos_AbstractFactoryStd.hpp"
5 
6 #include "Thyra_DefaultPreconditioner.hpp"
7 
8 #include "Teko_InverseLibrary.hpp"
9 #include "Teko_Preconditioner.hpp"
10 #include "Teko_Utilities.hpp"
11 #include "Teko_InverseLibrary.hpp"
12 #include "Teko_ReorderedLinearOp.hpp"
13 
14 #ifdef TEKO_HAVE_EPETRA
15 #include "Teko_InverseFactoryOperator.hpp" // an epetra specific object
16 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
17 #include "Teko_StridedEpetraOperator.hpp"
18 #include "Teko_BlockedEpetraOperator.hpp"
19 #include "Thyra_EpetraLinearOp.hpp"
20 #include "EpetraExt_RowMatrixOut.h"
21 #endif
22 
23 namespace Teko {
24 
25 using Teuchos::ParameterList;
26 using Teuchos::RCP;
27 
28 // hide stuff
29 namespace {
30 // Simple preconditioner class that adds a counter
31 class StratimikosFactoryPreconditioner : public Thyra::DefaultPreconditioner<double> {
32  public:
33  StratimikosFactoryPreconditioner() : iter_(0) {}
34 
35  inline void incrIter() { iter_++; }
36  inline std::size_t getIter() { return iter_; }
37 
38  private:
39  StratimikosFactoryPreconditioner(const StratimikosFactoryPreconditioner &);
40 
41  std::size_t iter_;
42 };
43 
44 // factory used to initialize the Teko::StratimikosFactory
45 // user data
46 class TekoFactoryBuilder
47  : public Teuchos::AbstractFactory<Thyra::PreconditionerFactoryBase<double> > {
48  public:
49  TekoFactoryBuilder(const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> &builder,
50  const Teuchos::RCP<Teko::RequestHandler> &rh)
51  : builder_(builder), requestHandler_(rh) {}
52  Teuchos::RCP<Thyra::PreconditionerFactoryBase<double> > create() const {
53  return Teuchos::rcp(new StratimikosFactory(builder_, requestHandler_));
54  }
55 
56  private:
57  Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builder_;
58  Teuchos::RCP<Teko::RequestHandler> requestHandler_;
59 };
60 } // namespace
61 
62 #ifdef TEKO_HAVE_EPETRA
63 
64 // Constructors/initializers/accessors
66  : epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())) {}
67 
68 // Constructors/initializers/accessors
69 StratimikosFactory::StratimikosFactory(const Teuchos::RCP<Teko::RequestHandler> &rh)
70  : epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())) {
71  setRequestHandler(rh);
72 }
73 
74 #endif // TEKO_HAVE_EPETRA
75 
77  const Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> &builder,
78  const Teuchos::RCP<Teko::RequestHandler> &rh)
79  :
80 #ifdef TEKO_HAVE_EPETRA
81  epetraFwdOpViewExtractor_(Teuchos::rcp(new Thyra::EpetraOperatorViewExtractorStd())),
82 #endif
83  builder_(builder) {
84  setRequestHandler(rh);
85 }
86 
87 // Overridden from PreconditionerFactoryBase
89  const Thyra::LinearOpSourceBase<double> & /* fwdOpSrc */) const {
90  using Teuchos::outArg;
91 
92  TEUCHOS_ASSERT(false); // what you doing?
93 
94  /*
95  Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
96  Thyra::EOpTransp epetraFwdOpTransp;
97  Thyra::EApplyEpetraOpAs epetraFwdOpApplyAs;
98  Thyra::EAdjointEpetraOp epetraFwdOpAdjointSupport;
99  double epetraFwdOpScalar;
100 
101  // check to make sure this is an epetra CrsMatrix
102  Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc.getOp();
103  epetraFwdOpViewExtractor_->getEpetraOpView(
104  fwdOp,
105  outArg(epetraFwdOp),outArg(epetraFwdOpTransp),
106  outArg(epetraFwdOpApplyAs),
107  outArg(epetraFwdOpAdjointSupport),
108  outArg(epetraFwdOpScalar));
109 
110  if( !dynamic_cast<const Epetra_CrsMatrix*>(&*epetraFwdOp) )
111  return false;
112  */
113 
114  return true;
115 }
116 
117 bool StratimikosFactory::applySupportsConj(Thyra::EConj /* conj */) const { return false; }
118 
119 bool StratimikosFactory::applyTransposeSupportsConj(Thyra::EConj /* conj */) const {
120  return false; // See comment below
121 }
122 
123 Teuchos::RCP<Thyra::PreconditionerBase<double> > StratimikosFactory::createPrec() const {
124  return Teuchos::rcp(new StratimikosFactoryPreconditioner());
125 }
126 
128  const Teuchos::RCP<const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
129  Thyra::PreconditionerBase<double> *prec, const Thyra::ESupportSolveUse supportSolveUse) const {
130  Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
131 
132 #ifdef TEKO_HAVE_EPETRA
133  if (epetraFwdOpViewExtractor_->isCompatible(*fwdOp))
134  initializePrec_Epetra(fwdOpSrc, prec, supportSolveUse);
135  else
136 #endif
137  initializePrec_Thyra(fwdOpSrc, prec, supportSolveUse);
138 }
139 
141  const Teuchos::RCP<const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
142  Thyra::PreconditionerBase<double> *prec, const Thyra::ESupportSolveUse /* supportSolveUse */
143 ) const {
144  using Teuchos::implicit_cast;
145  using Teuchos::RCP;
146  using Teuchos::rcp;
147  using Teuchos::rcp_dynamic_cast;
148  using Thyra::LinearOpBase;
149 
150  Teuchos::Time totalTimer(""), timer("");
151  totalTimer.start(true);
152 
153  const RCP<Teuchos::FancyOStream> out = this->getOStream();
154  const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
155 
156  bool mediumVerbosity =
157  (out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
158 
159  Teuchos::OSTab tab(out);
160  if (mediumVerbosity)
161  *out << "\nEntering Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
162 
163  Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
164 
165  // Get the concrete preconditioner object
166  StratimikosFactoryPreconditioner &defaultPrec =
167  Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
168  Teuchos::RCP<LinearOpBase<double> > prec_Op = defaultPrec.getNonconstUnspecifiedPrecOp();
169 
170  // Permform initialization if needed
171  const bool startingOver = (prec_Op == Teuchos::null);
172  if (startingOver) {
173  // start over
174  invLib_ = Teuchos::null;
175  invFactory_ = Teuchos::null;
176 
177  if (mediumVerbosity) *out << "\nCreating the initial Teko Operator object...\n";
178 
179  timer.start(true);
180 
181  // build library, and set request handler (user defined!)
182  invLib_ = Teko::InverseLibrary::buildFromParameterList(
183  paramList_->sublist("Inverse Factory Library"), builder_);
184  invLib_->setRequestHandler(reqHandler_);
185 
186  // build preconditioner factory
187  invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>("Inverse Type"));
188 
189  timer.stop();
190  if (mediumVerbosity)
191  Teuchos::OSTab(out).o() << "> Creation time = " << timer.totalElapsedTime() << " sec\n";
192  }
193 
194  if (mediumVerbosity) *out << "\nComputing the preconditioner ...\n";
195 
196  // setup reordering if required
197  std::string reorderType = paramList_->get<std::string>("Reorder Type");
198  if (reorderType != "") {
199  Teuchos::RCP<const Thyra::BlockedLinearOpBase<double> > blkFwdOp =
200  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(fwdOp, true);
201  RCP<const Teko::BlockReorderManager> brm = Teko::blockedReorderFromString(reorderType);
202  Teko::LinearOp blockedFwdOp = Teko::buildReorderedLinearOp(*brm, blkFwdOp);
203 
204  if (prec_Op == Teuchos::null) {
205  Teko::ModifiableLinearOp reorderedPrec = Teko::buildInverse(*invFactory_, blockedFwdOp);
206  prec_Op = Teuchos::rcp(new ReorderedLinearOp(brm, reorderedPrec));
207  } else {
208  Teko::ModifiableLinearOp reorderedPrec =
209  Teuchos::rcp_dynamic_cast<ReorderedLinearOp>(prec_Op, true)->getBlockedOp();
210  Teko::rebuildInverse(*invFactory_, blockedFwdOp, reorderedPrec);
211  }
212  } else {
213  // no reordering required
214  if (prec_Op == Teuchos::null)
215  prec_Op = Teko::buildInverse(*invFactory_, fwdOp);
216  else
217  Teko::rebuildInverse(*invFactory_, fwdOp, prec_Op);
218  }
219 
220  // construct preconditioner
221  timer.stop();
222 
223  if (mediumVerbosity)
224  Teuchos::OSTab(out).o() << "=> Preconditioner construction time = " << timer.totalElapsedTime()
225  << " sec\n";
226 
227  // Initialize the preconditioner
228  defaultPrec.initializeUnspecified(prec_Op);
229  defaultPrec.incrIter();
230  totalTimer.stop();
231 
232  if (out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
233  *out << "\nTotal time in Teko::StratimikosFactory = " << totalTimer.totalElapsedTime()
234  << " sec\n";
235  if (mediumVerbosity)
236  *out << "\nLeaving Teko::StratimikosFactory::initializePrec_Thyra(...) ...\n";
237 }
238 
239 #ifdef TEKO_HAVE_EPETRA
240 void StratimikosFactory::initializePrec_Epetra(
241  const Teuchos::RCP<const Thyra::LinearOpSourceBase<double> > &fwdOpSrc,
242  Thyra::PreconditionerBase<double> *prec, const Thyra::ESupportSolveUse /* supportSolveUse */
243 ) const {
244  using Teuchos::implicit_cast;
245  using Teuchos::outArg;
246  using Teuchos::RCP;
247  using Teuchos::rcp;
248  using Teuchos::rcp_dynamic_cast;
249 
250  Teuchos::Time totalTimer(""), timer("");
251  totalTimer.start(true);
252 
253  const RCP<Teuchos::FancyOStream> out = this->getOStream();
254  const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
255 
256  bool mediumVerbosity =
257  (out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW));
258 
259  Teuchos::OSTab tab(out);
260  if (mediumVerbosity)
261  *out << "\nEntering Teko::StratimikosFactory::initializePrec_Epetra(...) ...\n";
262 
263  Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp();
264 #ifdef _DEBUG
265  TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get() == NULL);
266  TEUCHOS_TEST_FOR_EXCEPT(prec == NULL);
267 #endif
268 
269  //
270  // Unwrap and get the forward Epetra_Operator object
271  //
272  Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
273  Thyra::EOpTransp epetraFwdOpTransp;
274  Thyra::EApplyEpetraOpAs epetraFwdOpApplyAs;
275  Thyra::EAdjointEpetraOp epetraFwdOpAdjointSupport;
276  double epetraFwdOpScalar;
277  epetraFwdOpViewExtractor_->getEpetraOpView(
278  fwdOp, outArg(epetraFwdOp), outArg(epetraFwdOpTransp), outArg(epetraFwdOpApplyAs),
279  outArg(epetraFwdOpAdjointSupport), outArg(epetraFwdOpScalar));
280  // Get the concrete preconditioner object
281  StratimikosFactoryPreconditioner &defaultPrec =
282  Teuchos::dyn_cast<StratimikosFactoryPreconditioner>(*prec);
283 
284  // Get the EpetraLinearOp object that is used to implement the preconditoner linear op
285  RCP<Thyra::EpetraLinearOp> epetra_precOp =
286  rcp_dynamic_cast<Thyra::EpetraLinearOp>(defaultPrec.getNonconstUnspecifiedPrecOp(), true);
287 
288  // Get the embedded ML_Epetra::MultiLevelPreconditioner object if it exists
289  Teuchos::RCP<Teko::Epetra::InverseFactoryOperator> teko_precOp;
290  if (epetra_precOp != Teuchos::null)
291  teko_precOp =
292  rcp_dynamic_cast<Teko::Epetra::InverseFactoryOperator>(epetra_precOp->epetra_op(), true);
293 
294  // Permform initialization if needed
295  const bool startingOver = (teko_precOp == Teuchos::null);
296  if (startingOver) {
297  // start over
298  invLib_ = Teuchos::null;
299  invFactory_ = Teuchos::null;
300  decomp_.clear();
301 
302  if (mediumVerbosity)
303  *out << "\nCreating the initial Teko::Epetra::InverseFactoryOperator object...\n";
304 
305  timer.start(true);
306 
307  std::stringstream ss;
308  ss << paramList_->get<std::string>("Strided Blocking");
309 
310  // figure out the decomposition requested by the string
311  while (not ss.eof()) {
312  int num = 0;
313  ss >> num;
314 
315  TEUCHOS_ASSERT(num > 0);
316 
317  decomp_.push_back(num);
318  }
319 
320  // build library, and set request handler (user defined!)
321  invLib_ = Teko::InverseLibrary::buildFromParameterList(
322  paramList_->sublist("Inverse Factory Library"), builder_);
323  invLib_->setRequestHandler(reqHandler_);
324 
325  // build preconditioner factory
326  invFactory_ = invLib_->getInverseFactory(paramList_->get<std::string>("Inverse Type"));
327 
328  // Create the initial preconditioner: DO NOT compute it yet
329  teko_precOp = rcp(new Teko::Epetra::InverseFactoryOperator(invFactory_));
330 
331  timer.stop();
332  if (mediumVerbosity)
333  Teuchos::OSTab(out).o() << "> Creation time = " << timer.totalElapsedTime() << " sec\n";
334  }
335 
336  if (mediumVerbosity) *out << "\nComputing the preconditioner ...\n";
337 
338  // construct preconditioner
339  {
340  bool writeBlockOps = paramList_->get<bool>("Write Block Operator");
341  timer.start(true);
342  teko_precOp->initInverse();
343 
344  if (decomp_.size() == 1) {
345  teko_precOp->rebuildInverseOperator(epetraFwdOp);
346 
347  // write out to disk
348  if (writeBlockOps) {
349  std::stringstream ss;
350  ss << "block-" << defaultPrec.getIter() << "_00.mm";
351  EpetraExt::RowMatrixToMatrixMarketFile(
352  ss.str().c_str(), *rcp_dynamic_cast<const Epetra_CrsMatrix>(epetraFwdOp));
353  }
354  } else {
355  Teuchos::RCP<Epetra_Operator> wrappedFwdOp =
356  buildWrappedEpetraOperator(epetraFwdOp, teko_precOp->getNonconstForwardOp(), *out);
357 
358  // write out to disk
359  if (writeBlockOps) {
360  std::stringstream ss;
361  ss << "block-" << defaultPrec.getIter();
362  // Teuchos::RCP<Teko::Epetra::StridedEpetraOperator> stridedJac
363  // = Teuchos::rcp_dynamic_cast<Teko::Epetra::StridedEpetraOperator>(wrappedFwdOp);
364  Teuchos::RCP<Teko::Epetra::BlockedEpetraOperator> stridedJac =
365  Teuchos::rcp_dynamic_cast<Teko::Epetra::BlockedEpetraOperator>(wrappedFwdOp);
366  if (stridedJac != Teuchos::null) {
367  // write out blocks of strided operator
368  stridedJac->WriteBlocks(ss.str());
369  } else
370  TEUCHOS_ASSERT(false);
371  }
372 
373  teko_precOp->rebuildInverseOperator(wrappedFwdOp);
374  }
375 
376  timer.stop();
377  }
378 
379  if (mediumVerbosity)
380  Teuchos::OSTab(out).o() << "=> Preconditioner construction time = " << timer.totalElapsedTime()
381  << " sec\n";
382 
383  // Initialize the output EpetraLinearOp
384  if (startingOver) {
385  epetra_precOp = rcp(new Thyra::EpetraLinearOp);
386  }
387  epetra_precOp->initialize(teko_precOp, epetraFwdOpTransp, Thyra::EPETRA_OP_APPLY_APPLY_INVERSE,
388  Thyra::EPETRA_OP_ADJOINT_UNSUPPORTED);
389 
390  // Initialize the preconditioner
391  defaultPrec.initializeUnspecified(
392  Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp));
393  defaultPrec.incrIter();
394  totalTimer.stop();
395 
396  if (out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
397  *out << "\nTotal time in Teko::StratimikosFactory = " << totalTimer.totalElapsedTime()
398  << " sec\n";
399  if (mediumVerbosity) *out << "\nLeaving Teko::StratimikosFactory::initializePrec(...) ...\n";
400 }
401 #endif // TEKO_HAVE_EPETRA
402 
404  Thyra::PreconditionerBase<double> * /* prec */,
405  Teuchos::RCP<const Thyra::LinearOpSourceBase<double> > * /* fwdOp */,
406  Thyra::ESupportSolveUse * /* supportSolveUse */
407 ) const {
408  TEUCHOS_TEST_FOR_EXCEPT(true);
409 }
410 
411 // Overridden from ParameterListAcceptor
412 
413 void StratimikosFactory::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const &paramList) {
414  TEUCHOS_TEST_FOR_EXCEPT(paramList.get() == NULL);
415 
416  paramList->validateParametersAndSetDefaults(*this->getValidParameters(), 0);
417  paramList_ = paramList;
418 }
419 
420 Teuchos::RCP<Teuchos::ParameterList> StratimikosFactory::getNonconstParameterList() {
421  return paramList_;
422 }
423 
424 Teuchos::RCP<Teuchos::ParameterList> StratimikosFactory::unsetParameterList() {
425  Teuchos::RCP<ParameterList> _paramList = paramList_;
426  paramList_ = Teuchos::null;
427  return _paramList;
428 }
429 
430 Teuchos::RCP<const Teuchos::ParameterList> StratimikosFactory::getParameterList() const {
431  return paramList_;
432 }
433 
434 Teuchos::RCP<const Teuchos::ParameterList> StratimikosFactory::getValidParameters() const {
435  using Teuchos::implicit_cast;
436  using Teuchos::rcp;
437  using Teuchos::rcp_implicit_cast;
438  using Teuchos::tuple;
439 
440  static RCP<const ParameterList> validPL;
441 
442  if (is_null(validPL)) {
443  Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList());
444 
445  pl->set("Test Block Operator", false,
446  "If Stratiikos/Teko is used to break an operator into its parts,\n"
447  "then setting this parameter to true will compare applications of the\n"
448  "segregated operator to the original operator.");
449  pl->set("Write Block Operator", false,
450  "Write out the segregated operator to disk with the name \"block-?_xx\"");
451  pl->set("Strided Blocking", "1",
452  "Assuming that the user wants Strided blocking, break the operator into\n"
453  "blocks. The syntax can be thought to be associated with the solution\n"
454  "vector. For example if your variables are [u v w p T], and we want [u v w]\n"
455  "blocked together, and p and T separate then the relevant string is \"3 1 1\".\n"
456  "Meaning put the first 3 unknowns per node together and separate the v and w\n"
457  "components.");
458  pl->set("Reorder Type", "",
459  "This specifies how the blocks are reordered for use in the preconditioner.\n"
460  "For example, assume the linear system is generated from 3D Navier-Stokes\n"
461  "with an energy equation, yielding the unknowns [u v w p T]. If the\n"
462  "\"Strided Blocking\" string is \"3 1 1\", then setting this parameter to\n"
463  "\"[2 [0 1]]\" will reorder the blocked operator so its nested with the\n"
464  "velocity and pressure forming an inner two-by-two block, and then the\n"
465  "temperature unknowns forming a two-by-two system with the velocity-pressure\n"
466  "block.");
467  std::string defaultInverseType = "";
468 #if defined(Teko_ENABLE_Amesos)
469  defaultInverseType = "Amesos";
470 #elif defined(Teko_ENABLE_Amesos2)
471  defaultInverseType = "Amesos2";
472 #endif
473  pl->set("Inverse Type", defaultInverseType,
474  "The type of inverse operator the user wants. This can be one of the defaults\n"
475  "from Stratimikos, or a Teko preconditioner defined in the\n"
476  "\"Inverse Factory Library\".");
477  pl->sublist("Inverse Factory Library", false, "Definition of Teko preconditioners.");
478 
479  validPL = pl;
480  }
481 
482  return validPL;
483 }
484 
485 #ifdef TEKO_HAVE_EPETRA
486 
489 Teuchos::RCP<Epetra_Operator> StratimikosFactory::buildWrappedEpetraOperator(
490  const Teuchos::RCP<const Epetra_Operator> &Jac, const Teuchos::RCP<Epetra_Operator> &wrapInput,
491  std::ostream &out) const {
492  Teuchos::RCP<Epetra_Operator> wrappedOp = wrapInput;
493 
494  // // initialize jacobian
495  // if(wrappedOp==Teuchos::null)
496  // {
497  // wrappedOp = Teuchos::rcp(new Teko::Epetra::StridedEpetraOperator(decomp_,Jac));
498  //
499  // // reorder the blocks if requested
500  // std::string reorderType = paramList_->get<std::string>("Reorder Type");
501  // if(reorderType!="") {
502  // RCP<const Teko::BlockReorderManager> brm =
503  // Teko::blockedReorderFromString(reorderType);
504  //
505  // // out << "Teko: Reordering = " << brm->toString() << std::endl;
506  // Teuchos::rcp_dynamic_cast<Teko::Epetra::StridedEpetraOperator>(wrappedOp)->Reorder(*brm);
507  // }
508  // }
509  // else {
510  // Teuchos::rcp_dynamic_cast<Teko::Epetra::StridedEpetraOperator>(wrappedOp)->RebuildOps();
511  // }
512  //
513  // // test blocked operator for correctness
514  // if(paramList_->get<bool>("Test Block Operator")) {
515  // bool result
516  // =
517  // Teuchos::rcp_dynamic_cast<Teko::Epetra::StridedEpetraOperator>(wrappedOp)->testAgainstFullOperator(600,1e-14);
518  //
519  // out << "Teko: Tested operator correctness: " << (result ? "passed" : "FAILED!") <<
520  // std::endl;
521  // }
522 
523  // initialize jacobian
524  if (wrappedOp == Teuchos::null) {
525  // build strided vector
526  std::vector<std::vector<int> > vars;
527  buildStridedVectors(*Jac, decomp_, vars);
528  wrappedOp = Teuchos::rcp(new Teko::Epetra::BlockedEpetraOperator(vars, Jac));
529 
530  // reorder the blocks if requested
531  std::string reorderType = paramList_->get<std::string>("Reorder Type");
532  if (reorderType != "") {
533  RCP<const Teko::BlockReorderManager> brm = Teko::blockedReorderFromString(reorderType);
534 
535  // out << "Teko: Reordering = " << brm->toString() << std::endl;
536  Teuchos::rcp_dynamic_cast<Teko::Epetra::BlockedEpetraOperator>(wrappedOp)->Reorder(*brm);
537  }
538  } else {
539  Teuchos::rcp_dynamic_cast<Teko::Epetra::BlockedEpetraOperator>(wrappedOp)->RebuildOps();
540  }
541 
542  // test blocked operator for correctness
543  if (paramList_->get<bool>("Test Block Operator")) {
544  bool result = Teuchos::rcp_dynamic_cast<Teko::Epetra::BlockedEpetraOperator>(wrappedOp)
545  ->testAgainstFullOperator(600, 1e-14);
546 
547  out << "Teko: Tested operator correctness: " << (result ? "passed" : "FAILED!") << std::endl;
548  }
549 
550  return wrappedOp;
551 }
552 #endif // TEKO_HAVE_EPETRA
553 
554 std::string StratimikosFactory::description() const {
555  std::ostringstream oss;
556  oss << "Teko::StratimikosFactory";
557  return oss.str();
558 }
559 
560 #ifdef TEKO_HAVE_EPETRA
561 void StratimikosFactory::buildStridedVectors(const Epetra_Operator &Jac,
562  const std::vector<int> &decomp,
563  std::vector<std::vector<int> > &vars) const {
564  const Epetra_Map &rangeMap = Jac.OperatorRangeMap();
565 
566  // compute total number of variables
567  int numVars = 0;
568  for (std::size_t i = 0; i < decomp.size(); i++) numVars += decomp[i];
569 
570  // verify that the decomposition is appropriate for this matrix
571  TEUCHOS_ASSERT((rangeMap.NumMyElements() % numVars) == 0);
572  TEUCHOS_ASSERT((rangeMap.NumGlobalElements() % numVars) == 0);
573 
574  int *globalIds = rangeMap.MyGlobalElements();
575 
576  vars.resize(decomp.size());
577  for (int i = 0; i < rangeMap.NumMyElements();) {
578  // for each "node" copy global ids to vectors
579  for (std::size_t d = 0; d < decomp.size(); d++) {
580  // for this variable copy global ids to variable arrays
581  int current = decomp[d];
582  for (int v = 0; v < current; v++, i++) vars[d].push_back(globalIds[i]);
583  }
584  }
585 }
586 #endif // TEKO_HAVE_EPETRA
587 
588 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder &builder,
589  const std::string &stratName) {
590  TEUCHOS_TEST_FOR_EXCEPTION(
591  builder.getValidParameters()->sublist("Preconditioner Types").isParameter(stratName),
592  std::logic_error,
593  "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
594  "\" because it is already included in builder!");
595 
596  Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy =
597  Teuchos::rcp(new Stratimikos::DefaultLinearSolverBuilder(builder));
598 
599  // use default constructor to add Teko::StratimikosFactory
600  Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder =
601  Teuchos::rcp(new TekoFactoryBuilder(builderCopy, Teuchos::null));
602  builder.setPreconditioningStrategyFactory(tekoFactoryBuilder, stratName);
603 }
604 
605 void addTekoToStratimikosBuilder(Stratimikos::DefaultLinearSolverBuilder &builder,
606  const Teuchos::RCP<Teko::RequestHandler> &rh,
607  const std::string &stratName) {
608  TEUCHOS_TEST_FOR_EXCEPTION(
609  builder.getValidParameters()->sublist("Preconditioner Types").isParameter(stratName),
610  std::logic_error,
611  "Teko::addTekoToStratimikosBuilder cannot add \"" + stratName +
612  "\" because it is already included in builder!");
613 
614  Teuchos::RCP<Stratimikos::DefaultLinearSolverBuilder> builderCopy =
615  Teuchos::rcp(new Stratimikos::DefaultLinearSolverBuilder(builder));
616 
617  // build an instance of a Teuchos::AbsractFactory<Thyra::PFB> so request handler is passed onto
618  // the resulting StratimikosFactory
619  Teuchos::RCP<TekoFactoryBuilder> tekoFactoryBuilder =
620  Teuchos::rcp(new TekoFactoryBuilder(builderCopy, rh));
621  builder.setPreconditioningStrategyFactory(tekoFactoryBuilder, stratName);
622 }
623 
624 } // namespace Teko
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 &paramList)
Tear about a user specified Epetra_Operator (CrsMatrix) using a vector of vectors of GIDs for each bl...
virtual void WriteBlocks(const std::string &prefix) const