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