Teko  Version of the Day
 All Classes Files Functions Variables Pages
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 #ifdef TEKO_HAVE_EPETRA
63 #include "Teko_DiagonalPreconditionerFactory.hpp"
64 #include "Teko_ProbingPreconditionerFactory.hpp"
65 #endif
66 #include "Teko_IdentityPreconditionerFactory.hpp"
67 #include "NS/Teko_LSCPreconditionerFactory.hpp"
68 #include "NS/Teko_SIMPLEPreconditionerFactory.hpp"
69 #include "NS/Teko_TimingsSIMPLEPreconditionerFactory.hpp"
70 
71 #ifdef Teko_ENABLE_ML_SMOOTHERS
72 #include "Teko_SmootherPreconditionerFactory.hpp"
73 #include "Teko_MLPreconditionerFactory.hpp"
74 #endif
75 
76 #include "Thyra_DefaultPreconditioner.hpp"
77 
78 using namespace Thyra;
79 using Teuchos::RCP;
80 
81 namespace Teko {
83 
85 bool PreconditionerFactory::isCompatible(const Thyra::LinearOpSourceBase<double> &fwdOpSrc) const {
86  RCP<const Thyra::LinearOpBase<double> > A = fwdOpSrc.getOp();
87  return A != Teuchos::null;
88 }
89 
91 RCP<Thyra::PreconditionerBase<double> > PreconditionerFactory::createPrec() const {
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  // get the blocked linear operator
105  LinearOp A = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(ASrc->getOp());
106 
107  Preconditioner *blkPrec = dynamic_cast<Preconditioner *>(prec);
108  TEUCHOS_ASSERT(blkPrec != 0);
109 
110  // grab the state object
111  RCP<PreconditionerState> state = blkPrec->getStateObject();
112  state->setInitialized(false);
113 
114  // build the preconditioner
115  const RCP<const LinearOpBase<double> > M = buildPreconditionerOperator(A, *state);
116 
117  // set the request handler for the
118  setOpRequestHandler(*this, M);
119 
120  // must first cast that to be initialized
121  DefaultPreconditioner<double> &dPrec = Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
122  dPrec.initializeUnspecified(Teuchos::rcp_const_cast<LinearOpBase<double> >(M));
123 }
124 
126 void PreconditionerFactory::initializePrec(
127  const RCP<const LinearOpSourceBase<double> > &ASrc,
128  const RCP<const Thyra::MultiVectorBase<double> > &solnVec, PreconditionerBase<double> *prec,
129  const ESupportSolveUse supportSolveUse) const {
130  Preconditioner *blkPrec = dynamic_cast<Preconditioner *>(prec);
131  blkPrec->setSourceVector(Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(solnVec));
132 
133  initializePrec(ASrc, prec, supportSolveUse);
134 }
135 
137 void PreconditionerFactory::uninitializePrec(
138  PreconditionerBase<double> * /* prec */,
139  RCP<const LinearOpSourceBase<double> > * /* fwdOpSrc */,
140  ESupportSolveUse * /* supportSolveUse */) const {
141  // Preconditioner * blkPrec = dynamic_cast<Preconditioner *>(prec);
142 
143  // what do I do here?
144  TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "\"PreconditionerFactory::uninitializePrec not implemented\"");
145 }
146 
147 // for ParameterListAcceptor
149 
151 void PreconditionerFactory::setParameterList(const RCP<Teuchos::ParameterList> &paramList) {
152  paramList_ = paramList;
153 }
154 
156 RCP<Teuchos::ParameterList> PreconditionerFactory::getNonconstParameterList() { return paramList_; }
157 
159 RCP<Teuchos::ParameterList> PreconditionerFactory::unsetParameterList() {
160  RCP<Teuchos::ParameterList> _paramList = paramList_;
161  paramList_ = Teuchos::null;
162  return _paramList;
163 }
164 
166 void PreconditionerFactory::setInverseLibrary(const RCP<const InverseLibrary> &il) {
167  inverseLibrary_ = il;
168 }
169 
171 RCP<const InverseLibrary> PreconditionerFactory::getInverseLibrary() const {
172  // lazily build the inverse library only when needed
173  if (inverseLibrary_ == Teuchos::null) return InverseLibrary::buildFromStratimikos();
174 
175  return inverseLibrary_;
176 }
177 
179 // Static members and methods
181 
183 void PreconditionerFactory::setOpRequestHandler(const RequestHandlerContainer &rhc,
184  const LinearOp &op) {
185  ModifiableLinearOp mlo = Teuchos::rcp_const_cast<Thyra::LinearOpBase<double> >(op);
186 
187  // conditionally set the request handler
188  RCP<RequestHandlerContainer> reqHandCont =
189  Teuchos::rcp_dynamic_cast<RequestHandlerContainer>(mlo);
190  if (reqHandCont != Teuchos::null) {
191  reqHandCont->setRequestHandler(rhc.getRequestHandler());
192  } else {
193  // is null
194  }
195 }
196 
198 CloneFactory<PreconditionerFactory> PreconditionerFactory::precFactoryBuilder_;
199 
214 RCP<PreconditionerFactory> PreconditionerFactory::buildPreconditionerFactory(
215  const std::string &name, const Teuchos::ParameterList &settings,
216  const RCP<const InverseLibrary> &invLib) {
217  Teko_DEBUG_SCOPE("PreconditionerFactory::buildPreconditionerFactory", 10);
218 
219  // initialize the defaults if necessary
220  if (precFactoryBuilder_.cloneCount() == 0) initializePrecFactoryBuilder();
221 
222  // request the preconditioner factory from the CloneFactory
223  RCP<PreconditionerFactory> precFact = precFactoryBuilder_.build(name);
224 
225  Teko_DEBUG_MSG_BEGIN(5);
226  DEBUG_STREAM << "Looked up \"" << name << "\"" << std::endl;
227  DEBUG_STREAM << "Built " << precFact << std::endl;
228  Teko_DEBUG_MSG_END();
229 
230  if (precFact == Teuchos::null) return Teuchos::null;
231 
232  // add in the inverse library
233  if (invLib != Teuchos::null) {
234  precFact->setInverseLibrary(invLib);
235  precFact->setRequestHandler(invLib->getRequestHandler());
236  }
237 
238  // now that inverse library has been set,
239  // pass in the parameter list
240  precFact->initializeFromParameterList(settings);
241 
242  return precFact;
243 }
244 
258 void PreconditionerFactory::addPreconditionerFactory(const std::string &name,
259  const RCP<Cloneable> &clone) {
260  // initialize the defaults if necessary
261  if (precFactoryBuilder_.cloneCount() == 0) initializePrecFactoryBuilder();
262 
263  // add clone to builder
264  precFactoryBuilder_.addClone(name, clone);
265 }
266 
268 void PreconditionerFactory::initializePrecFactoryBuilder() {
269  RCP<Cloneable> clone;
270 
271  // add various preconditioners to factory
272  clone = rcp(new AutoClone<LU2x2PreconditionerFactory>());
273  precFactoryBuilder_.addClone("Block LU2x2", clone);
274 
275  clone = rcp(new AutoClone<JacobiPreconditionerFactory>());
276  precFactoryBuilder_.addClone("Block Jacobi", clone);
277 
279  precFactoryBuilder_.addClone("Block Gauss-Seidel", clone);
280 
281  clone = rcp(new AutoClone<AddPreconditionerFactory>());
282  precFactoryBuilder_.addClone("Block Add", clone);
283 
284  clone = rcp(new AutoClone<MultPreconditionerFactory>());
285  precFactoryBuilder_.addClone("Block Multiply", clone);
286 
287  clone = rcp(new AutoClone<NS::LSCPreconditionerFactory>());
288  precFactoryBuilder_.addClone("NS LSC", clone);
289 
291  precFactoryBuilder_.addClone("NS SIMPLE", clone);
292 
294  precFactoryBuilder_.addClone("NS SIMPLE-Timed", clone);
295 
297  precFactoryBuilder_.addClone("Iterative Preconditioner", clone);
298 
299 #ifdef TEKO_HAVE_EPETRA
300  clone = rcp(new AutoClone<DiagonalPreconditionerFactory>());
301  precFactoryBuilder_.addClone("Explicit Diagonal Preconditioner", clone);
302 #endif
303 
305  precFactoryBuilder_.addClone("Diagnostic Inverse", clone);
306 
308  precFactoryBuilder_.addClone("Diagonal Scaling", clone);
309 
310  clone = rcp(new AutoClone<IdentityPreconditionerFactory>());
311  precFactoryBuilder_.addClone("Identity", clone);
312 
313 #if defined(Teko_ENABLE_Isorropia) && defined(TEKO_HAVE_EPETRA)
314  clone = rcp(new AutoClone<ProbingPreconditionerFactory>());
315  precFactoryBuilder_.addClone("Probing Preconditioner", clone);
316 #endif
317 
318 #ifdef Teko_ENABLE_ML_SMOOTHERS
319  clone = rcp(new AutoClone<MLPreconditionerFactory>());
320  precFactoryBuilder_.addClone("Blocked ML Preconditioner", clone);
321 #endif
322 }
323 
324 void PreconditionerFactory::getPreconditionerFactoryNames(std::vector<std::string> &names) {
325  // initialize the defaults if necessary
326  if (precFactoryBuilder_.cloneCount() == 0) initializePrecFactoryBuilder();
327  precFactoryBuilder_.getCloneNames(names);
328 }
329 
330 } // end namespace Teko
virtual void setRequestHandler(const Teuchos::RCP< RequestHandler > &rh)=0
Set the request handler with pointers to the appropriate callbacks.
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.