Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_LSCPreconditionerFactory.cpp
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 #include "Teko_LSCPreconditionerFactory.hpp"
48 
49 #include "Thyra_DefaultMultipliedLinearOp.hpp"
50 #include "Thyra_DefaultAddedLinearOp.hpp"
51 #include "Thyra_DefaultIdentityLinearOp.hpp"
52 #include "Thyra_DefaultZeroLinearOp.hpp"
53 
54 #include "Teko_LU2x2InverseOp.hpp"
55 #include "Teko_Utilities.hpp"
56 #include "Teko_BlockUpperTriInverseOp.hpp"
57 #include "Teko_StaticLSCStrategy.hpp"
58 #include "Teko_InvLSCStrategy.hpp"
59 #include "Teko_PresLaplaceLSCStrategy.hpp"
60 #include "Teko_LSCSIMPLECStrategy.hpp"
61 
62 #include "Teuchos_Time.hpp"
63 
64 namespace Teko {
65 namespace NS {
66 
67 using Teuchos::rcp;
68 using Teuchos::RCP;
69 using Teuchos::rcp_dynamic_cast;
70 
71 using Thyra::add;
72 using Thyra::identity;
73 using Thyra::multiply;
74 
75 // Stabilized constructor
76 LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp& invF, const LinearOp& invBQBtmC,
77  const LinearOp& invD, const LinearOp& invMass)
78  : invOpsStrategy_(rcp(new StaticLSCStrategy(invF, invBQBtmC, invD, invMass))),
79  isSymmetric_(true) {}
80 
81 // Stable constructor
82 LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp& invF, const LinearOp& invBQBtmC,
83  const LinearOp& invMass)
84  : invOpsStrategy_(rcp(new StaticLSCStrategy(invF, invBQBtmC, invMass))), isSymmetric_(true) {}
85 
86 // fully generic constructor
87 LSCPreconditionerFactory::LSCPreconditionerFactory(const RCP<LSCStrategy>& strategy)
88  : invOpsStrategy_(strategy), isSymmetric_(true) {}
89 
90 LSCPreconditionerFactory::LSCPreconditionerFactory() : isSymmetric_(true) {}
91 
92 // for PreconditionerFactoryBase
94 
95 // initialize a newly created preconditioner object
96 LinearOp LSCPreconditionerFactory::buildPreconditionerOperator(
97  BlockedLinearOp& blockOp, BlockPreconditionerState& state) const {
98  Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildPreconditionerOperator", 10);
99  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
100  Teko_DEBUG_EXPR(Teuchos::Time totalTimer(""));
101  Teko_DEBUG_EXPR(totalTimer.start());
102 
103  // extract sub-matrices from source operator
104  LinearOp F = blockOp->getBlock(0, 0);
105  LinearOp B = blockOp->getBlock(1, 0);
106  LinearOp Bt = blockOp->getBlock(0, 1);
107 
108  if (not isSymmetric_) Bt = scale(-1.0, adjoint(B));
109 
110  // build what is neccessary for the state object
111  Teko_DEBUG_EXPR(timer.start(true));
112  invOpsStrategy_->buildState(blockOp, state);
113  Teko_DEBUG_EXPR(timer.stop());
114  Teko_DEBUG_MSG("LSCPrecFact::buildPO BuildStateTime = " << timer.totalElapsedTime(), 2);
115 
116  // extract operators from strategy
117  Teko_DEBUG_EXPR(timer.start(true));
118  LinearOp invF = invOpsStrategy_->getInvF(blockOp, state);
119  LinearOp invBQBtmC = invOpsStrategy_->getInvBQBt(blockOp, state);
120  LinearOp invBHBtmC = invOpsStrategy_->getInvBHBt(blockOp, state);
121  LinearOp outerStab = invOpsStrategy_->getOuterStabilization(blockOp, state);
122  LinearOp innerStab = invOpsStrategy_->getInnerStabilization(blockOp, state);
123 
124  // if necessary build an identity mass matrix
125  LinearOp invMass = invOpsStrategy_->getInvMass(blockOp, state);
126  LinearOp HScaling = invOpsStrategy_->getHScaling(blockOp, state);
127  if (invMass == Teuchos::null) invMass = identity<double>(F->range());
128  if (HScaling == Teuchos::null) HScaling = identity<double>(F->range());
129  Teko_DEBUG_EXPR(timer.stop());
130  Teko_DEBUG_MSG("LSCPrecFact::buildPO GetInvTime = " << timer.totalElapsedTime(), 2);
131 
132  // need to build Schur complement, inv(P) = inv(B*Bt)*(B*F*Bt)*inv(B*Bt)
133 
134  // first construct middle operator: M = B * inv(Mass) * F * inv(Mass) * Bt
135  LinearOp M =
136  // (B * inv(Mass) ) * F * (inv(Mass) * Bt)
137  multiply(multiply(B, invMass), F, multiply(HScaling, Bt));
138  if (innerStab != Teuchos::null) // deal with inner stabilization
139  M = add(M, innerStab);
140 
141  // now construct a linear operator schur complement
142  LinearOp invPschur;
143  if (outerStab != Teuchos::null)
144  invPschur = add(multiply(invBQBtmC, M, invBHBtmC), outerStab);
145  else
146  invPschur = multiply(invBQBtmC, M, invBHBtmC);
147 
148  // build the preconditioner operator: Use LDU or upper triangular approximation
149  if (invOpsStrategy_->useFullLDU()) {
150  Teko_DEBUG_EXPR(totalTimer.stop());
151  Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(), 2);
152 
153  // solve using a full LDU decomposition
154  return createLU2x2InverseOp(blockOp, invF, invPschur, "LSC-LDU");
155  } else {
156  // build diagonal operations
157  std::vector<LinearOp> invDiag(2);
158  invDiag[0] = invF;
159  invDiag[1] = Thyra::scale(-1.0, invPschur);
160 
161  // get upper triangular matrix
162  BlockedLinearOp U = getUpperTriBlocks(blockOp);
163 
164  Teko_DEBUG_EXPR(totalTimer.stop());
165  Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(), 2);
166 
167  // solve using only one inversion of F
168  return createBlockUpperTriInverseOp(U, invDiag, "LSC-Upper");
169  }
170 }
171 
173 void LSCPreconditionerFactory::initializeFromParameterList(const Teuchos::ParameterList& pl) {
174  Teko_DEBUG_SCOPE("LSCPreconditionerFactory::initializeFromParameterList", 10);
175 
176  RCP<const InverseLibrary> invLib = getInverseLibrary();
177 
178  if (pl.isParameter("Is Symmetric")) isSymmetric_ = pl.get<bool>("Is Symmetric");
179 
180  std::string name = "Basic Inverse";
181  if (pl.isParameter("Strategy Name")) name = pl.get<std::string>("Strategy Name");
182  const Teuchos::ParameterEntry* pe = pl.getEntryPtr("Strategy Settings");
183 
184  // check for a mistake in input file
185  if (name != "Basic Inverse" && pe == 0) {
186  RCP<Teuchos::FancyOStream> out = getOutputStream();
187  *out << "LSC Construction failed: ";
188  *out << "Strategy \"" << name << "\" requires a \"Strategy Settings\" sublist" << std::endl;
189  throw std::runtime_error("LSC Construction failed: Strategy Settings not set");
190  }
191 
192  // get the parameter list to construct the strategy
193  Teuchos::RCP<const Teuchos::ParameterList> stratPL = Teuchos::rcpFromRef(pl);
194  if (pe != 0) stratPL = Teuchos::rcpFromRef(pl.sublist("Strategy Settings"));
195 
196  // build the strategy object
197  RCP<LSCStrategy> strategy = buildStrategy(name, *stratPL, invLib, getRequestHandler());
198 
199  // strategy could not be built
200  if (strategy == Teuchos::null) {
201  RCP<Teuchos::FancyOStream> out = getOutputStream();
202  *out << "LSC Construction failed: ";
203  *out << "Strategy \"" << name << "\" could not be constructed" << std::endl;
204  throw std::runtime_error("LSC Construction failed: Strategy could not be constructed");
205  }
206 
207  strategy->setSymmetric(isSymmetric_);
208  invOpsStrategy_ = strategy;
209 }
210 
212 Teuchos::RCP<Teuchos::ParameterList> LSCPreconditionerFactory::getRequestedParameters() const {
213  return invOpsStrategy_->getRequestedParameters();
214 }
215 
217 bool LSCPreconditionerFactory::updateRequestedParameters(const Teuchos::ParameterList& pl) {
218  return invOpsStrategy_->updateRequestedParameters(pl);
219 }
220 
222 // Static members and methods
224 
226 CloneFactory<LSCStrategy> LSCPreconditionerFactory::strategyBuilder_;
227 
240 RCP<LSCStrategy> LSCPreconditionerFactory::buildStrategy(const std::string& name,
241  const Teuchos::ParameterList& settings,
242  const RCP<const InverseLibrary>& invLib,
243  const RCP<RequestHandler>& rh) {
244  Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildStrategy", 10);
245 
246  // initialize the defaults if necessary
247  if (strategyBuilder_.cloneCount() == 0) initializeStrategyBuilder();
248 
249  // request the preconditioner factory from the CloneFactory
250  Teko_DEBUG_MSG("Building LSC strategy \"" << name << "\"", 1);
251  RCP<LSCStrategy> strategy = strategyBuilder_.build(name);
252 
253  if (strategy == Teuchos::null) return Teuchos::null;
254 
255  // now that inverse library has been set,
256  // pass in the parameter list
257  strategy->setRequestHandler(rh);
258  strategy->initializeFromParameterList(settings, *invLib);
259 
260  return strategy;
261 }
262 
276 void LSCPreconditionerFactory::addStrategy(const std::string& name, const RCP<Cloneable>& clone) {
277  // initialize the defaults if necessary
278  if (strategyBuilder_.cloneCount() == 0) initializeStrategyBuilder();
279 
280  // add clone to builder
281  strategyBuilder_.addClone(name, clone);
282 }
283 
285 void LSCPreconditionerFactory::initializeStrategyBuilder() {
286  RCP<Cloneable> clone;
287 
288  // add various strategies to the factory
289  clone = rcp(new AutoClone<InvLSCStrategy>());
290  strategyBuilder_.addClone("Basic Inverse", clone);
291 
292  // add various strategies to the factory
293  clone = rcp(new AutoClone<PresLaplaceLSCStrategy>());
294  strategyBuilder_.addClone("Pressure Laplace", clone);
295 
296  // add various strategies to the factory
297  clone = rcp(new AutoClone<LSCSIMPLECStrategy>());
298  strategyBuilder_.addClone("SIMPLEC", clone);
299 }
300 
301 } // end namespace NS
302 } // end namespace Teko