Teko  Version of the Day
Teko_PreconditionerFactory.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_Config.h"
48 #include "Teko_PreconditionerFactory.hpp"
49 
50 #include "Teko_InverseLibrary.hpp"
51 #include "Teko_Preconditioner.hpp"
52 
53 // Specific preconditioners included for dynamic creation
54 #include "Teko_JacobiPreconditionerFactory.hpp"
55 #include "Teko_GaussSeidelPreconditionerFactory.hpp"
56 #include "Teko_AddPreconditionerFactory.hpp"
57 #include "Teko_MultPreconditionerFactory.hpp"
58 #include "Teko_LU2x2PreconditionerFactory.hpp"
59 #include "Teko_IterativePreconditionerFactory.hpp"
60 #include "Teko_DiagnosticPreconditionerFactory.hpp"
61 #include "Teko_DiagonallyScaledPreconditionerFactory.hpp"
62 #include "Teko_DiagonalPreconditionerFactory.hpp"
63 #include "Teko_ProbingPreconditionerFactory.hpp"
64 #include "Teko_IdentityPreconditionerFactory.hpp"
65 #include "NS/Teko_LSCPreconditionerFactory.hpp"
66 #include "NS/Teko_SIMPLEPreconditionerFactory.hpp"
67 
68 #ifdef Teko_ENABLE_ML_SMOOTHERS
69 #include "Teko_SmootherPreconditionerFactory.hpp"
70 #include "Teko_MLPreconditionerFactory.hpp"
71 #endif
72 
73 
74 #include "Thyra_DefaultPreconditioner.hpp"
75 
76 using namespace Thyra;
77 using Teuchos::RCP;
78 
79 namespace Teko {
81 
83 bool PreconditionerFactory::isCompatible(const Thyra::LinearOpSourceBase<double> &fwdOpSrc) const
84 {
85  RCP<const Thyra::LinearOpBase<double> > A = fwdOpSrc.getOp();
86  return A!=Teuchos::null;
87 }
88 
90 RCP<Thyra::PreconditionerBase<double> > PreconditionerFactory::createPrec() const
91 {
92  // build a preconditioner, give it some inital state
93  RCP<Preconditioner> bp = rcp(new Preconditioner());
94  bp->setStateObject(buildPreconditionerState());
95  bp->getStateObject()->setInitialized(false);
96 
97  return bp;
98 }
99 
101 void PreconditionerFactory::initializePrec(const RCP<const LinearOpSourceBase<double> > & ASrc,
102  PreconditionerBase<double> * prec,
103  const ESupportSolveUse supportSolveUse) const
104 {
105  // get the blocked linear operator
106  LinearOp A = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(ASrc->getOp());
107 
108  Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec);
109  TEUCHOS_ASSERT(blkPrec!=0);
110 
111  // grab the state object
112  RCP<PreconditionerState> state = blkPrec->getStateObject();
113  state->setInitialized(false);
114 
115  // build the preconditioner
116  const RCP<const LinearOpBase<double> > M = buildPreconditionerOperator(A,*state);
117 
118  // set the request handler for the
119  setOpRequestHandler(*this,M);
120 
121  // must first cast that to be initialized
122  DefaultPreconditioner<double> & dPrec = Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
123  dPrec.initializeUnspecified(Teuchos::rcp_const_cast<LinearOpBase<double> >(M));
124 }
125 
127 void PreconditionerFactory::initializePrec(const RCP<const LinearOpSourceBase<double> > & ASrc,
128  const RCP<const Thyra::MultiVectorBase<double> > & solnVec,
129  PreconditionerBase<double> * prec,
130  const ESupportSolveUse supportSolveUse) const
131 {
132  Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec);
133  blkPrec->setSourceVector(Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(solnVec));
134 
135  initializePrec(ASrc,prec,supportSolveUse);
136 }
137 
139 void PreconditionerFactory::uninitializePrec(PreconditionerBase<double> * prec,
140  RCP<const LinearOpSourceBase<double> > * fwdOpSrc,
141  ESupportSolveUse *supportSolveUse) const
142 {
143  // Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec);
144 
145  // what do I do here?
146  TEUCHOS_TEST_FOR_EXCEPT_MSG(true,"\"PreconditionerFactory::uninitializePrec not implemented\"");
147 }
148 
149 // for ParameterListAcceptor
151 
153 void PreconditionerFactory::setParameterList(const RCP<Teuchos::ParameterList> & paramList)
154 {
155  paramList_ = paramList;
156 }
157 
159 RCP< Teuchos::ParameterList > PreconditionerFactory::getNonconstParameterList()
160 {
161  return paramList_;
162 }
163 
165 RCP< Teuchos::ParameterList > PreconditionerFactory::unsetParameterList()
166 {
167  RCP<Teuchos::ParameterList> _paramList = paramList_;
168  paramList_ = Teuchos::null;
169  return _paramList;
170 }
171 
173 void PreconditionerFactory::setInverseLibrary(const RCP<const InverseLibrary> & il)
174 {
175  inverseLibrary_ = il;
176 }
177 
179 RCP<const InverseLibrary> PreconditionerFactory::getInverseLibrary() const
180 {
181  // lazily build the inverse library only when needed
182  if(inverseLibrary_==Teuchos::null)
183  return InverseLibrary::buildFromStratimikos();
184 
185  return inverseLibrary_;
186 }
187 
189 // Static members and methods
191 
193 void PreconditionerFactory::setOpRequestHandler(const RequestHandlerContainer & rhc,const LinearOp & op)
194 {
195  ModifiableLinearOp mlo = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(op);
196 
197  // conditionally set the request handler
198  RCP<RequestHandlerContainer> reqHandCont = Teuchos::rcp_dynamic_cast<RequestHandlerContainer>(mlo);
199  if(reqHandCont!=Teuchos::null) {
200  reqHandCont->setRequestHandler(rhc.getRequestHandler());
201  }
202  else {
203  // is null
204  }
205 
206 }
207 
209 CloneFactory<PreconditionerFactory> PreconditionerFactory::precFactoryBuilder_;
210 
225 RCP<PreconditionerFactory>
226 PreconditionerFactory::buildPreconditionerFactory(const std::string & name,
227  const Teuchos::ParameterList & settings,
228  const RCP<const InverseLibrary> & invLib)
229 {
230  Teko_DEBUG_SCOPE("PreconditionerFactory::buildPreconditionerFactory",10);
231 
232  // initialize the defaults if necessary
233  if(precFactoryBuilder_.cloneCount()==0) initializePrecFactoryBuilder();
234 
235  // request the preconditioner factory from the CloneFactory
236  RCP<PreconditionerFactory> precFact = precFactoryBuilder_.build(name);
237 
238  Teko_DEBUG_MSG_BEGIN(5);
239  DEBUG_STREAM << "Looked up \"" << name << "\"" << std::endl;
240  DEBUG_STREAM << "Built " << precFact << std::endl;
241  Teko_DEBUG_MSG_END();
242 
243  if(precFact==Teuchos::null)
244  return Teuchos::null;
245 
246  // add in the inverse library
247  if(invLib!=Teuchos::null) {
248  precFact->setInverseLibrary(invLib);
249  precFact->setRequestHandler(invLib->getRequestHandler());
250  }
251 
252  // now that inverse library has been set,
253  // pass in the parameter list
254  precFact->initializeFromParameterList(settings);
255 
256  return precFact;
257 }
258 
272 void PreconditionerFactory::addPreconditionerFactory(const std::string & name,const RCP<Cloneable> & clone)
273 {
274  // initialize the defaults if necessary
275  if(precFactoryBuilder_.cloneCount()==0) initializePrecFactoryBuilder();
276 
277  // add clone to builder
278  precFactoryBuilder_.addClone(name,clone);
279 }
280 
282 void PreconditionerFactory::initializePrecFactoryBuilder()
283 {
284  RCP<Cloneable> clone;
285 
286  // add various preconditioners to factory
287  clone = rcp(new AutoClone<LU2x2PreconditionerFactory>());
288  precFactoryBuilder_.addClone("Block LU2x2",clone);
289 
290  clone = rcp(new AutoClone<JacobiPreconditionerFactory>());
291  precFactoryBuilder_.addClone("Block Jacobi",clone);
292 
294  precFactoryBuilder_.addClone("Block Gauss-Seidel",clone);
295 
296  clone = rcp(new AutoClone<AddPreconditionerFactory>());
297  precFactoryBuilder_.addClone("Block Add",clone);
298 
299  clone = rcp(new AutoClone<MultPreconditionerFactory>());
300  precFactoryBuilder_.addClone("Block Multiply",clone);
301 
302  clone = rcp(new AutoClone<NS::LSCPreconditionerFactory>());
303  precFactoryBuilder_.addClone("NS LSC",clone);
304 
306  precFactoryBuilder_.addClone("NS SIMPLE",clone);
307 
309  precFactoryBuilder_.addClone("Iterative Preconditioner",clone);
310 
311  clone = rcp(new AutoClone<DiagonalPreconditionerFactory>());
312  precFactoryBuilder_.addClone("Explicit Diagonal Preconditioner",clone);
313 
315  precFactoryBuilder_.addClone("Diagnostic Inverse",clone);
316 
318  precFactoryBuilder_.addClone("Diagonal Scaling",clone);
319 
320  clone = rcp(new AutoClone<IdentityPreconditionerFactory>());
321  precFactoryBuilder_.addClone("Identity",clone);
322 
323 #ifdef Teko_ENABLE_Isorropia
324  clone = rcp(new AutoClone<ProbingPreconditionerFactory>());
325  precFactoryBuilder_.addClone("Probing Preconditioner",clone);
326 #endif
327 
328 #ifdef Teko_ENABLE_ML_SMOOTHERS
329  clone = rcp(new AutoClone<MLPreconditionerFactory>());
330  precFactoryBuilder_.addClone("Blocked ML Preconditioner",clone);
331 #endif
332 }
333 
334 void PreconditionerFactory::getPreconditionerFactoryNames(std::vector<std::string> & names)
335 {
336  // initialize the defaults if necessary
337  if(precFactoryBuilder_.cloneCount()==0) initializePrecFactoryBuilder();
338  precFactoryBuilder_.getCloneNames(names);
339 }
340 
341 } // end namespace Teko
virtual void setRequestHandler(const Teuchos::RCP< RequestHandler > &rh)=0
Set the request handler with pointers to the appropriate callbacks.
virtual void setSourceVector(const RCP< Thyra::MultiVectorBase< double > > &srcVec)
An extension of the Thyra::DefaultPreconditioner class with some specializations useful for use withi...
virtual Teuchos::RCP< RequestHandler > getRequestHandler() const =0
Get the request handler with pointers to the appropriate callbacks.