Teko Version of the Day
Loading...
Searching...
No Matches
Teko_SIMPLEPreconditionerFactory.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#include "Teko_SIMPLEPreconditionerFactory.hpp"
11
12#include "Teko_Utilities.hpp"
13#include "Teko_InverseFactory.hpp"
14#include "Teko_BlockLowerTriInverseOp.hpp"
15#include "Teko_BlockUpperTriInverseOp.hpp"
16#include <stdexcept>
17#ifdef TEKO_HAVE_EPETRA
18#include "Teko_DiagonalPreconditionerFactory.hpp"
19#endif
20
21#include "Teuchos_Time.hpp"
22
23using Teuchos::RCP;
24
25namespace Teko {
26namespace NS {
27
28// Constructor definition
29SIMPLEPreconditionerFactory ::SIMPLEPreconditionerFactory(const RCP<InverseFactory>& inverse,
30 double alpha)
31 : invVelFactory_(inverse),
32 invPrsFactory_(inverse),
33 alpha_(alpha),
34 fInverseType_(Diagonal),
35 useMass_(false) {}
36
37SIMPLEPreconditionerFactory ::SIMPLEPreconditionerFactory(const RCP<InverseFactory>& invVFact,
38 const RCP<InverseFactory>& invPFact,
39 double alpha)
40 : invVelFactory_(invVFact),
41 invPrsFactory_(invPFact),
42 alpha_(alpha),
43 fInverseType_(Diagonal),
44 useMass_(false) {}
45
46SIMPLEPreconditionerFactory::SIMPLEPreconditionerFactory()
47 : alpha_(1.0), fInverseType_(Diagonal), useMass_(false) {}
48
49// Use the factory to build the preconditioner (this is where the work goes)
50LinearOp SIMPLEPreconditionerFactory ::buildPreconditionerOperator(
51 BlockedLinearOp& blockOp, BlockPreconditionerState& state) const {
52 Teko_DEBUG_SCOPE("SIMPLEPreconditionerFactory::buildPreconditionerOperator", 10);
53 Teko_DEBUG_EXPR(Teuchos::Time timer(""));
54
55 int rows = blockRowCount(blockOp);
56 int cols = blockColCount(blockOp);
57
58 TEUCHOS_ASSERT(rows == 2); // sanity checks
59 TEUCHOS_ASSERT(cols == 2);
60
61 bool buildExplicitSchurComplement = true;
62
63 // extract subblocks
64 const LinearOp F = getBlock(0, 0, blockOp);
65 const LinearOp Bt = getBlock(0, 1, blockOp);
66 const LinearOp B = getBlock(1, 0, blockOp);
67 const LinearOp C = getBlock(1, 1, blockOp);
68
69 LinearOp matF = F;
70 if (useMass_) {
71 TEUCHOS_ASSERT(massMatrix_ != Teuchos::null);
72 matF = massMatrix_;
73 }
74
75 // get approximation of inv(F) name H
76 std::string fApproxStr = "<error>";
77 LinearOp H;
78 if (fInverseType_ == NotDiag) {
79 H = buildInverse(*customHFactory_, matF);
80 fApproxStr = customHFactory_->toString();
81
82 // since H is now implicit, we must build an implicit Schur complement
83 buildExplicitSchurComplement = false;
84 } else if (fInverseType_ == BlkDiag) {
85#ifdef TEKO_HAVE_EPETRA
86 // Block diagonal approximation for H
89 Hfact.initializeFromParameterList(BlkDiagList_);
90 H = Hfact.buildPreconditionerOperator(matF, Hstate);
91
92 /*
93 // Get a FECrsMarix out of the BDP
94 RCP<Epetra_FECrsMatrix> Hcrs=rcp(Hstate.BDP_->CreateFECrsMatrix());
95 H=Thyra::epetraLinearOp(Hcrs);
96 */
97
98 buildExplicitSchurComplement = true; // NTS: Do I need this?
99 // Answer - no, but it is documenting whats going on here.
100#else
101 throw std::logic_error(
102 "SIMPLEPreconditionerFactory fInverseType_ == "
103 "BlkDiag but EPETRA is turned off!");
104#endif
105
106 } else {
107 // get generic diagonal
108 H = getInvDiagonalOp(matF, fInverseType_);
109 fApproxStr = getDiagonalName(fInverseType_);
110 }
111
112 // adjust H for time scaling if it is a mass matrix
113 if (useMass_) {
114 RCP<const Teuchos::ParameterList> pl = state.getParameterList();
115
116 if (pl->isParameter("stepsize")) {
117 // get the step size
118 double stepsize = pl->get<double>("stepsize");
119
120 // scale by stepsize only if it is larger than 0
121 if (stepsize > 0.0) H = scale(stepsize, H);
122 }
123 }
124
125 // build approximate Schur complement: hatS = -C + B*H*Bt
126 LinearOp HBt, hatS;
127
128 if (buildExplicitSchurComplement) {
129 ModifiableLinearOp& mHBt = state.getModifiableOp("HBt");
130 ModifiableLinearOp& mhatS = state.getModifiableOp("hatS");
131 ModifiableLinearOp& BHBt = state.getModifiableOp("BHBt");
132
133 // build H*Bt
134 mHBt = explicitMultiply(H, Bt, mHBt);
135 HBt = mHBt;
136
137 // build B*H*Bt
138 BHBt = explicitMultiply(B, HBt, BHBt);
139
140 // build C-B*H*Bt
141 mhatS = explicitAdd(C, scale(-1.0, BHBt), mhatS);
142 hatS = mhatS;
143 } else {
144 // build an implicit Schur complement
145 HBt = multiply(H, Bt);
146
147 hatS = add(C, scale(-1.0, multiply(B, HBt)));
148 }
149
150 Teko::ModifiableLinearOp& precInvF = state.getModifiableOp("precInvF");
151 if (precVelFactory_) {
152 if (precInvF == Teuchos::null) {
153 precInvF = precVelFactory_->buildInverse(F);
154 state.addModifiableOp("precInvF", precInvF);
155 } else {
156 Teko::rebuildInverse(*precVelFactory_, F, precInvF);
157 }
158 }
159
160 // build the inverse for F
161 Teko::ModifiableLinearOp& invF = state.getModifiableOp("invF");
162 if (invF == Teuchos::null) {
163 if (precInvF.is_null()) {
164 invF = Teko::buildInverse(*invVelFactory_, F);
165 } else {
166 invF = Teko::buildInverse(*invVelFactory_, F, precInvF);
167 }
168 } else {
169 if (precInvF.is_null()) {
170 Teko::rebuildInverse(*invVelFactory_, F, invF);
171 } else {
172 Teko::rebuildInverse(*invVelFactory_, F, precInvF, invF);
173 }
174 }
175
176 Teko::ModifiableLinearOp& precInvS = state.getModifiableOp("precInvS");
177 if (precPrsFactory_) {
178 if (precInvS == Teuchos::null) {
179 precInvS = precPrsFactory_->buildInverse(hatS);
180 state.addModifiableOp("precInvS", precInvS);
181 } else {
182 Teko::rebuildInverse(*precPrsFactory_, hatS, precInvS);
183 }
184 }
185
186 // build the approximate Schur complement
187 Teko::ModifiableLinearOp& invS = state.getModifiableOp("invS");
188 if (invS == Teuchos::null) {
189 if (precInvS == Teuchos::null) {
190 invS = Teko::buildInverse(*invPrsFactory_, hatS);
191 } else {
192 invS = Teko::buildInverse(*invPrsFactory_, hatS, precInvS);
193 }
194 } else {
195 if (precInvS == Teuchos::null) {
196 Teko::rebuildInverse(*invPrsFactory_, hatS, invS);
197 } else {
198 Teko::rebuildInverse(*invPrsFactory_, hatS, precInvS, invS);
199 }
200 }
201
202 std::vector<LinearOp> invDiag(2); // vector storing inverses
203
204 // build lower triangular inverse matrix
205 BlockedLinearOp L = zeroBlockedOp(blockOp);
206 setBlock(1, 0, L, B);
207 endBlockFill(L);
208
209 invDiag[0] = invF;
210 invDiag[1] = invS;
211 LinearOp invL = createBlockLowerTriInverseOp(L, invDiag);
212
213 // build upper triangular matrix
214 BlockedLinearOp U = zeroBlockedOp(blockOp);
215 setBlock(0, 1, U, scale(1.0 / alpha_, HBt));
216 endBlockFill(U);
217
218 invDiag[0] = identity(rangeSpace(invF));
219 invDiag[1] = scale(alpha_, identity(rangeSpace(invS)));
220 LinearOp invU = createBlockUpperTriInverseOp(U, invDiag);
221
222 // return implicit product operator
223 return multiply(invU, invL, "SIMPLE_" + fApproxStr);
224}
225
227void SIMPLEPreconditionerFactory::initializeFromParameterList(const Teuchos::ParameterList& pl) {
228 RCP<const InverseLibrary> invLib = getInverseLibrary();
229
230 // default conditions
231 useMass_ = false;
232 customHFactory_ = Teuchos::null;
233 fInverseType_ = Diagonal;
234
235 // get string specifying inverse
236 std::string invStr = "", invVStr = "", invPStr = "", precVStr = "", precPStr = "";
237 alpha_ = 1.0;
238
239 // "parse" the parameter list
240 if (pl.isParameter("Inverse Type")) invStr = pl.get<std::string>("Inverse Type");
241 if (pl.isParameter("Inverse Velocity Type"))
242 invVStr = pl.get<std::string>("Inverse Velocity Type");
243 if (pl.isParameter("Preconditioner Velocity Type"))
244 precVStr = pl.get<std::string>("Preconditioner Velocity Type");
245 if (pl.isParameter("Inverse Pressure Type"))
246 invPStr = pl.get<std::string>("Inverse Pressure Type");
247 if (pl.isParameter("Preconditioner Pressure Type"))
248 precPStr = pl.get<std::string>("Preconditioner Pressure Type");
249 if (pl.isParameter("Alpha")) alpha_ = pl.get<double>("Alpha");
250 if (pl.isParameter("Explicit Velocity Inverse Type")) {
251 std::string fInverseStr = pl.get<std::string>("Explicit Velocity Inverse Type");
252
253 // build inverse types
254 fInverseType_ = getDiagonalType(fInverseStr);
255 if (fInverseType_ == NotDiag) customHFactory_ = invLib->getInverseFactory(fInverseStr);
256
257 // Grab the sublist if we're using the block diagonal
258 if (fInverseType_ == BlkDiag) BlkDiagList_ = pl.sublist("H options");
259 }
260 if (pl.isParameter("Use Mass Scaling")) useMass_ = pl.get<bool>("Use Mass Scaling");
261
262 Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM << "SIMPLE Parameters: " << std::endl;
263 DEBUG_STREAM << " inv type = \"" << invStr << "\"" << std::endl;
264 DEBUG_STREAM << " inv v type = \"" << invVStr << "\"" << std::endl;
265 DEBUG_STREAM << " prec v type = \"" << precVStr << "\"" << std::endl;
266 DEBUG_STREAM << " inv p type = \"" << invPStr << "\"" << std::endl;
267 DEBUG_STREAM << " prec p type = \"" << precPStr << "\"" << std::endl;
268 DEBUG_STREAM << " alpha = " << alpha_ << std::endl;
269 DEBUG_STREAM << " use mass = " << useMass_ << std::endl;
270 DEBUG_STREAM << " vel scaling = " << getDiagonalName(fInverseType_) << std::endl;
271 DEBUG_STREAM << "SIMPLE Parameter list: " << std::endl;
272 pl.print(DEBUG_STREAM);
273 Teko_DEBUG_MSG_END()
274
275 // set defaults as needed
276#if defined(Teko_ENABLE_Amesos)
277 if (invStr == "") invStr = "Amesos";
278#elif defined(Teko_ENABLE_Amesos2)
279 if (invStr == "") invStr = "Amesos2";
280#endif
281
282 if (invVStr == "") invVStr = invStr;
283 if (invPStr == "") invPStr = invStr;
284
285 // two inverse factory objects
286 RCP<InverseFactory> invVFact, invPFact;
287
288 // build velocity inverse factory
289 invVFact = invLib->getInverseFactory(invVStr);
290 invPFact = invVFact; // by default these are the same
291 if (invVStr != invPStr) // if different, build pressure inverse factory
292 invPFact = invLib->getInverseFactory(invPStr);
293
294 RCP<InverseFactory> precVFact, precPFact;
295 if (precVStr != "") precVFact = invLib->getInverseFactory(precVStr);
296
297 if (precPStr != "") precPFact = invLib->getInverseFactory(precPStr);
298
299 // based on parameter type build a strategy
300 invVelFactory_ = invVFact;
301 invPrsFactory_ = invPFact;
302
303 precVelFactory_ = precVFact;
304 precPrsFactory_ = precPFact;
305
306 if (useMass_) {
307 Teuchos::RCP<Teko::RequestHandler> rh = getRequestHandler();
308 rh->preRequest<Teko::LinearOp>(Teko::RequestMesg("Velocity Mass Matrix"));
309 Teko::LinearOp mass = rh->request<Teko::LinearOp>(Teko::RequestMesg("Velocity Mass Matrix"));
310 setMassMatrix(mass);
311 }
312}
313
315Teuchos::RCP<Teuchos::ParameterList> SIMPLEPreconditionerFactory::getRequestedParameters() const {
316 Teuchos::RCP<Teuchos::ParameterList> result;
317 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList());
318
319 // grab parameters from F solver
320 {
321 RCP<Teuchos::ParameterList> vList = invVelFactory_->getRequestedParameters();
322 if (vList != Teuchos::null) {
323 Teuchos::ParameterList::ConstIterator itr;
324 for (itr = vList->begin(); itr != vList->end(); ++itr) pl->setEntry(itr->first, itr->second);
325 result = pl;
326 }
327 }
328
329 if (precVelFactory_ != Teuchos::null) {
330 RCP<Teuchos::ParameterList> vList = precVelFactory_->getRequestedParameters();
331 if (vList != Teuchos::null) {
332 Teuchos::ParameterList::ConstIterator itr;
333 for (itr = vList->begin(); itr != vList->end(); ++itr) pl->setEntry(itr->first, itr->second);
334 result = pl;
335 }
336 }
337
338 // grab parameters from S solver
339 {
340 RCP<Teuchos::ParameterList> pList = invPrsFactory_->getRequestedParameters();
341 if (pList != Teuchos::null) {
342 Teuchos::ParameterList::ConstIterator itr;
343 for (itr = pList->begin(); itr != pList->end(); ++itr) pl->setEntry(itr->first, itr->second);
344 result = pl;
345 }
346 }
347
348 if (precPrsFactory_ != Teuchos::null) {
349 RCP<Teuchos::ParameterList> pList = precPrsFactory_->getRequestedParameters();
350 if (pList != Teuchos::null) {
351 Teuchos::ParameterList::ConstIterator itr;
352 for (itr = pList->begin(); itr != pList->end(); ++itr) pl->setEntry(itr->first, itr->second);
353 result = pl;
354 }
355 }
356
357 // grab parameters from S solver
358 if (customHFactory_ != Teuchos::null) {
359 RCP<Teuchos::ParameterList> hList = customHFactory_->getRequestedParameters();
360 if (hList != Teuchos::null) {
361 Teuchos::ParameterList::ConstIterator itr;
362 for (itr = hList->begin(); itr != hList->end(); ++itr) pl->setEntry(itr->first, itr->second);
363 result = pl;
364 }
365 }
366
367 return result;
368}
369
371bool SIMPLEPreconditionerFactory::updateRequestedParameters(const Teuchos::ParameterList& pl) {
372 Teko_DEBUG_SCOPE("InvLSCStrategy::updateRequestedParameters", 10);
373 bool result = true;
374
375 // update requested parameters in solvers
376 result &= invVelFactory_->updateRequestedParameters(pl);
377 result &= invPrsFactory_->updateRequestedParameters(pl);
378 if (precVelFactory_) result &= precVelFactory_->updateRequestedParameters(pl);
379 if (precPrsFactory_) result &= precPrsFactory_->updateRequestedParameters(pl);
380 if (customHFactory_ != Teuchos::null) result &= customHFactory_->updateRequestedParameters(pl);
381
382 return result;
383}
384
385} // end namespace NS
386} // end namespace Teko
@ BlkDiag
Specifies that a block diagonal approximation is to be used.
@ NotDiag
For user convenience, if Teko recieves this value, exceptions will be thrown.
@ Diagonal
Specifies that just the diagonal is used.
MultiVector getBlock(int i, const BlockedMultiVector &bmv)
Get the ith block from a BlockedMultiVector object.
An implementation of a state object for block preconditioners.
Preconditioner factory for building explcit inverse of diagonal operators. This includes block operat...
virtual void initializeFromParameterList(const Teuchos::ParameterList &pl)
Initialize from a parameter list.
LinearOp buildPreconditionerOperator(LinearOp &lo, PreconditionerState &state) const
virtual bool updateRequestedParameters(const Teuchos::ParameterList &pl)
For assisting in construction of the preconditioner.
virtual void initializeFromParameterList(const Teuchos::ParameterList &pl)
Initialize from a parameter list.
virtual void setMassMatrix(Teko::LinearOp &mass)
Set the mass matrix for this factory.
virtual Teuchos::RCP< Teuchos::ParameterList > getRequestedParameters() const
For assisting in construction of the preconditioner.
Teuchos::RCP< const InverseLibrary > getInverseLibrary() const
Get the inverse library used by this preconditioner factory.
Teuchos::RCP< RequestHandler > getRequestHandler() const
Get the request handler with pointers to the appropriate callbacks.
virtual void addModifiableOp(const std::string &name, const Teko::ModifiableLinearOp &mlo)
Add a named operator to the state object.
virtual Teko::ModifiableLinearOp & getModifiableOp(const std::string &name)
Add a named operator to the state object.