Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_PCDStrategy.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_PCDStrategy.hpp"
48 
49 #include "Teuchos_TimeMonitor.hpp"
50 #include "Teko_Utilities.hpp"
51 
52 namespace Teko {
53 namespace NS {
54 
55 using Teuchos::TimeMonitor;
56 
57 Teuchos::RCP<Teuchos::Time> PCDStrategy::initTimer_;
58 Teuchos::RCP<Teuchos::Time> PCDStrategy::invSTimer_;
59 Teuchos::RCP<Teuchos::Time> PCDStrategy::invFTimer_;
60 Teuchos::RCP<Teuchos::Time> PCDStrategy::opsTimer_;
61 
63  if (initTimer_ == Teuchos::null)
64  initTimer_ = TimeMonitor::getNewTimer("PCDStrategy::initializePrec");
65 
66  if (invSTimer_ == Teuchos::null)
67  invSTimer_ = TimeMonitor::getNewTimer("PCDStrategy::initializePrec invS");
68 
69  if (invFTimer_ == Teuchos::null)
70  invFTimer_ = TimeMonitor::getNewTimer("PCDStrategy::initializePrec invF");
71 
72  if (opsTimer_ == Teuchos::null)
73  opsTimer_ = TimeMonitor::getNewTimer("PCDStrategy::initializePrec buildOps");
74 }
75 
76 PCDStrategy::PCDStrategy() : massInverseType_(Diagonal), schurCompOrdering_(false) {
77  pcdParams_ = Teuchos::rcp(new Teuchos::ParameterList);
78  lapParams_ = Teuchos::rcp(new Teuchos::ParameterList);
79 
80  lapParams_->set("Name", getPressureLaplaceString());
81  pcdParams_->set("Name", getPCDString());
82 
83  buildTimers();
84 }
85 
87 PCDStrategy::PCDStrategy(const Teuchos::RCP<InverseFactory>& invFA,
88  const Teuchos::RCP<InverseFactory>& invS)
89  : invFactoryF_(invFA),
90  invFactoryS_(invS),
91  massInverseType_(Diagonal),
92  schurCompOrdering_(false) {
93  pcdParams_ = Teuchos::rcp(new Teuchos::ParameterList);
94  lapParams_ = Teuchos::rcp(new Teuchos::ParameterList);
95 
96  lapParams_->set("Name", getPressureLaplaceString());
97  pcdParams_->set("Name", getPCDString());
98 
99  buildTimers();
100 }
101 
103 const Teko::LinearOp PCDStrategy::getHatInvA00(const Teko::BlockedLinearOp& A,
104  BlockPreconditionerState& state) const {
105  initializeState(A, state);
106 
107  return state.getModifiableOp("invF");
108 }
109 
111 const Teko::LinearOp PCDStrategy::getTildeInvA00(const Teko::BlockedLinearOp& A,
112  BlockPreconditionerState& state) const {
113  initializeState(A, state);
114 
115  return state.getModifiableOp("invF");
116 }
117 
120 const Teko::LinearOp PCDStrategy::getInvS(const Teko::BlockedLinearOp& A,
121  BlockPreconditionerState& state) const {
122  initializeState(A, state);
123 
124  return state.getLinearOp("invS");
125 }
126 
127 void PCDStrategy::initializeState(const Teko::BlockedLinearOp& A,
128  BlockPreconditionerState& state) const {
129  Teko_DEBUG_SCOPE("PCDStrategy::initializeState", 10);
130  TEUCHOS_ASSERT(getRequestHandler() != Teuchos::null);
131 
132  std::string pcdStr = getPCDString();
133  std::string presLapStr = getPressureLaplaceString();
134  std::string presMassStr = getPressureMassString();
135 
136  // no work to be done
137  if (state.isInitialized()) return;
138 
139  Teuchos::TimeMonitor timer(*initTimer_, true);
140 
141  // extract sub blocks
142  LinearOp F = Teko::getBlock(0, 0, A);
143  LinearOp Bt = Teko::getBlock(0, 1, A);
144  LinearOp B = Teko::getBlock(1, 0, A);
145  LinearOp C = Teko::getBlock(1, 1, A);
146 
147  LinearOp Qp = getRequestHandler()->request<LinearOp>(presMassStr);
148  TEUCHOS_ASSERT(Qp != Teuchos::null);
149 
150  // build the inverse Laplacian complement
152  LinearOp iQp;
153  if (massInverseType_ == NotDiag) {
154  ModifiableLinearOp& invMass = state.getModifiableOp("invMass");
155  Teko_DEBUG_SCOPE("Building inv(Mass)", 10);
156 
157  if (invMass == Teuchos::null)
158  invMass = buildInverse(*invFactoryS_, Qp);
159  else
160  rebuildInverse(*invFactoryS_, Qp, invMass);
161 
162  iQp = invMass;
163  } else {
164  Teko_DEBUG_MSG(
165  "Building inverse mass of type \"" << Teko::getDiagonalName(massInverseType_) << "\"", 10);
166  iQp = getInvDiagonalOp(Qp, massInverseType_);
167  }
168 
169  // build the inverse Laplacian complement
171  ModifiableLinearOp& invLaplace = state.getModifiableOp("invLaplace");
172  {
173  Teuchos::TimeMonitor timerInvS(*invSTimer_, true);
174 
175  // LinearOp laplace = getRequestHandler()->request<Teko::LinearOp>(presLapStr);
176  LinearOp laplace = getRequestHandler()->request<Teko::LinearOp>(RequestMesg(lapParams_));
177  TEUCHOS_ASSERT(laplace != Teuchos::null);
178  if (invLaplace == Teuchos::null)
179  invLaplace = buildInverse(*invFactoryS_, laplace);
180  else
181  rebuildInverse(*invFactoryS_, laplace, invLaplace);
182  }
183 
184  // build the inverse Schur complement
186  {
187  Teko_DEBUG_SCOPE("Building S", 10);
188  Teuchos::TimeMonitor timerS(*opsTimer_, true);
189 
190  // build Schur-complement
191  // LinearOp pcd = getRequestHandler()->request<Teko::LinearOp>(pcdStr);
192  LinearOp pcd = getRequestHandler()->request<Teko::LinearOp>(RequestMesg(pcdParams_));
193  TEUCHOS_ASSERT(pcd != Teuchos::null);
194  LinearOp invL = invLaplace;
195 
196  LinearOp invS;
197  if (schurCompOrdering_ == false)
198  invS = multiply(iQp, pcd, invL);
199  else
200  invS = multiply(invL, pcd, iQp);
201 
202  state.addLinearOp("invS", invS);
203  }
204 
205  // build inverse F
207  {
208  Teko_DEBUG_SCOPE("Building inv(F)", 10);
209  Teuchos::TimeMonitor timerInvF(*invFTimer_, true);
210 
211  ModifiableLinearOp& invF = state.getModifiableOp("invF");
212  if (invF == Teuchos::null)
213  invF = buildInverse(*invFactoryF_, F);
214  else
215  rebuildInverse(*invFactoryF_, F, invF);
216  }
217 
218  // mark state as initialized
219  state.setInitialized(true);
220 }
221 
233 void PCDStrategy::initializeFromParameterList(const Teuchos::ParameterList& pl,
234  const InverseLibrary& invLib) {
235  Teko_DEBUG_SCOPE("PCDStrategy::initializeFromParameterList", 10);
236 
237  std::string invStr = "", invFStr = "", invSStr = "";
238 #if defined(Teko_ENABLE_Amesos)
239  invStr = "Amesos";
240 #elif defined(Teko_ENABLE_Amesos2)
241  invStr = "Amesos2";
242 #endif
243 
244  massInverseType_ = Diagonal;
245 
246  // "parse" the parameter list
247  if (pl.isParameter("Inverse Type")) invStr = pl.get<std::string>("Inverse Type");
248  if (pl.isParameter("Inverse F Type")) invFStr = pl.get<std::string>("Inverse F Type");
249  if (pl.isParameter("Inverse Laplace Type")) invSStr = pl.get<std::string>("Inverse Laplace Type");
250  if (pl.isParameter("Inverse Mass Type")) {
251  std::string massInverseStr = pl.get<std::string>("Inverse Mass Type");
252 
253  // build inverse types
254  massInverseType_ = getDiagonalType(massInverseStr);
255  }
256  if (pl.isParameter("Flip Schur Complement Ordering"))
257  schurCompOrdering_ = pl.get<bool>("Flip Schur Complement Ordering");
258 
259  // set defaults as needed
260  if (invFStr == "") invFStr = invStr;
261  if (invSStr == "") invSStr = invStr;
262 
263  // read pressure laplace parameters
264  if (pl.isSublist("Pressure Laplace Parameters"))
265  lapParams_ =
266  Teuchos::rcp(new Teuchos::ParameterList(pl.sublist("Pressure Laplace Parameters")));
267  else
268  lapParams_ = Teuchos::rcp(new Teuchos::ParameterList);
269 
270  // read pcd operator parameters
271  if (pl.isSublist("Pressure Convection Diffusion Parameters"))
272  pcdParams_ = Teuchos::rcp(
273  new Teuchos::ParameterList(pl.sublist("Pressure Convection Diffusion Parameters")));
274  else
275  pcdParams_ = Teuchos::rcp(new Teuchos::ParameterList);
276 
277  // The user should not have already added this parameters
278  TEUCHOS_TEST_FOR_EXCEPTION(
279  lapParams_->isParameter("Name"), std::logic_error,
280  "Teko: Parameter \"Name\" is not allowed in the sublist \"" + lapParams_->name() + "\"");
281  TEUCHOS_TEST_FOR_EXCEPTION(
282  lapParams_->isParameter("Tag"), std::logic_error,
283  "Teko: Parameter \"Tag\" is not allowed in the sublist \"" + lapParams_->name() + "\"");
284  TEUCHOS_TEST_FOR_EXCEPTION(
285  pcdParams_->isParameter("Name"), std::logic_error,
286  "Teko: Parameter \"Name\" is not allowed in the sublist \"" + pcdParams_->name() + "\"");
287  TEUCHOS_TEST_FOR_EXCEPTION(
288  pcdParams_->isParameter("Tag"), std::logic_error,
289  "Teko: Parameter \"Tag\" is not allowed in the sublist \"" + pcdParams_->name() + "\"");
290 
291  Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM << "PCD Strategy Parameters: " << std::endl;
292  DEBUG_STREAM << " inv type = \"" << invStr << "\"" << std::endl;
293  DEBUG_STREAM << " inv F type = \"" << invFStr << "\"" << std::endl;
294  DEBUG_STREAM << " inv Laplace type = \"" << invSStr << "\"" << std::endl;
295  DEBUG_STREAM << " inv Mass type = \"" << Teko::getDiagonalName(massInverseType_) << "\""
296  << std::endl;
297  DEBUG_STREAM << "PCD Strategy Parameter list: " << std::endl;
298  pl.print(DEBUG_STREAM);
299  Teko_DEBUG_MSG_END()
300 
301  // build velocity inverse factory
302  invFactoryF_ = invLib.getInverseFactory(invFStr);
303 
304  if (invFStr == invSStr)
305  invFactoryS_ = invFactoryF_;
306  else
307  invFactoryS_ = invLib.getInverseFactory(invSStr);
308 
309  lapParams_->set("Name", getPressureLaplaceString());
310  pcdParams_->set("Name", getPCDString());
311 
312  // setup a request for required operators
313  getRequestHandler()->preRequest<Teko::LinearOp>(getPressureMassString());
314  // getRequestHandler()->preRequest<Teko::LinearOp>(getPCDString());
315  // getRequestHandler()->preRequest<Teko::LinearOp>(getPressureLaplaceString());
316  getRequestHandler()->preRequest<Teko::LinearOp>(Teko::RequestMesg(lapParams_));
317  getRequestHandler()->preRequest<Teko::LinearOp>(Teko::RequestMesg(pcdParams_));
318 }
319 
321 Teuchos::RCP<Teuchos::ParameterList> PCDStrategy::getRequestedParameters() const {
322  TEUCHOS_ASSERT(false);
323 
324  return Teuchos::null;
325 }
326 
328 bool PCDStrategy::updateRequestedParameters(const Teuchos::ParameterList& /* pl */) {
329  TEUCHOS_ASSERT(false);
330 
331  return true;
332 }
333 
334 } // end namespace NS
335 } // end namespace Teko
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
virtual void initializeFromParameterList(const Teuchos::ParameterList &settings, const InverseLibrary &invLib)
This function builds the internals of the state from a parameter list.
virtual const Teko::LinearOp getHatInvA00(const Teko::BlockedLinearOp &A, BlockPreconditionerState &state) const
virtual const Teko::LinearOp getTildeInvA00(const Teko::BlockedLinearOp &A, BlockPreconditionerState &state) const
virtual void addLinearOp(const std::string &name, const Teko::LinearOp &lo)
Add a named operator to the state object.
void initializeState(const Teko::BlockedLinearOp &A, BlockPreconditionerState &state) const
An implementation of a state object for block preconditioners.
Teuchos::RCP< RequestHandler > getRequestHandler() const
This method gets the request handler uses by this object.
virtual Teko::LinearOp getLinearOp(const std::string &name)
Add a named operator to the state object.
PCDStrategy()
default Constructor
virtual bool updateRequestedParameters(const Teuchos::ParameterList &pl)
Update this object with the fields from a parameter list.
Teuchos::RCP< Teuchos::ParameterList > pcdParams_
Passed to application for construction of PCD operator.
virtual const Teko::LinearOp getInvS(const Teko::BlockedLinearOp &A, BlockPreconditionerState &state) const
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
Teuchos::RCP< Teuchos::ParameterList > lapParams_
Passed to application for construction of laplace operator.
virtual void setInitialized(bool init=true)
virtual Teko::ModifiableLinearOp & getModifiableOp(const std::string &name)
Add a named operator to the state object.
virtual Teuchos::RCP< Teuchos::ParameterList > getRequestedParameters() const
Request the additional parameters this preconditioner factory needs.