Teko Version of the Day
Loading...
Searching...
No Matches
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
60namespace Teko {
61namespace Epetra {
62
63using Teuchos::RCP;
64using Teuchos::rcp;
65using Teuchos::rcpFromRef;
66using Teuchos::rcp_dynamic_cast;
67
74EpetraBlockPreconditioner::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
98void 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
142void 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
188void 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
235void 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
285Teuchos::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
304Teuchos::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
314Teuchos::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
327Teuchos::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 Teuchos::RCP< PreconditionerState > getPreconditionerState()
virtual void initPreconditioner(bool clearOld=false)
Build the underlying data structure for the preconditioner.
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 rebuildPreconditioner(const Teuchos::RCP< const Epetra_Operator > &A)
Rebuild this preconditioner from an Epetra_Operator passed in this to object.
const RCP< const MappingStrategy > getMapStrategy() const
Get the mapping strategy for this wrapper (translate between Thyra and Epetra)
const RCP< const Thyra::LinearOpBase< double > > getThyraOp() const
Return the thyra operator associated with this wrapper.
Flip a mapping strategy object around to give the "inverse" mapping strategy.