Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_PresLaplaceLSCStrategy.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 "NS/Teko_PresLaplaceLSCStrategy.hpp"
48 
49 #include "Thyra_DefaultDiagonalLinearOp.hpp"
50 
51 #include "Teuchos_Time.hpp"
52 #include "Teuchos_TimeMonitor.hpp"
53 
54 // Teko includes
55 #include "Teko_Utilities.hpp"
56 #include "NS/Teko_LSCPreconditionerFactory.hpp"
57 
58 using Teuchos::RCP;
59 using Teuchos::rcp_const_cast;
60 using Teuchos::rcp_dynamic_cast;
61 
62 namespace Teko {
63 namespace NS {
64 
66 // PresLaplaceLSCStrategy Implementation
68 
69 // constructors
71 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy()
72  : invFactoryV_(Teuchos::null),
73  invFactoryP_(Teuchos::null),
74  eigSolveParam_(5),
75  useFullLDU_(false),
76  useMass_(false),
77  scaleType_(AbsRowSum) {}
78 
79 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy(const Teuchos::RCP<InverseFactory>& factory)
80  : invFactoryV_(factory),
81  invFactoryP_(factory),
82  eigSolveParam_(5),
83  useFullLDU_(false),
84  useMass_(false),
85  scaleType_(AbsRowSum) {}
86 
87 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy(const Teuchos::RCP<InverseFactory>& invFactF,
88  const Teuchos::RCP<InverseFactory>& invFactS)
89  : invFactoryV_(invFactF),
90  invFactoryP_(invFactS),
91  eigSolveParam_(5),
92  useFullLDU_(false),
93  useMass_(false),
94  scaleType_(AbsRowSum) {}
95 
97 
98 void PresLaplaceLSCStrategy::buildState(BlockedLinearOp& A, BlockPreconditionerState& state) const {
99  Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::buildState", 10);
100 
101  LSCPrecondState* lscState = dynamic_cast<LSCPrecondState*>(&state);
102  TEUCHOS_ASSERT(lscState != 0);
103 
104  // if neccessary save state information
105  if (not lscState->isInitialized()) {
106  Teko_DEBUG_EXPR(Teuchos::Time timer(""));
107 
108  // construct operators
109  {
110  Teko_DEBUG_SCOPE("PL-LSC::buildState constructing operators", 1);
111  Teko_DEBUG_EXPR(timer.start(true));
112 
113  initializeState(A, lscState);
114 
115  Teko_DEBUG_EXPR(timer.stop());
116  Teko_DEBUG_MSG("PL-LSC::buildState BuildOpsTime = " << timer.totalElapsedTime(), 1);
117  }
118 
119  // Build the inverses
120  {
121  Teko_DEBUG_SCOPE("PL-LSC::buildState calculating inverses", 1);
122  Teko_DEBUG_EXPR(timer.start(true));
123 
124  computeInverses(A, lscState);
125 
126  Teko_DEBUG_EXPR(timer.stop());
127  Teko_DEBUG_MSG("PL-LSC::buildState BuildInvTime = " << timer.totalElapsedTime(), 1);
128  }
129  }
130 }
131 
132 // functions inherited from LSCStrategy
133 LinearOp PresLaplaceLSCStrategy::getInvBQBt(const BlockedLinearOp& /* A */,
134  BlockPreconditionerState& state) const {
135  return state.getModifiableOp("invPresLap");
136 }
137 
138 LinearOp PresLaplaceLSCStrategy::getInvBHBt(const BlockedLinearOp& /* A */,
139  BlockPreconditionerState& state) const {
140  return state.getModifiableOp("invPresLap");
141 }
142 
143 LinearOp PresLaplaceLSCStrategy::getInvF(const BlockedLinearOp& /* A */,
144  BlockPreconditionerState& state) const {
145  return state.getModifiableOp("invF");
146 }
147 
148 // LinearOp PresLaplaceLSCStrategy::getInvAlphaD(const BlockedLinearOp & A,BlockPreconditionerState
149 // & state) const
150 LinearOp PresLaplaceLSCStrategy::getOuterStabilization(const BlockedLinearOp& /* A */,
151  BlockPreconditionerState& state) const {
152  LSCPrecondState* lscState = dynamic_cast<LSCPrecondState*>(&state);
153  TEUCHOS_ASSERT(lscState != 0);
154  TEUCHOS_ASSERT(lscState->isInitialized())
155 
156  return lscState->aiD_;
157 }
158 
159 LinearOp PresLaplaceLSCStrategy::getInvMass(const BlockedLinearOp& /* A */,
160  BlockPreconditionerState& state) const {
161  LSCPrecondState* lscState = dynamic_cast<LSCPrecondState*>(&state);
162  TEUCHOS_ASSERT(lscState != 0);
163  TEUCHOS_ASSERT(lscState->isInitialized())
164 
165  return lscState->invMass_;
166 }
167 
168 LinearOp PresLaplaceLSCStrategy::getHScaling(const BlockedLinearOp& A,
169  BlockPreconditionerState& state) const {
170  return getInvMass(A, state);
171 }
172 
174 void PresLaplaceLSCStrategy::initializeState(const BlockedLinearOp& A,
175  LSCPrecondState* state) const {
176  Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::initializeState", 10);
177 
178  std::string velMassStr = getVelocityMassString();
179 
180  const LinearOp F = getBlock(0, 0, A);
181  const LinearOp Bt = getBlock(0, 1, A);
182  const LinearOp B = getBlock(1, 0, A);
183  const LinearOp C = getBlock(1, 1, A);
184 
185  LinearOp D = B;
186  LinearOp G = Bt;
187 
188  bool isStabilized = (not isZeroOp(C));
189 
190  // grab operators from state object
191  LinearOp massMatrix = state->getLinearOp(velMassStr);
192 
193  // The logic follows like this
194  // if there is no mass matrix available --> build from F
195  // if there is a mass matrix and the inverse hasn't yet been built
196  // --> build from the mass matrix
197  // otherwise, there is already an invMass_ matrix that is appropriate
198  // --> use that one
199  if (massMatrix == Teuchos::null) {
200  Teko_DEBUG_MSG(
201  "PL-LSC::initializeState Build Scaling <F> type \"" << getDiagonalName(scaleType_) << "\"",
202  1);
203  state->invMass_ = getInvDiagonalOp(F, scaleType_);
204  } else if (state->invMass_ == Teuchos::null) {
205  Teko_DEBUG_MSG("PL-LSC::initializeState Build Scaling <mass> type \""
206  << getDiagonalName(scaleType_) << "\"",
207  1);
208  state->invMass_ = getInvDiagonalOp(massMatrix, scaleType_);
209  }
210  // else "invMass_" should be set and there is no reason to rebuild it
211 
212  // if this is a stable discretization...we are done!
213  if (not isStabilized) {
214  state->aiD_ = Teuchos::null;
215 
216  state->setInitialized(true);
217 
218  return;
219  }
220 
221  // compute alpha scaled inv(D): EHSST2007 Eq. 4.29
222  // construct B_idF_Bt and save it for refilling later: This could reuse BQBt graph
223  LinearOp invDiagF = getInvDiagonalOp(F);
224  Teko::ModifiableLinearOp& modB_idF_Bt = state->getModifiableOp("BidFBt");
225  modB_idF_Bt = explicitMultiply(B, invDiagF, Bt, modB_idF_Bt);
226  const LinearOp B_idF_Bt = modB_idF_Bt;
227 
228  MultiVector vec_D = getDiagonal(B_idF_Bt); // this memory could be reused
229  update(-1.0, getDiagonal(C), 1.0, vec_D); // vec_D = diag(B*inv(diag(F))*Bt)-diag(C)
230  const LinearOp invD = buildInvDiagonal(vec_D, "inv(D)");
231 
232  Teko_DEBUG_MSG("Calculating alpha", 10);
233  const LinearOp BidFBtidD = multiply<double>(B_idF_Bt, invD);
234  double num = std::fabs(Teko::computeSpectralRad(BidFBtidD, 5e-2, false, eigSolveParam_));
235  Teko_DEBUG_MSG("Calculated alpha", 10);
236  state->alpha_ = 1.0 / num;
237  state->aiD_ = Thyra::scale(state->alpha_, invD);
238 
239  Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM << "PL-LSC Alpha Parameter = " << state->alpha_ << std::endl;
240  Teko_DEBUG_MSG_END()
241 
242  state->setInitialized(true);
243 }
244 
250 void PresLaplaceLSCStrategy::computeInverses(const BlockedLinearOp& A,
251  LSCPrecondState* state) const {
252  Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::computeInverses", 10);
253  Teko_DEBUG_EXPR(Teuchos::Time invTimer(""));
254 
255  std::string presLapStr = getPressureLaplaceString();
256 
257  const LinearOp F = getBlock(0, 0, A);
258  const LinearOp presLap = state->getLinearOp(presLapStr);
259 
261 
262  // (re)build the inverse of F
263  Teko_DEBUG_MSG("PL-LSC::computeInverses Building inv(F)", 1);
264  Teko_DEBUG_EXPR(invTimer.start(true));
265  ModifiableLinearOp& invF = state->getModifiableOp("invF");
266  if (invF == Teuchos::null) {
267  invF = buildInverse(*invFactoryV_, F);
268  } else {
269  rebuildInverse(*invFactoryV_, F, invF);
270  }
271  Teko_DEBUG_EXPR(invTimer.stop());
272  Teko_DEBUG_MSG("PL-LSC::computeInverses GetInvF = " << invTimer.totalElapsedTime(), 1);
273 
275 
276  // (re)build the inverse of P
277  Teko_DEBUG_MSG("PL-LSC::computeInverses Building inv(PresLap)", 1);
278  Teko_DEBUG_EXPR(invTimer.start(true));
279  ModifiableLinearOp& invPresLap = state->getModifiableOp("invPresLap");
280  if (invPresLap == Teuchos::null) {
281  invPresLap = buildInverse(*invFactoryP_, presLap);
282  } else {
283  // not need because the pressure laplacian never changes
284  // rebuildInverse(*invFactoryP_,presLap,invPresLap);
285  }
286  Teko_DEBUG_EXPR(invTimer.stop());
287  Teko_DEBUG_MSG("PL-LSC::computeInverses GetInvBQBt = " << invTimer.totalElapsedTime(), 1);
288 }
289 
291 void PresLaplaceLSCStrategy::initializeFromParameterList(const Teuchos::ParameterList& pl,
292  const InverseLibrary& invLib) {
293  // get string specifying inverse
294  std::string invStr = "", invVStr = "", invPStr = "";
295 #if defined(Teko_ENABLE_Amesos)
296  invStr = "Amesos";
297 #elif defined(Teko_ENABLE_Amesos2)
298  invStr = "Amesos2";
299 #endif
300 
301  bool useLDU = false;
302  scaleType_ = AbsRowSum;
303 
304  // "parse" the parameter list
305  if (pl.isParameter("Inverse Type")) invStr = pl.get<std::string>("Inverse Type");
306  if (pl.isParameter("Inverse Velocity Type"))
307  invVStr = pl.get<std::string>("Inverse Velocity Type");
308  if (pl.isParameter("Inverse Pressure Type"))
309  invPStr = pl.get<std::string>("Inverse Pressure Type");
310  if (pl.isParameter("Use LDU")) useLDU = pl.get<bool>("Use LDU");
311  if (pl.isParameter("Use Mass Scaling")) useMass_ = pl.get<bool>("Use Mass Scaling");
312  if (pl.isParameter("Eigen Solver Iterations"))
313  eigSolveParam_ = pl.get<int>("Eigen Solver Iterations");
314  if (pl.isParameter("Scaling Type")) {
315  scaleType_ = getDiagonalType(pl.get<std::string>("Scaling Type"));
316  TEUCHOS_TEST_FOR_EXCEPT(scaleType_ == NotDiag);
317  }
318 
319  // set defaults as needed
320  if (invVStr == "") invVStr = invStr;
321  if (invPStr == "") invPStr = invStr;
322 
323  Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM << "LSC Inverse Strategy Parameters: " << std::endl;
324  DEBUG_STREAM << " inv v type = \"" << invVStr << "\"" << std::endl;
325  DEBUG_STREAM << " inv p type = \"" << invPStr << "\"" << std::endl;
326  DEBUG_STREAM << " use ldu = " << useLDU << std::endl;
327  DEBUG_STREAM << " use mass = " << useMass_ << std::endl;
328  DEBUG_STREAM << " scale type = " << getDiagonalName(scaleType_) << std::endl;
329  DEBUG_STREAM << "LSC Pressure Laplace Strategy Parameter list: " << std::endl;
330  pl.print(DEBUG_STREAM);
331  Teko_DEBUG_MSG_END()
332 
333  // build velocity inverse factory
334  invFactoryV_ = invLib.getInverseFactory(invVStr);
335  invFactoryP_ = invFactoryV_; // by default these are the same
336  if (invVStr != invPStr) // if different, build pressure inverse factory
337  invFactoryP_ = invLib.getInverseFactory(invPStr);
338 
339  // set other parameters
340  setUseFullLDU(useLDU);
341 }
342 
344 Teuchos::RCP<Teuchos::ParameterList> PresLaplaceLSCStrategy::getRequestedParameters() const {
345  Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::getRequestedParameters", 10);
346  Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList());
347 
348  // grab parameters from F solver
349  RCP<Teuchos::ParameterList> fList = invFactoryV_->getRequestedParameters();
350  if (fList != Teuchos::null) {
351  Teuchos::ParameterList::ConstIterator itr;
352  for (itr = fList->begin(); itr != fList->end(); ++itr) pl->setEntry(itr->first, itr->second);
353  }
354 
355  // grab parameters from S solver
356  RCP<Teuchos::ParameterList> sList = invFactoryP_->getRequestedParameters();
357  if (sList != Teuchos::null) {
358  Teuchos::ParameterList::ConstIterator itr;
359  for (itr = sList->begin(); itr != sList->end(); ++itr) pl->setEntry(itr->first, itr->second);
360  }
361 
362  // use the mass matrix
363  if (useMass_) pl->set(getVelocityMassString(), false, "Velocity mass matrix");
364  pl->set(getPressureLaplaceString(), false, "Pressure Laplacian matrix");
365 
366  return pl;
367 }
368 
370 bool PresLaplaceLSCStrategy::updateRequestedParameters(const Teuchos::ParameterList& pl) {
371  Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::updateRequestedParameters", 10);
372  bool result = true;
373 
374  // update requested parameters in solvers
375  result &= invFactoryV_->updateRequestedParameters(pl);
376  result &= invFactoryP_->updateRequestedParameters(pl);
377 
378  Teuchos::ParameterList hackList(pl);
379 
380  // get required operator acknowledgment...user must set these to true
381  bool plo = hackList.get<bool>(getPressureLaplaceString(), false);
382 
383  bool vmo = true;
384  if (useMass_) vmo = hackList.get<bool>(getVelocityMassString(), false);
385 
386  if (not plo) {
387  Teko_DEBUG_MSG("User must acknowledge the use of the \"" << getPressureLaplaceString() << "\"!",
388  0);
389  }
390  if (not vmo) {
391  Teko_DEBUG_MSG("User must acknowledge the use of the \"" << getVelocityMassString() << "\"!",
392  0);
393  }
394 
395  result &= (plo & vmo);
396 
397  return result;
398 }
399 
400 } // end namespace NS
401 } // end namespace Teko
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
An implementation of a state object for block preconditioners.
virtual Teko::LinearOp getLinearOp(const std::string &name)
Add a named operator to the state object.
LinearOp invMass_
Inverse mass operator ( )
Preconditioner state for the LSC factory.
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
virtual void setInitialized(bool init=true)
virtual Teko::ModifiableLinearOp & getModifiableOp(const std::string &name)
Add a named operator to the state object.