Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_DiagnosticPreconditionerFactory.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 // Teko includes
11 #include "Teko_DiagnosticPreconditionerFactory.hpp"
12 
13 #include "Teko_PreconditionerInverseFactory.hpp"
15 
16 #include "Teuchos_TimeMonitor.hpp"
17 
18 namespace Teko {
19 
22  : outputStream_(Teko::getOutputStream()),
23  invFactory_(Teuchos::null),
24  diagString_("<label me!>"),
25  printResidual_(false) {}
26 
31  const Teuchos::RCP<Teko::InverseFactory>& invFactory, const std::string& label,
32  const Teuchos::RCP<std::ostream>& os, bool printResidual)
33  : outputStream_(Teko::getOutputStream()),
34  invFactory_(invFactory),
35  precFactory_(Teuchos::null),
36  diagString_(label),
37  printResidual_(printResidual) {
38  initTimers(diagString_);
39 
40  if (os != Teuchos::null) outputStream_ = os;
41 }
42 
47  const Teuchos::RCP<Teko::InverseFactory>& invFactory,
48  const Teuchos::RCP<Teko::InverseFactory>& precFactory, const std::string& label,
49  const Teuchos::RCP<std::ostream>& os, bool printResidual)
50  : outputStream_(Teko::getOutputStream()),
51  invFactory_(invFactory),
52  precFactory_(precFactory),
53  diagString_(label),
54  printResidual_(printResidual) {
55  initTimers(diagString_);
56 
57  if (os != Teuchos::null) outputStream_ = os;
58 }
59 
60 double DiagnosticPreconditionerFactory::totalInitialBuildTime() const {
61  return buildTimer_->totalElapsedTime() + precBuildTimer_->totalElapsedTime();
62 }
63 
64 double DiagnosticPreconditionerFactory::totalRebuildTime() const {
65  return rebuildTimer_->totalElapsedTime() + precRebuildTimer_->totalElapsedTime();
66 }
67 
69  // check timers for null
70  if (buildTimer_ == Teuchos::null || rebuildTimer_ == Teuchos::null) {
71  // (*outputStream_) << "DiagnosticPreconditionerFactory \"" << diagString_ << "\": "
72  // << "Timers not initialized" << std::endl;
73 
74  return;
75  }
76 
77  double initBuildTime = totalInitialBuildTime();
78  int initBuilds = numInitialBuilds();
79 
80  double initRebuildTime = totalRebuildTime();
81  int initRebuilds = numRebuilds();
82 
83  (*outputStream_) << "DiagnosticPreconditionerFactory \"" << diagString_ << "\":\n";
84 
85  // print build string
86  (*outputStream_) << " build elapsed = " << initBuildTime << ", "
87  << "num builds = " << initBuilds << ", ";
88  if (initBuilds > 0)
89  (*outputStream_) << "timer/app = " << initBuildTime / double(initBuilds) << "\n";
90  else
91  (*outputStream_) << "timer/app = "
92  << "none"
93  << "\n";
94 
95  // print rebuild string
96  (*outputStream_) << " rebuild elapsed = " << initRebuildTime << ", "
97  << "num rebuilds = " << initRebuilds << ", ";
98  if (initRebuilds > 0)
99  (*outputStream_) << "timer/app = " << initRebuildTime / double(initRebuilds) << "\n";
100  else
101  (*outputStream_) << "timer/app = "
102  << "none"
103  << "\n";
104 
105  // print total string
106  (*outputStream_) << " total elapsed = " << initRebuildTime + initBuildTime << ", "
107  << "num rebuilds = " << initRebuilds + initBuilds << ", ";
108  if (initBuilds + initRebuilds > 0)
109  (*outputStream_) << "timer/app = "
110  << (initRebuildTime + initBuildTime) / double(initRebuilds + initBuilds)
111  << std::endl;
112  else
113  (*outputStream_) << "timer/app = "
114  << "none" << std::endl;
115 }
116 
121  LinearOp& lo, PreconditionerState& state) const {
122  using Teuchos::RCP;
123  using Teuchos::rcp_dynamic_cast;
124 
125  TEUCHOS_TEST_FOR_EXCEPTION(
126  invFactory_ == Teuchos::null, std::runtime_error,
127  "ERROR: Teko::DiagnosticPreconditionerFactory::buildPreconditionerOperator requires that an "
128  << "inverse factory has been set. Currently it is null!");
129 
130  TEUCHOS_TEST_FOR_EXCEPTION(
131  buildTimer_ == Teuchos::null || rebuildTimer_ == Teuchos::null, std::runtime_error,
132  "ERROR: Teko::DiagnosticPreconditionerFactory::buildPreconditionerOperator requires that "
133  << "the timers be initialized. Currently they are null! (label = \"" << diagString_
134  << "\")");
135 
136  // build user specified preconditioner
137  ModifiableLinearOp& diagOp_ptr = state.getModifiableOp("diagnosticOp");
138  ModifiableLinearOp& diagOp_prec_ptr = state.getModifiableOp("prec_diagnosticOp");
139 
140  if (precFactory_ != Teuchos::null) {
141  if (diagOp_prec_ptr == Teuchos::null) {
142  {
143  // start timer on construction, end on destruction
144  Teuchos::TimeMonitor monitor(*precBuildTimer_, false);
145 
146  diagOp_prec_ptr = precFactory_->buildInverse(lo);
147  }
148 
149  state.addModifiableOp("prec_diagnosticOp", diagOp_prec_ptr);
150  } else {
151  Teuchos::TimeMonitor monitor(*precRebuildTimer_, false);
152  Teko::rebuildInverse(*precFactory_, lo, diagOp_prec_ptr);
153  }
154  }
155 
156  if (diagOp_ptr == Teuchos::null) {
157  ModifiableLinearOp invOp;
158  {
159  // start timer on construction, end on destruction
160  Teuchos::TimeMonitor monitor(*buildTimer_, false);
161 
162  if (diagOp_prec_ptr.is_null())
163  invOp = Teko::buildInverse(*invFactory_, lo);
164  else
165  invOp = Teko::buildInverse(*invFactory_, lo, diagOp_prec_ptr);
166  }
167 
168  // only printing residual requires use of forward operator
169  if (printResidual_)
170  diagOp_ptr = createDiagnosticLinearOp(outputStream_, lo, invOp, diagString_);
171  else
172  diagOp_ptr = createDiagnosticLinearOp(outputStream_, invOp, diagString_);
173  } else {
174  RCP<DiagnosticLinearOp> diagOp = rcp_dynamic_cast<DiagnosticLinearOp>(diagOp_ptr);
175 
176  // only printing residual requires use of forward operator
177  if (printResidual_) diagOp->setForwardOp(lo);
178 
179  ModifiableLinearOp invOp = diagOp->getModifiableOp();
180  {
181  // start timer on construction, end on destruction
182  Teuchos::TimeMonitor monitor(*rebuildTimer_, false);
183 
184  if (diagOp_prec_ptr.is_null())
185  Teko::rebuildInverse(*invFactory_, lo, invOp);
186  else
187  Teko::rebuildInverse(*invFactory_, lo, diagOp_prec_ptr, invOp);
188  }
189  }
190 
191  return diagOp_ptr.getConst();
192 }
193 
198  const Teuchos::ParameterList& settings) {
199  TEUCHOS_TEST_FOR_EXCEPTION(
200  not settings.isParameter("Inverse Factory"), std::runtime_error,
201  "Parameter \"Inverse Factory\" is required by a Teko::DiagnosticPreconditionerFactory");
202  TEUCHOS_TEST_FOR_EXCEPTION(
203  not settings.isParameter("Descriptive Label"), std::runtime_error,
204  "Parameter \"Descriptive Label\" is required by a Teko::DiagnosticPreconditionerFactory");
205 
206  // grab library and preconditioner name
207  std::string invName = settings.get<std::string>("Inverse Factory");
208  std::string precName = "";
209  if (settings.isParameter("Preconditioner Factory"))
210  precName = settings.get<std::string>("Preconditioner Factory");
211  diagString_ = settings.get<std::string>("Descriptive Label");
212 
213  // build preconditioner factory
214  Teuchos::RCP<const InverseLibrary> il = getInverseLibrary();
215  invFactory_ = il->getInverseFactory(invName);
216  if (precName != "") precFactory_ = il->getInverseFactory(precName);
217  TEUCHOS_TEST_FOR_EXCEPTION(invFactory_ == Teuchos::null, std::runtime_error,
218  "ERROR: \"Inverse Factory\" = " << invName << " could not be found");
219 
220  if (settings.isParameter("Print Residual")) printResidual_ = settings.get<bool>("Print Residual");
221 
222  // build timers to use
223  initTimers(diagString_);
224 }
225 
229 Teuchos::RCP<Teuchos::ParameterList> DiagnosticPreconditionerFactory::getRequestedParameters()
230  const {
231  TEUCHOS_TEST_FOR_EXCEPTION(
232  invFactory_ == Teuchos::null, std::runtime_error,
233  "ERROR: Teko::DiagnosticPreconditionerFactory::getRequestedParameters requires that a "
234  << "preconditioner factory has been set. Currently it is null!");
235 
236  return invFactory_->getRequestedParameters();
237 }
238 
241 bool DiagnosticPreconditionerFactory::updateRequestedParameters(const Teuchos::ParameterList& pl) {
242  TEUCHOS_TEST_FOR_EXCEPTION(
243  invFactory_ == Teuchos::null, std::runtime_error,
244  "ERROR: Teko::DiagnosticPreconditionerFactory::updateRequestedParameters requires that a "
245  << "preconditioner factory has been set. Currently it is null!");
246 
247  bool success = true;
248  success &= invFactory_->updateRequestedParameters(pl);
249  if (precFactory_) success &= precFactory_->updateRequestedParameters(pl);
250 
251  return success;
252 }
253 
254 void DiagnosticPreconditionerFactory::initTimers(const std::string& str) {
255  buildTimer_ = Teuchos::rcp(new Teuchos::Time(str + " buildTimer"));
256  rebuildTimer_ = Teuchos::rcp(new Teuchos::Time(str + " rebuildTimer"));
257  precBuildTimer_ = Teuchos::rcp(new Teuchos::Time(str + " precBuildTimer"));
258  precRebuildTimer_ = Teuchos::rcp(new Teuchos::Time(str + " precRebuildTimer"));
259 }
260 
261 } // end namespace Teko
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
virtual Teuchos::RCP< Teuchos::ParameterList > getRequestedParameters() const
Request the additional parameters this preconditioner factory needs.
virtual ~DiagnosticPreconditionerFactory()
default destructor: prints out diagnostic string
DiagnosticPreconditionerFactory()
Default constructor, for use with the AutoClone class.
virtual bool updateRequestedParameters(const Teuchos::ParameterList &pl)
Update this object with the fields from a parameter list.
This linear operator prints diagnostics about operator application and creation times. It is useful for debugging problems and determining bottle necks.
virtual void addModifiableOp(const std::string &name, const Teko::ModifiableLinearOp &mlo)
Add a named operator to the state object.
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
Teuchos::RCP< const InverseLibrary > getInverseLibrary() const
Get the inverse library used by this preconditioner factory.
virtual void initializeFromParameterList(const Teuchos::ParameterList &settings)
This function builds the internals of the preconditioner factory from a parameter list...
An implementation of a state object preconditioners.
virtual LinearOp buildPreconditionerOperator(LinearOp &lo, PreconditionerState &state) const
Function that is called to build the preconditioner for the linear operator that is passed in...
virtual Teko::ModifiableLinearOp & getModifiableOp(const std::string &name)
Add a named operator to the state object.