Teko Version of the Day
Loading...
Searching...
No Matches
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
32namespace Teko {
33
34using Teuchos::ParameterList;
35using Teuchos::RCP;
36
37// hide stuff
38namespace {
39// Simple preconditioner class that adds a counter
40class 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
55class 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
78StratimikosFactory::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
85StratimikosFactory::StratimikosFactory(
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
126bool StratimikosFactory::applySupportsConj(Thyra::EConj /* conj */) const { return false; }
127
128bool StratimikosFactory::applyTransposeSupportsConj(Thyra::EConj /* conj */) const {
129 return false; // See comment below
130}
131
132Teuchos::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
249void 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
422void 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
429Teuchos::RCP<Teuchos::ParameterList> StratimikosFactory::getNonconstParameterList() {
430 return paramList_;
431}
432
433Teuchos::RCP<Teuchos::ParameterList> StratimikosFactory::unsetParameterList() {
434 Teuchos::RCP<ParameterList> _paramList = paramList_;
435 paramList_ = Teuchos::null;
436 return _paramList;
437}
438
439Teuchos::RCP<const Teuchos::ParameterList> StratimikosFactory::getParameterList() const {
440 return paramList_;
441}
442
443Teuchos::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
498Teuchos::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
564 std::ostringstream oss;
565 oss << "Teko::StratimikosFactory";
566 return oss.str();
567}
568
569#ifdef TEKO_HAVE_EPETRA
570void 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
597void 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
614void 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
Tear about a user specified Epetra_Operator (CrsMatrix) using a vector of vectors of GIDs for each bl...
A single Epetra wrapper for all operators constructed from an inverse operator.
This class takes a blocked linear op and represents it in a flattened form.
void initializePrec(const Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > &fwdOp, Thyra::PreconditionerBase< double > *prec, const Thyra::ESupportSolveUse supportSolveUse) const
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
Teuchos::RCP< Thyra::PreconditionerBase< double > > createPrec() const
bool isCompatible(const Thyra::LinearOpSourceBase< double > &fwdOp) const
bool applyTransposeSupportsConj(Thyra::EConj conj) const
bool applySupportsConj(Thyra::EConj conj) const
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
void uninitializePrec(Thyra::PreconditionerBase< double > *prec, Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > *fwdOp, Thyra::ESupportSolveUse *supportSolveUse) const
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
void initializePrec_Thyra(const Teuchos::RCP< const Thyra::LinearOpSourceBase< double > > &fwdOp, Thyra::PreconditionerBase< double > *prec, const Thyra::ESupportSolveUse supportSolveUse) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const