Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_EpetraBlockPreconditioner.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_EpetraBlockPreconditioner.hpp"
11 #include "Teko_Preconditioner.hpp"
12 
13 // Thyra includes
14 #include "Thyra_DefaultLinearOpSource.hpp"
15 #include "Thyra_EpetraLinearOp.hpp"
16 
17 // Teuchos includes
18 #include "Teuchos_Time.hpp"
19 
20 // Teko includes
21 #include "Teko_BasicMappingStrategy.hpp"
22 
23 namespace Teko {
24 namespace Epetra {
25 
26 using Teuchos::RCP;
27 using Teuchos::rcp;
28 using Teuchos::rcp_dynamic_cast;
29 using Teuchos::rcpFromRef;
30 
37 EpetraBlockPreconditioner::EpetraBlockPreconditioner(
38  const Teuchos::RCP<const PreconditionerFactory>& bfp)
39  : preconFactory_(bfp), firstBuildComplete_(false) {}
40 
42  if ((not clearOld) && preconObj_ != Teuchos::null) return;
43  preconObj_ = preconFactory_->createPrec();
44 }
45 
58 void EpetraBlockPreconditioner::buildPreconditioner(const Teuchos::RCP<const Epetra_Operator>& A,
59  bool clear) {
60  Teko_DEBUG_SCOPE("EBP::buildPreconditioner", 10);
61 
62  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
63  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
64 
65  // set the mapping strategy
66  // SetMapStrategy(rcp(new InverseMappingStrategy(eow->getMapStrategy())));
67  SetMapStrategy(rcp(new InverseMappingStrategy(extractMappingStrategy(A))));
68 
69  // build preconObj_
70  initPreconditioner(clear);
71 
72  // actually build the preconditioner
73  RCP<const Thyra::LinearOpSourceBase<double> > lOpSrc = Thyra::defaultLinearOpSource(thyraA);
74  preconFactory_->initializePrec(lOpSrc, &*preconObj_, Thyra::SUPPORT_SOLVE_UNSPECIFIED);
75 
76  // extract preconditioner operator
77  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
78 
79  SetOperator(preconditioner, false);
80 
81  firstBuildComplete_ = true;
82 
83  TEUCHOS_ASSERT(preconObj_ != Teuchos::null);
84  TEUCHOS_ASSERT(getThyraOp() != Teuchos::null);
85  TEUCHOS_ASSERT(getMapStrategy() != Teuchos::null);
86  TEUCHOS_ASSERT(firstBuildComplete_ == true);
87 }
88 
102 void EpetraBlockPreconditioner::buildPreconditioner(const Teuchos::RCP<const Epetra_Operator>& A,
103  const Epetra_MultiVector& epetra_mv,
104  bool clear) {
105  Teko_DEBUG_SCOPE("EBP::buildPreconditioner - with solution", 10);
106 
107  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
108  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
109 
110  // set the mapping strategy
111  SetMapStrategy(rcp(new InverseMappingStrategy(extractMappingStrategy(A))));
112 
113  TEUCHOS_ASSERT(getMapStrategy() != Teuchos::null);
114 
115  // build the thyra version of the source multivector
116  RCP<Thyra::MultiVectorBase<double> > thyra_mv =
117  Thyra::createMembers(thyraA->range(), epetra_mv.NumVectors());
118  getMapStrategy()->copyEpetraIntoThyra(epetra_mv, thyra_mv.ptr());
119 
120  // build preconObj_
121  initPreconditioner(clear);
122 
123  // actually build the preconditioner
124  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA), thyra_mv, &*preconObj_,
125  Thyra::SUPPORT_SOLVE_UNSPECIFIED);
126  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
127 
128  SetOperator(preconditioner, false);
129 
130  firstBuildComplete_ = true;
131 
132  TEUCHOS_ASSERT(preconObj_ != Teuchos::null);
133  TEUCHOS_ASSERT(getThyraOp() != Teuchos::null);
134  TEUCHOS_ASSERT(getMapStrategy() != Teuchos::null);
135  TEUCHOS_ASSERT(firstBuildComplete_ == true);
136 }
137 
152  const Teuchos::RCP<const Epetra_Operator>& A) {
153  Teko_DEBUG_SCOPE("EBP::rebuildPreconditioner", 10);
154 
155  // if the preconditioner hasn't been built yet, rebuild from scratch
156  if (not firstBuildComplete_) {
157  buildPreconditioner(A, false);
158  return;
159  }
160  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
161 
162  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
163  Teko_DEBUG_EXPR(timer.start(true));
164  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
165  Teko_DEBUG_EXPR(timer.stop());
166  Teko_DEBUG_MSG("EBP::rebuild get thyraop time = " << timer.totalElapsedTime(), 2);
167 
168  // reinitialize the preconditioner
169  Teko_DEBUG_EXPR(timer.start(true));
170  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA), &*preconObj_,
171  Thyra::SUPPORT_SOLVE_UNSPECIFIED);
172  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
173  Teko_DEBUG_EXPR(timer.stop());
174  Teko_DEBUG_MSG("EBP::rebuild initialize prec time = " << timer.totalElapsedTime(), 2);
175 
176  Teko_DEBUG_EXPR(timer.start(true));
177  SetOperator(preconditioner, false);
178  Teko_DEBUG_EXPR(timer.stop());
179  Teko_DEBUG_MSG("EBP::rebuild set operator time = " << timer.totalElapsedTime(), 2);
180 
181  TEUCHOS_ASSERT(preconObj_ != Teuchos::null);
182  TEUCHOS_ASSERT(getThyraOp() != Teuchos::null);
183  TEUCHOS_ASSERT(firstBuildComplete_ == true);
184 }
185 
199 void EpetraBlockPreconditioner::rebuildPreconditioner(const Teuchos::RCP<const Epetra_Operator>& A,
200  const Epetra_MultiVector& epetra_mv) {
201  Teko_DEBUG_SCOPE("EBP::rebuildPreconditioner - with solution", 10);
202 
203  // if the preconditioner hasn't been built yet, rebuild from scratch
204  if (not firstBuildComplete_) {
205  buildPreconditioner(A, epetra_mv, false);
206  return;
207  }
208  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
209 
210  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
211  Teko_DEBUG_EXPR(timer.start(true));
212  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
213  Teko_DEBUG_EXPR(timer.stop());
214  Teko_DEBUG_MSG("EBP::rebuild get thyraop time = " << timer.totalElapsedTime(), 2);
215 
216  // build the thyra version of the source multivector
217  Teko_DEBUG_EXPR(timer.start(true));
218  RCP<Thyra::MultiVectorBase<double> > thyra_mv =
219  Thyra::createMembers(thyraA->range(), epetra_mv.NumVectors());
220  getMapStrategy()->copyEpetraIntoThyra(epetra_mv, thyra_mv.ptr());
221  Teko_DEBUG_EXPR(timer.stop());
222  Teko_DEBUG_MSG("EBP::rebuild vector copy time = " << timer.totalElapsedTime(), 2);
223 
224  // reinitialize the preconditioner
225  Teko_DEBUG_EXPR(timer.start(true));
226  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA), thyra_mv, &*preconObj_,
227  Thyra::SUPPORT_SOLVE_UNSPECIFIED);
228  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
229  Teko_DEBUG_EXPR(timer.stop());
230  Teko_DEBUG_MSG("EBP::rebuild initialize prec time = " << timer.totalElapsedTime(), 2);
231 
232  Teko_DEBUG_EXPR(timer.start(true));
233  SetOperator(preconditioner, false);
234  Teko_DEBUG_EXPR(timer.stop());
235  Teko_DEBUG_MSG("EBP::rebuild set operator time = " << timer.totalElapsedTime(), 2);
236 
237  TEUCHOS_ASSERT(preconObj_ != Teuchos::null);
238  TEUCHOS_ASSERT(getThyraOp() != Teuchos::null);
239  TEUCHOS_ASSERT(firstBuildComplete_ == true);
240 }
241 
251 Teuchos::RCP<PreconditionerState> EpetraBlockPreconditioner::getPreconditionerState() {
252  Teuchos::RCP<Preconditioner> bp = rcp_dynamic_cast<Preconditioner>(preconObj_);
253 
254  if (bp != Teuchos::null) return bp->getStateObject();
255 
256  return Teuchos::null;
257 }
258 
268 Teuchos::RCP<const PreconditionerState> EpetraBlockPreconditioner::getPreconditionerState() const {
269  Teuchos::RCP<const Preconditioner> bp = rcp_dynamic_cast<const Preconditioner>(preconObj_);
270 
271  if (bp != Teuchos::null) return bp->getStateObject();
272 
273  return Teuchos::null;
274 }
275 
276 Teuchos::RCP<const Thyra::LinearOpBase<double> > EpetraBlockPreconditioner::extractLinearOp(
277  const Teuchos::RCP<const Epetra_Operator>& A) const {
278  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
279  const RCP<const EpetraOperatorWrapper>& eow = rcp_dynamic_cast<const EpetraOperatorWrapper>(A);
280 
281  // if it is an EpetraOperatorWrapper, then get the Thyra operator
282  if (eow != Teuchos::null) return eow->getThyraOp();
283 
284  // otherwise wrap it up as a thyra operator
285  return Thyra::epetraLinearOp(A);
286 }
287 
288 Teuchos::RCP<const MappingStrategy> EpetraBlockPreconditioner::extractMappingStrategy(
289  const Teuchos::RCP<const Epetra_Operator>& A) const {
290  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
291  const RCP<const EpetraOperatorWrapper>& eow = rcp_dynamic_cast<const EpetraOperatorWrapper>(A);
292 
293  // if it is an EpetraOperatorWrapper, then get the Thyra operator
294  if (eow != Teuchos::null) return eow->getMapStrategy();
295 
296  // otherwise wrap it up as a thyra operator
297  RCP<const Epetra_Map> range = rcpFromRef(A->OperatorRangeMap());
298  RCP<const Epetra_Map> domain = rcpFromRef(A->OperatorDomainMap());
299  return rcp(new BasicMappingStrategy(range, domain, A->Comm()));
300 }
301 
302 } // end namespace Epetra
303 } // end namespace Teko
virtual const RCP< PreconditionerState > getStateObject()
virtual void buildPreconditioner(const Teuchos::RCP< const Epetra_Operator > &A, bool clear=true)
Build this preconditioner from an Epetra_Operator passed in to this object.
virtual void initPreconditioner(bool clearOld=false)
Build the underlying data structure for the preconditioner.
virtual void rebuildPreconditioner(const Teuchos::RCP< const Epetra_Operator > &A)
Rebuild this preconditioner from an Epetra_Operator passed in this to object.
Implements the Epetra_Operator interface with a Thyra LinearOperator. This enables the use of absrtac...
virtual Teuchos::RCP< PreconditionerState > getPreconditionerState()
Flip a mapping strategy object around to give the &quot;inverse&quot; mapping strategy.
const RCP< const MappingStrategy > getMapStrategy() const
Get the mapping strategy for this wrapper (translate between Thyra and Epetra)
An extension of the Thyra::DefaultPreconditioner class with some specializations useful for use withi...
const RCP< const Thyra::LinearOpBase< double > > getThyraOp() const
Return the thyra operator associated with this wrapper.