Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_EpetraBlockPreconditioner.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include "Teko_EpetraBlockPreconditioner.hpp"
48 #include "Teko_Preconditioner.hpp"
49 
50 // Thyra includes
51 #include "Thyra_DefaultLinearOpSource.hpp"
52 #include "Thyra_EpetraLinearOp.hpp"
53 
54 // Teuchos includes
55 #include "Teuchos_Time.hpp"
56 
57 // Teko includes
58 #include "Teko_BasicMappingStrategy.hpp"
59 
60 namespace Teko {
61 namespace Epetra {
62 
63 using Teuchos::RCP;
64 using Teuchos::rcp;
65 using Teuchos::rcpFromRef;
66 using Teuchos::rcp_dynamic_cast;
67 
74 EpetraBlockPreconditioner::EpetraBlockPreconditioner(const Teuchos::RCP<const PreconditionerFactory> & bfp)
75  : preconFactory_(bfp), firstBuildComplete_(false)
76 {
77 }
78 
80 {
81  if((not clearOld) && preconObj_!=Teuchos::null)
82  return;
83  preconObj_ = preconFactory_->createPrec();
84 }
85 
98 void EpetraBlockPreconditioner::buildPreconditioner(const Teuchos::RCP<const Epetra_Operator> & A,bool clear)
99 {
100  Teko_DEBUG_SCOPE("EBP::buildPreconditioner",10);
101 
102  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
103  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
104 
105  // set the mapping strategy
106  // SetMapStrategy(rcp(new InverseMappingStrategy(eow->getMapStrategy())));
107  SetMapStrategy(rcp(new InverseMappingStrategy(extractMappingStrategy(A))));
108 
109  // build preconObj_
110  initPreconditioner(clear);
111 
112  // actually build the preconditioner
113  RCP<const Thyra::LinearOpSourceBase<double> > lOpSrc = Thyra::defaultLinearOpSource(thyraA);
114  preconFactory_->initializePrec(lOpSrc,&*preconObj_,Thyra::SUPPORT_SOLVE_UNSPECIFIED);
115 
116  // extract preconditioner operator
117  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
118 
119  SetOperator(preconditioner,false);
120 
121  firstBuildComplete_ = true;
122 
123  TEUCHOS_ASSERT(preconObj_!=Teuchos::null);
124  TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null);
125  TEUCHOS_ASSERT(getMapStrategy()!=Teuchos::null);
126  TEUCHOS_ASSERT(firstBuildComplete_==true);
127 }
128 
142 void EpetraBlockPreconditioner::buildPreconditioner(const Teuchos::RCP<const Epetra_Operator> & A,const Epetra_MultiVector & epetra_mv,bool clear)
143 {
144  Teko_DEBUG_SCOPE("EBP::buildPreconditioner - with solution",10);
145 
146  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
147  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
148 
149  // set the mapping strategy
150  SetMapStrategy(rcp(new InverseMappingStrategy(extractMappingStrategy(A))));
151 
152  TEUCHOS_ASSERT(getMapStrategy()!=Teuchos::null);
153 
154  // build the thyra version of the source multivector
155  RCP<Thyra::MultiVectorBase<double> > thyra_mv = Thyra::createMembers(thyraA->range(),epetra_mv.NumVectors());
156  getMapStrategy()->copyEpetraIntoThyra(epetra_mv,thyra_mv.ptr());
157 
158  // build preconObj_
159  initPreconditioner(clear);
160 
161  // actually build the preconditioner
162  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA),thyra_mv,&*preconObj_,Thyra::SUPPORT_SOLVE_UNSPECIFIED);
163  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
164 
165  SetOperator(preconditioner,false);
166 
167  firstBuildComplete_ = true;
168 
169  TEUCHOS_ASSERT(preconObj_!=Teuchos::null);
170  TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null);
171  TEUCHOS_ASSERT(getMapStrategy()!=Teuchos::null);
172  TEUCHOS_ASSERT(firstBuildComplete_==true);
173 }
174 
188 void EpetraBlockPreconditioner::rebuildPreconditioner(const Teuchos::RCP<const Epetra_Operator> & A)
189 {
190  Teko_DEBUG_SCOPE("EBP::rebuildPreconditioner",10);
191 
192  // if the preconditioner hasn't been built yet, rebuild from scratch
193  if(not firstBuildComplete_) {
194  buildPreconditioner(A,false);
195  return;
196  }
197  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
198 
199  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
200  Teko_DEBUG_EXPR(timer.start(true));
201  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
202  Teko_DEBUG_EXPR(timer.stop());
203  Teko_DEBUG_MSG("EBP::rebuild get thyraop time = " << timer.totalElapsedTime(),2);
204 
205  // reinitialize the preconditioner
206  Teko_DEBUG_EXPR(timer.start(true));
207  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA),&*preconObj_,Thyra::SUPPORT_SOLVE_UNSPECIFIED);
208  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
209  Teko_DEBUG_EXPR(timer.stop());
210  Teko_DEBUG_MSG("EBP::rebuild initialize prec time = " << timer.totalElapsedTime(),2);
211 
212  Teko_DEBUG_EXPR(timer.start(true));
213  SetOperator(preconditioner,false);
214  Teko_DEBUG_EXPR(timer.stop());
215  Teko_DEBUG_MSG("EBP::rebuild set operator time = " << timer.totalElapsedTime(),2);
216 
217  TEUCHOS_ASSERT(preconObj_!=Teuchos::null);
218  TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null);
219  TEUCHOS_ASSERT(firstBuildComplete_==true);
220 }
221 
235 void EpetraBlockPreconditioner::rebuildPreconditioner(const Teuchos::RCP<const Epetra_Operator> & A,const Epetra_MultiVector & epetra_mv)
236 {
237  Teko_DEBUG_SCOPE("EBP::rebuildPreconditioner - with solution",10);
238 
239  // if the preconditioner hasn't been built yet, rebuild from scratch
240  if(not firstBuildComplete_) {
241  buildPreconditioner(A,epetra_mv,false);
242  return;
243  }
244  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
245 
246  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
247  Teko_DEBUG_EXPR(timer.start(true));
248  RCP<const Thyra::LinearOpBase<double> > thyraA = extractLinearOp(A);
249  Teko_DEBUG_EXPR(timer.stop());
250  Teko_DEBUG_MSG("EBP::rebuild get thyraop time = " << timer.totalElapsedTime(),2);
251 
252  // build the thyra version of the source multivector
253  Teko_DEBUG_EXPR(timer.start(true));
254  RCP<Thyra::MultiVectorBase<double> > thyra_mv = Thyra::createMembers(thyraA->range(),epetra_mv.NumVectors());
255  getMapStrategy()->copyEpetraIntoThyra(epetra_mv,thyra_mv.ptr());
256  Teko_DEBUG_EXPR(timer.stop());
257  Teko_DEBUG_MSG("EBP::rebuild vector copy time = " << timer.totalElapsedTime(),2);
258 
259  // reinitialize the preconditioner
260  Teko_DEBUG_EXPR(timer.start(true));
261  preconFactory_->initializePrec(Thyra::defaultLinearOpSource(thyraA),thyra_mv,&*preconObj_,Thyra::SUPPORT_SOLVE_UNSPECIFIED);
262  RCP<const Thyra::LinearOpBase<double> > preconditioner = preconObj_->getUnspecifiedPrecOp();
263  Teko_DEBUG_EXPR(timer.stop());
264  Teko_DEBUG_MSG("EBP::rebuild initialize prec time = " << timer.totalElapsedTime(),2);
265 
266  Teko_DEBUG_EXPR(timer.start(true));
267  SetOperator(preconditioner,false);
268  Teko_DEBUG_EXPR(timer.stop());
269  Teko_DEBUG_MSG("EBP::rebuild set operator time = " << timer.totalElapsedTime(),2);
270 
271  TEUCHOS_ASSERT(preconObj_!=Teuchos::null);
272  TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null);
273  TEUCHOS_ASSERT(firstBuildComplete_==true);
274 }
275 
285 Teuchos::RCP<PreconditionerState> EpetraBlockPreconditioner::getPreconditionerState()
286 {
287  Teuchos::RCP<Preconditioner> bp = rcp_dynamic_cast<Preconditioner>(preconObj_);
288 
289  if(bp!=Teuchos::null)
290  return bp->getStateObject();
291 
292  return Teuchos::null;
293 }
294 
304 Teuchos::RCP<const PreconditionerState> EpetraBlockPreconditioner::getPreconditionerState() const
305 {
306  Teuchos::RCP<const Preconditioner> bp = rcp_dynamic_cast<const Preconditioner>(preconObj_);
307 
308  if(bp!=Teuchos::null)
309  return bp->getStateObject();
310 
311  return Teuchos::null;
312 }
313 
314 Teuchos::RCP<const Thyra::LinearOpBase<double> > EpetraBlockPreconditioner::extractLinearOp(const Teuchos::RCP<const Epetra_Operator> & A) const
315 {
316  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
317  const RCP<const EpetraOperatorWrapper> & eow = rcp_dynamic_cast<const EpetraOperatorWrapper>(A);
318 
319  // if it is an EpetraOperatorWrapper, then get the Thyra operator
320  if(eow!=Teuchos::null)
321  return eow->getThyraOp();
322 
323  // otherwise wrap it up as a thyra operator
324  return Thyra::epetraLinearOp(A);
325 }
326 
327 Teuchos::RCP<const MappingStrategy> EpetraBlockPreconditioner::extractMappingStrategy(const Teuchos::RCP<const Epetra_Operator> & A) const
328 {
329  // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator
330  const RCP<const EpetraOperatorWrapper> & eow = rcp_dynamic_cast<const EpetraOperatorWrapper>(A);
331 
332  // if it is an EpetraOperatorWrapper, then get the Thyra operator
333  if(eow!=Teuchos::null)
334  return eow->getMapStrategy();
335 
336  // otherwise wrap it up as a thyra operator
337  RCP<const Epetra_Map> range = rcpFromRef(A->OperatorRangeMap());
338  RCP<const Epetra_Map> domain = rcpFromRef(A->OperatorDomainMap());
339  return rcp(new BasicMappingStrategy(range,domain,A->Comm()));
340 }
341 
342 } // end namespace Epetra
343 } // 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.