Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_SmootherPreconditionerFactory.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Teko: A package for block and physics based preconditioning
4 //
5 // Copyright 2010 NTESS and the Teko contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 // Teko includes
11 #include "Teko_SmootherPreconditionerFactory.hpp"
12 
13 #include "Teko_PreconditionerInverseFactory.hpp"
14 #include "Thyra_MultiVectorStdOps.hpp"
15 
16 namespace Teko {
17 
18 // A small utility class to help distinguish smoothers
19 class SmootherRequestMesg : public RequestMesg {
20  public:
21  SmootherRequestMesg(unsigned int block)
22  : RequestMesg("__smoother_request_message__"), block_(block) {}
23 
24  unsigned int getBlock() const { return block_; }
25 
26  private:
27  unsigned int block_;
28 };
29 
33 
34 SmootherLinearOp::SmootherLinearOp(const LinearOp& A, const LinearOp& invM,
35  unsigned int applications, bool useDestAsInitialGuess)
36  : A_(A),
37  invM_(invM),
38  applications_(applications),
39  initialGuessType_(Unspecified),
40  requestMesg_(Teuchos::null) {
41  // set initial guess type
42  initialGuessType_ = useDestAsInitialGuess ? DestAsInitialGuess : NoInitialGuess;
43 }
44 
45 SmootherLinearOp::SmootherLinearOp(const LinearOp& A, const LinearOp& invM,
46  unsigned int applications, unsigned int block)
47  : A_(A),
48  invM_(invM),
49  applications_(applications),
50  initialGuessType_(RequestInitialGuess),
51  requestMesg_(Teuchos::null) {
52  requestMesg_ = Teuchos::rcp(new SmootherRequestMesg(block));
53 }
54 
55 void SmootherLinearOp::implicitApply(const MultiVector& b, MultiVector& x, const double alpha,
56  const double beta) const {
57  using Teuchos::RCP;
58 
59  MultiVector residual = deepcopy(b); // residual = b
60  MultiVector scrap = deepcopy(b); // scrap = b
61  MultiVector error; // location for initial guess
62 
63  // construct initial guess: required to assign starting point for destination
64  // vector appropriately
65  switch (initialGuessType_) {
66  case RequestInitialGuess:
67  // get initial guess from request handler
68  error = deepcopy(getRequestHandler()->request<MultiVector>(*requestMesg_));
69  Thyra::assign<double>(x.ptr(), *error); // x = error (initial guess)
70  break;
71  case DestAsInitialGuess:
72  error = deepcopy(x); // error = x
73  break;
74  case NoInitialGuess:
75  Thyra::assign<double>(x.ptr(), 0.0); // x = 0
76  error = deepcopy(x); // error = x
77  break;
78  case Unspecified:
79  default: TEUCHOS_ASSERT(false);
80  }
81 
82  for (unsigned int current = 0; current < applications_; ++current) {
83  // compute current residual
84  Teko::applyOp(A_, error, scrap);
85  Teko::update(-1.0, scrap, 1.0, residual); // residual = residual-A*error
86 
87  // compute appoximate correction using residual
88  Thyra::assign(error.ptr(), 0.0); // set error to zero
89  Teko::applyOp(invM_, residual, error);
90 
91  // update solution with error
92  Teko::update(1.0, error, 1.0, x); // x = x+error
93  }
94 }
95 
97 void SmootherLinearOp::setRequestHandler(const Teuchos::RCP<RequestHandler>& rh) {
98  Teko_DEBUG_SCOPE("SmootherLinearOp::setRequestHandler", 10);
99  requestHandler_ = rh;
100 }
101 
103 Teuchos::RCP<RequestHandler> SmootherLinearOp::getRequestHandler() const {
104  Teko_DEBUG_SCOPE("SmootherLinearOp::getRequestHandler", 10);
105  return requestHandler_;
106 }
107 
108 LinearOp buildSmootherLinearOp(const LinearOp& A, const LinearOp& invM, unsigned int applications,
109  bool useDestAsInitialGuess) {
110  return Teuchos::rcp(new SmootherLinearOp(A, invM, applications, useDestAsInitialGuess));
111 }
112 
113 LinearOp buildSmootherLinearOp(const LinearOp& A, const LinearOp& invM, unsigned int applications,
114  unsigned int initialGuessBlock) {
115  return Teuchos::rcp(new SmootherLinearOp(A, invM, applications, initialGuessBlock));
116 }
117 
121 
123 SmootherPreconditionerFactory::SmootherPreconditionerFactory()
124  : sweepCount_(0),
125  initialGuessType_(Unspecified),
126  initialGuessBlock_(0),
127  precFactory_(Teuchos::null) {}
128 
132 LinearOp SmootherPreconditionerFactory::buildPreconditionerOperator(
133  LinearOp& lo, PreconditionerState& state) const {
134  TEUCHOS_TEST_FOR_EXCEPTION(
135  precFactory_ == Teuchos::null, std::runtime_error,
136  "ERROR: Teko::SmootherPreconditionerFactory::buildPreconditionerOperator requires that a "
137  << "preconditioner factory has been set. Currently it is null!");
138 
139  // preconditions
140  TEUCHOS_ASSERT(sweepCount_ > 0);
141  TEUCHOS_ASSERT(initialGuessType_ != Unspecified);
142  TEUCHOS_ASSERT(precFactory_ != Teuchos::null);
143 
144  // build user specified preconditioner
145  ModifiableLinearOp& invM = state.getModifiableOp("prec");
146  if (invM == Teuchos::null)
147  invM = Teko::buildInverse(*precFactory_, lo);
148  else
149  Teko::rebuildInverse(*precFactory_, lo, invM);
150 
151  // conditional on initial guess type, build the smoother
152  switch (initialGuessType_) {
153  case RequestInitialGuess:
154  return buildSmootherLinearOp(lo, invM, sweepCount_, initialGuessBlock_);
155  case DestAsInitialGuess:
156  return buildSmootherLinearOp(lo, invM, sweepCount_, true); // use an initial guess
157  case NoInitialGuess:
158  return buildSmootherLinearOp(lo, invM, sweepCount_, false); // no initial guess
159  case Unspecified:
160  default: TEUCHOS_ASSERT(false);
161  }
162 
163  // should never get here
164  TEUCHOS_ASSERT(false);
165  return Teuchos::null;
166 }
167 
171 void SmootherPreconditionerFactory::initializeFromParameterList(
172  const Teuchos::ParameterList& settings) {
173  // declare all strings used by this initialization routine
175 
176  const std::string str_sweepCount = "Sweep Count";
177  const std::string str_initialGuessBlock = "Initial Guess Block";
178  const std::string str_destAsInitialGuess = "Destination As Initial Guess";
179  const std::string str_precType = "Preconditioner Type";
180 
181  // default parameters
183 
184  initialGuessType_ = Unspecified;
185  initialGuessBlock_ = 0;
186  sweepCount_ = 0;
187  precFactory_ = Teuchos::null;
188 
189  // get sweep counts
191 
192  if (settings.isParameter(str_sweepCount)) sweepCount_ = settings.get<int>(str_sweepCount);
193 
194  // get initial guess
196 
197  if (settings.isParameter(str_initialGuessBlock)) {
198  initialGuessBlock_ = settings.get<int>(str_initialGuessBlock);
199  initialGuessType_ = RequestInitialGuess;
200  }
201 
202  if (settings.isParameter(str_destAsInitialGuess)) {
203  bool useDest = settings.get<bool>(str_destAsInitialGuess);
204  if (useDest) {
205  TEUCHOS_TEST_FOR_EXCEPTION(initialGuessType_ != Unspecified, std::runtime_error,
206  "Cannot set both \"" << str_initialGuessBlock << "\" and \""
207  << str_destAsInitialGuess << "\"");
208 
209  initialGuessType_ = DestAsInitialGuess;
210  }
211  }
212 
213  // safe to assume if the other values are not turned on there is no initial guess
214  if (initialGuessType_ == Unspecified) initialGuessType_ = NoInitialGuess;
215 
216  // get preconditioner factory
218 
219  TEUCHOS_TEST_FOR_EXCEPTION(
220  not settings.isParameter(str_precType), std::runtime_error,
221  "Parameter \"" << str_precType << "\" is required by a Teko::SmootherPreconditionerFactory");
222 
223  // grab library and preconditioner name
224  Teuchos::RCP<const InverseLibrary> il = getInverseLibrary();
225  std::string precName = settings.get<std::string>(str_precType);
226 
227  // build preconditioner factory
228  precFactory_ = il->getInverseFactory(precName);
229  TEUCHOS_TEST_FOR_EXCEPTION(
230  precFactory_ == Teuchos::null, std::runtime_error,
231  "ERROR: \"" << str_precType << "\" = " << precName << " could not be found");
232 
233  // post conditions required to be satisfied
235 
236  TEUCHOS_ASSERT(sweepCount_ > 0);
237  TEUCHOS_ASSERT(initialGuessType_ != Unspecified);
238  TEUCHOS_ASSERT(precFactory_ != Teuchos::null);
239 }
240 
241 } // end namespace Teko
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
virtual void setRequestHandler(const Teuchos::RCP< RequestHandler > &rh)
Set the request handler with pointers to the appropriate callbacks.
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
virtual Teuchos::RCP< RequestHandler > getRequestHandler() const
Get the request handler with pointers to the appropriate callbacks.
virtual void implicitApply(const MultiVector &x, MultiVector &y, const double alpha=1.0, const double beta=0.0) const
Perform a matrix vector multiply with this implicitly defined blocked operator.