Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_NeumannSeriesPreconditionerFactory.hpp
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 #ifndef __Teko_NeumannSeriesPreconditionerFactory_hpp__
48 #define __Teko_NeumannSeriesPreconditionerFactory_hpp__
49 
50 #include "Teko_NeumannSeriesPreconditionerFactoryDecl.hpp"
51 
52 #include "Thyra_DefaultPreconditioner.hpp"
53 #include "Thyra_DefaultPreconditioner.hpp"
54 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
55 #include "Thyra_DefaultAddedLinearOp.hpp"
56 #include "Thyra_DefaultMultipliedLinearOp.hpp"
57 #include "Thyra_DefaultIdentityLinearOp.hpp"
58 
59 #include "Teuchos_Array.hpp"
60 #include "Teuchos_StandardParameterEntryValidators.hpp"
61 
62 namespace Teko {
63 
64 using Teuchos::RCP;
65 using Teuchos::rcp;
66 
67 static RCP<Teuchos::StringToIntegralParameterEntryValidator<Teko::DiagonalType> > scalingTypeVdtor;
68 
69 template <typename ScalarT>
70 NeumannSeriesPreconditionerFactory<ScalarT>::NeumannSeriesPreconditionerFactory()
71  : numberOfTerms_(1), scalingType_(Teko::NotDiag) {}
72 
74 template <typename ScalarT>
75 bool NeumannSeriesPreconditionerFactory<ScalarT>::isCompatible(
76  const Thyra::LinearOpSourceBase<ScalarT> & /* fwdOpSrc */) const {
77  return true;
78 }
79 
81 template <typename ScalarT>
82 RCP<Thyra::PreconditionerBase<ScalarT> > NeumannSeriesPreconditionerFactory<ScalarT>::createPrec()
83  const {
84  return rcp(new Thyra::DefaultPreconditioner<ScalarT>());
85 }
86 
95 template <typename ScalarT>
96 void NeumannSeriesPreconditionerFactory<ScalarT>::initializePrec(
97  const RCP<const Thyra::LinearOpSourceBase<ScalarT> > &fwdOpSrc,
98  Thyra::PreconditionerBase<ScalarT> *prec,
99  const Thyra::ESupportSolveUse /* supportSolveUse */) const {
100  using Thyra::add;
101  using Thyra::multiply;
102  using Thyra::scale;
103 
104  RCP<const Thyra::LinearOpBase<ScalarT> > M; // left-preconditioner
105  RCP<const Thyra::LinearOpBase<ScalarT> > A = fwdOpSrc->getOp();
106  if (scalingType_ != Teko::NotDiag) {
107  M = Teko::getInvDiagonalOp(A, scalingType_);
108  A = Thyra::multiply(M, A);
109  }
110 
111  RCP<const Thyra::LinearOpBase<ScalarT> > id = Thyra::identity<ScalarT>(A->range()); // I
112  RCP<const Thyra::LinearOpBase<ScalarT> > idMA = add(id, scale(-1.0, A)); // I - A
113 
114  RCP<const Thyra::LinearOpBase<ScalarT> > precOp;
115  if (numberOfTerms_ == 1) {
116  // no terms requested, just return identity matrix
117  precOp = id;
118  } else {
119  int iters = numberOfTerms_ - 1;
120  // use Horner's method to computed higher order polynomials
121  precOp = add(scale(2.0, id), scale(-1.0, A)); // I + (I - A)
122  for (int i = 0; i < iters; i++) precOp = add(id, multiply(idMA, precOp)); // I + (I - A) * p
123  }
124 
125  // multiply by the preconditioner if it exists
126  if (M != Teuchos::null) precOp = Thyra::multiply(precOp, M);
127 
128  // must first cast that to be initialized
129  Thyra::DefaultPreconditioner<ScalarT> &dPrec =
130  Teuchos::dyn_cast<Thyra::DefaultPreconditioner<ScalarT> >(*prec);
131 
132  // this const-cast is unfortunate...needs to be fixed (larger than it seems!) ECC FIXME!
133  dPrec.initializeUnspecified(Teuchos::rcp_const_cast<Thyra::LinearOpBase<ScalarT> >(precOp));
134 }
135 
137 template <typename ScalarT>
138 void NeumannSeriesPreconditionerFactory<ScalarT>::uninitializePrec(
139  Thyra::PreconditionerBase<ScalarT> *prec,
140  RCP<const Thyra::LinearOpSourceBase<ScalarT> > * /* fwdOpSrc */,
141  Thyra::ESupportSolveUse * /* supportSolveUse */) const {
142  Thyra::DefaultPreconditioner<ScalarT> &dPrec =
143  Teuchos::dyn_cast<Thyra::DefaultPreconditioner<ScalarT> >(*prec);
144 
145  // wipe out any old preconditioner
146  dPrec.uninitialize();
147 }
148 
149 // for ParameterListAcceptor
150 
152 template <typename ScalarT>
153 void NeumannSeriesPreconditionerFactory<ScalarT>::setParameterList(
154  const RCP<Teuchos::ParameterList> &paramList) {
155  TEUCHOS_TEST_FOR_EXCEPT(paramList == Teuchos::null);
156 
157  // check the parameters are correct
158  paramList->validateParametersAndSetDefaults(*getValidParameters(), 0);
159 
160  // store the parameter list
161  paramList_ = paramList;
162 
163  numberOfTerms_ = paramList_->get<int>("Number of Terms");
164 
165  // get the scaling type
166  scalingType_ = Teko::NotDiag;
167  const Teuchos::ParameterEntry *entry = paramList_->getEntryPtr("Scaling Type");
168  if (entry != NULL) scalingType_ = scalingTypeVdtor->getIntegralValue(*entry);
169 }
170 
172 template <typename ScalarT>
173 RCP<const Teuchos::ParameterList> NeumannSeriesPreconditionerFactory<ScalarT>::getValidParameters()
174  const {
175  static RCP<Teuchos::ParameterList> validPL;
176 
177  // only fill valid parameter list once
178  if (validPL == Teuchos::null) {
179  RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList());
180 
181  // build the validator for scaling type
182  scalingTypeVdtor = Teuchos::stringToIntegralParameterEntryValidator<DiagonalType>(
183  Teuchos::tuple<std::string>("Diagonal", "Lumped", "AbsRowSum", "None"),
184  Teuchos::tuple<Teko::DiagonalType>(Teko::Diagonal, Teko::Lumped, Teko::AbsRowSum,
185  Teko::NotDiag),
186  "Scaling Type");
187 
188  pl->set<int>("Number of Terms", 1,
189  "The number of terms to use in the Neumann series expansion.");
190  pl->set("Scaling Type", "None", "The number of terms to use in the Neumann series expansion.",
191  scalingTypeVdtor);
192 
193  validPL = pl;
194  }
195 
196  return validPL;
197 }
198 
200 template <typename ScalarT>
201 RCP<Teuchos::ParameterList> NeumannSeriesPreconditionerFactory<ScalarT>::unsetParameterList() {
202  Teuchos::RCP<Teuchos::ParameterList> oldList = paramList_;
203  paramList_ = Teuchos::null;
204  return oldList;
205 }
206 
208 template <typename ScalarT>
209 RCP<const Teuchos::ParameterList> NeumannSeriesPreconditionerFactory<ScalarT>::getParameterList()
210  const {
211  return paramList_;
212 }
213 
215 template <typename ScalarT>
216 RCP<Teuchos::ParameterList>
217 NeumannSeriesPreconditionerFactory<ScalarT>::getNonconstParameterList() {
218  return paramList_;
219 }
220 
221 template <typename ScalarT>
222 std::string NeumannSeriesPreconditionerFactory<ScalarT>::description() const {
223  std::ostringstream oss;
224  oss << "Teko::NeumannSeriesPreconditionerFactory";
225  return oss.str();
226 }
227 
228 } // end namespace Teko
229 
230 #endif