Teko Version of the Day
Loading...
Searching...
No Matches
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
16namespace Teko {
17
18// A small utility class to help distinguish smoothers
19class 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
34SmootherLinearOp::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
45SmootherLinearOp::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
55void 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
97void SmootherLinearOp::setRequestHandler(const Teuchos::RCP<RequestHandler>& rh) {
98 Teko_DEBUG_SCOPE("SmootherLinearOp::setRequestHandler", 10);
99 requestHandler_ = rh;
100}
101
103Teuchos::RCP<RequestHandler> SmootherLinearOp::getRequestHandler() const {
104 Teko_DEBUG_SCOPE("SmootherLinearOp::getRequestHandler", 10);
105 return requestHandler_;
106}
107
108LinearOp 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
113LinearOp 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
123SmootherPreconditionerFactory::SmootherPreconditionerFactory()
124 : sweepCount_(0),
125 initialGuessType_(Unspecified),
126 initialGuessBlock_(0),
127 precFactory_(Teuchos::null) {}
128
132LinearOp 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
171void 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
MultiVector deepcopy(const MultiVector &v)
Perform a deep copy of the vector.
Teuchos::RCP< const InverseLibrary > getInverseLibrary() const
Get the inverse library used by this preconditioner factory.
An implementation of a state object preconditioners.
virtual void setRequestHandler(const Teuchos::RCP< RequestHandler > &rh)
Set 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.
virtual Teuchos::RCP< RequestHandler > getRequestHandler() const
Get the request handler with pointers to the appropriate callbacks.