Teko Version of the Day
Loading...
Searching...
No Matches
Teko_LSCPreconditionerFactory.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_LSCPreconditionerFactory.hpp"
11
12#include "Thyra_DefaultMultipliedLinearOp.hpp"
13#include "Thyra_DefaultAddedLinearOp.hpp"
14#include "Thyra_DefaultIdentityLinearOp.hpp"
15#include "Thyra_DefaultZeroLinearOp.hpp"
16
18#include "Teko_Utilities.hpp"
19#include "Teko_BlockUpperTriInverseOp.hpp"
20#include "Teko_StaticLSCStrategy.hpp"
21#include "Teko_InvLSCStrategy.hpp"
22#include "Teko_PresLaplaceLSCStrategy.hpp"
23#include "Teko_LSCSIMPLECStrategy.hpp"
24
25#include "Teuchos_Time.hpp"
26
27namespace Teko {
28namespace NS {
29
30using Teuchos::rcp;
31using Teuchos::RCP;
32using Teuchos::rcp_dynamic_cast;
33
34using Thyra::add;
35using Thyra::identity;
36using Thyra::multiply;
37
38// Stabilized constructor
39LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp& invF, const LinearOp& invBQBtmC,
40 const LinearOp& invD, const LinearOp& invMass)
41 : invOpsStrategy_(rcp(new StaticLSCStrategy(invF, invBQBtmC, invD, invMass))),
42 isSymmetric_(true) {}
43
44// Stable constructor
45LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp& invF, const LinearOp& invBQBtmC,
46 const LinearOp& invMass)
47 : invOpsStrategy_(rcp(new StaticLSCStrategy(invF, invBQBtmC, invMass))), isSymmetric_(true) {}
48
49// fully generic constructor
50LSCPreconditionerFactory::LSCPreconditionerFactory(const RCP<LSCStrategy>& strategy)
51 : invOpsStrategy_(strategy), isSymmetric_(true) {}
52
53LSCPreconditionerFactory::LSCPreconditionerFactory() : isSymmetric_(true) {}
54
55// for PreconditionerFactoryBase
57
58// initialize a newly created preconditioner object
59LinearOp LSCPreconditionerFactory::buildPreconditionerOperator(
60 BlockedLinearOp& blockOp, BlockPreconditionerState& state) const {
61 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildPreconditionerOperator", 10);
62 Teko_DEBUG_EXPR(Teuchos::Time timer(""));
63 Teko_DEBUG_EXPR(Teuchos::Time totalTimer(""));
64 Teko_DEBUG_EXPR(totalTimer.start());
65
66 // extract sub-matrices from source operator
67 LinearOp F = blockOp->getBlock(0, 0);
68 LinearOp B = blockOp->getBlock(1, 0);
69 LinearOp Bt = blockOp->getBlock(0, 1);
70
71 if (not isSymmetric_) Bt = scale(-1.0, adjoint(B));
72
73 // build what is neccessary for the state object
74 Teko_DEBUG_EXPR(timer.start(true));
75 invOpsStrategy_->buildState(blockOp, state);
76 Teko_DEBUG_EXPR(timer.stop());
77 Teko_DEBUG_MSG("LSCPrecFact::buildPO BuildStateTime = " << timer.totalElapsedTime(), 2);
78
79 // extract operators from strategy
80 Teko_DEBUG_EXPR(timer.start(true));
81 LinearOp invF = invOpsStrategy_->getInvF(blockOp, state);
82 LinearOp invBQBtmC = invOpsStrategy_->getInvBQBt(blockOp, state);
83 LinearOp invBHBtmC = invOpsStrategy_->getInvBHBt(blockOp, state);
84 LinearOp outerStab = invOpsStrategy_->getOuterStabilization(blockOp, state);
85 LinearOp innerStab = invOpsStrategy_->getInnerStabilization(blockOp, state);
86
87 // if necessary build an identity mass matrix
88 LinearOp invMass = invOpsStrategy_->getInvMass(blockOp, state);
89 LinearOp HScaling = invOpsStrategy_->getHScaling(blockOp, state);
90 if (invMass == Teuchos::null) invMass = identity<double>(F->range());
91 if (HScaling == Teuchos::null) HScaling = identity<double>(F->range());
92 Teko_DEBUG_EXPR(timer.stop());
93 Teko_DEBUG_MSG("LSCPrecFact::buildPO GetInvTime = " << timer.totalElapsedTime(), 2);
94
95 // need to build Schur complement, inv(P) = inv(B*Bt)*(B*F*Bt)*inv(B*Bt)
96
97 // first construct middle operator: M = B * inv(Mass) * F * inv(Mass) * Bt
98 LinearOp M =
99 // (B * inv(Mass) ) * F * (inv(Mass) * Bt)
100 multiply(multiply(B, invMass), F, multiply(HScaling, Bt));
101 if (innerStab != Teuchos::null) // deal with inner stabilization
102 M = add(M, innerStab);
103
104 // now construct a linear operator schur complement
105 LinearOp invPschur;
106 if (outerStab != Teuchos::null)
107 invPschur = add(multiply(invBQBtmC, M, invBHBtmC), outerStab);
108 else
109 invPschur = multiply(invBQBtmC, M, invBHBtmC);
110
111 // build the preconditioner operator: Use LDU or upper triangular approximation
112 if (invOpsStrategy_->useFullLDU()) {
113 Teko_DEBUG_EXPR(totalTimer.stop());
114 Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(), 2);
115
116 // solve using a full LDU decomposition
117 return createLU2x2InverseOp(blockOp, invF, invPschur, "LSC-LDU");
118 } else {
119 // build diagonal operations
120 std::vector<LinearOp> invDiag(2);
121 invDiag[0] = invF;
122 invDiag[1] = Thyra::scale(-1.0, invPschur);
123
124 // get upper triangular matrix
125 BlockedLinearOp U = getUpperTriBlocks(blockOp);
126
127 Teko_DEBUG_EXPR(totalTimer.stop());
128 Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(), 2);
129
130 // solve using only one inversion of F
131 return createBlockUpperTriInverseOp(U, invDiag, "LSC-Upper");
132 }
133}
134
136void LSCPreconditionerFactory::initializeFromParameterList(const Teuchos::ParameterList& pl) {
137 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::initializeFromParameterList", 10);
138
139 RCP<const InverseLibrary> invLib = getInverseLibrary();
140
141 if (pl.isParameter("Is Symmetric")) isSymmetric_ = pl.get<bool>("Is Symmetric");
142
143 std::string name = "Basic Inverse";
144 if (pl.isParameter("Strategy Name")) name = pl.get<std::string>("Strategy Name");
145 const Teuchos::ParameterEntry* pe = pl.getEntryPtr("Strategy Settings");
146
147 // check for a mistake in input file
148 if (name != "Basic Inverse" && pe == 0) {
149 RCP<Teuchos::FancyOStream> out = getOutputStream();
150 *out << "LSC Construction failed: ";
151 *out << "Strategy \"" << name << "\" requires a \"Strategy Settings\" sublist" << std::endl;
152 throw std::runtime_error("LSC Construction failed: Strategy Settings not set");
153 }
154
155 // get the parameter list to construct the strategy
156 Teuchos::RCP<const Teuchos::ParameterList> stratPL = Teuchos::rcpFromRef(pl);
157 if (pe != 0) stratPL = Teuchos::rcpFromRef(pl.sublist("Strategy Settings"));
158
159 // build the strategy object
160 RCP<LSCStrategy> strategy = buildStrategy(name, *stratPL, invLib, getRequestHandler());
161
162 // strategy could not be built
163 if (strategy == Teuchos::null) {
164 RCP<Teuchos::FancyOStream> out = getOutputStream();
165 *out << "LSC Construction failed: ";
166 *out << "Strategy \"" << name << "\" could not be constructed" << std::endl;
167 throw std::runtime_error("LSC Construction failed: Strategy could not be constructed");
168 }
169
170 strategy->setSymmetric(isSymmetric_);
171 invOpsStrategy_ = strategy;
172}
173
175Teuchos::RCP<Teuchos::ParameterList> LSCPreconditionerFactory::getRequestedParameters() const {
176 return invOpsStrategy_->getRequestedParameters();
177}
178
180bool LSCPreconditionerFactory::updateRequestedParameters(const Teuchos::ParameterList& pl) {
181 return invOpsStrategy_->updateRequestedParameters(pl);
182}
183
185// Static members and methods
187
189CloneFactory<LSCStrategy> LSCPreconditionerFactory::strategyBuilder_;
190
203RCP<LSCStrategy> LSCPreconditionerFactory::buildStrategy(const std::string& name,
204 const Teuchos::ParameterList& settings,
205 const RCP<const InverseLibrary>& invLib,
206 const RCP<RequestHandler>& rh) {
207 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildStrategy", 10);
208
209 // initialize the defaults if necessary
210 if (strategyBuilder_.cloneCount() == 0) initializeStrategyBuilder();
211
212 // request the preconditioner factory from the CloneFactory
213 Teko_DEBUG_MSG("Building LSC strategy \"" << name << "\"", 1);
214 RCP<LSCStrategy> strategy = strategyBuilder_.build(name);
215
216 if (strategy == Teuchos::null) return Teuchos::null;
217
218 // now that inverse library has been set,
219 // pass in the parameter list
220 strategy->setRequestHandler(rh);
221 strategy->initializeFromParameterList(settings, *invLib);
222
223 return strategy;
224}
225
239void LSCPreconditionerFactory::addStrategy(const std::string& name, const RCP<Cloneable>& clone) {
240 // initialize the defaults if necessary
241 if (strategyBuilder_.cloneCount() == 0) initializeStrategyBuilder();
242
243 // add clone to builder
244 strategyBuilder_.addClone(name, clone);
245}
246
248void LSCPreconditionerFactory::initializeStrategyBuilder() {
249 RCP<Cloneable> clone;
250
251 // add various strategies to the factory
252 clone = rcp(new AutoClone<InvLSCStrategy>());
253 strategyBuilder_.addClone("Basic Inverse", clone);
254
255 // add various strategies to the factory
256 clone = rcp(new AutoClone<PresLaplaceLSCStrategy>());
257 strategyBuilder_.addClone("Pressure Laplace", clone);
258
259 // add various strategies to the factory
260 clone = rcp(new AutoClone<LSCSIMPLECStrategy>());
261 strategyBuilder_.addClone("SIMPLEC", clone);
262}
263
264} // end namespace NS
265} // end namespace Teko
LinearOp createLU2x2InverseOp(BlockedLinearOp &A, LinearOp &invA00, LinearOp &invS)
Constructor method for building LU2x2InverseOp.