Stratimikos  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Thyra_IfpackPreconditionerFactory.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Stratimikos: Thyra-based strategies for linear solvers
4 //
5 // Copyright 2006 NTESS and the Stratimikos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Thyra_IfpackPreconditionerFactory.hpp"
11 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
12 #include "Thyra_EpetraLinearOp.hpp"
13 #include "Thyra_DefaultPreconditioner.hpp"
14 #include "Ifpack_ValidParameters.h"
15 #include "Ifpack_Preconditioner.h"
16 #include "Ifpack.h"
17 #include "Epetra_RowMatrix.h"
18 #include "Teuchos_TimeMonitor.hpp"
19 #include "Teuchos_dyn_cast.hpp"
20 #include "Teuchos_implicit_cast.hpp"
21 #include "Teuchos_StandardParameterEntryValidators.hpp"
22 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
23 #include "Teuchos_ValidatorXMLConverterDB.hpp"
24 #include "Teuchos_StaticSetupMacro.hpp"
25 
26 
27 namespace {
28 
29 Teuchos::RCP<Teuchos::Time> overallTimer, creationTimer, factorizationTimer;
30 
31 const std::string Ifpack_name = "Ifpack";
32 
33 const std::string IfpackSettings_name = "Ifpack Settings";
34 
35 const std::string PrecType_name = "Prec Type";
37 precTypeValidator; // Will be setup below!
38 const Ifpack::EPrecType PrecType_default = Ifpack::ILU;
39 const std::string PrecTypeName_default = Ifpack::precTypeNames[PrecType_default];
40 
41 const std::string Overlap_name = "Overlap";
42 const int Overlap_default = 0;
43 
44 
45 TEUCHOS_STATIC_SETUP()
46 {
48 }
49 
50 
51 } // namespace
52 
53 namespace Thyra {
54 
55 // Constructors/initializers/accessors
56 
58  :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd()))
59  ,precType_(PrecType_default)
60  ,overlap_(Overlap_default)
61 {
62  initializeTimers();
63  getValidParameters(); // Make sure validators get created!
64 }
65 
66 // Overridden from PreconditionerFactoryBase
67 
69  const LinearOpSourceBase<double> &fwdOpSrc
70  ) const
71 {
72  using Teuchos::outArg;
74  EOpTransp epetraFwdOpTransp;
75  EApplyEpetraOpAs epetraFwdOpApplyAs;
76  EAdjointEpetraOp epetraFwdOpAdjointSupport;
77  double epetraFwdOpScalar;
78  epetraFwdOpViewExtractor_->getEpetraOpView(
79  fwdOpSrc.getOp(),
80  outArg(epetraFwdOp), outArg(epetraFwdOpTransp),
81  outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport),
82  outArg(epetraFwdOpScalar)
83  );
84  if( !dynamic_cast<const Epetra_RowMatrix*>(&*epetraFwdOp) )
85  return false;
86  return true;
87 }
88 
90 {
91  return true;
92 }
93 
95 {
96  return false; // See comment below
97 }
98 
101 {
103 }
104 
106  const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc
108  ,const ESupportSolveUse /* supportSolveUse */
109  ) const
110 {
111  using Teuchos::outArg;
112  using Teuchos::OSTab;
113  using Teuchos::dyn_cast;
114  using Teuchos::RCP;
115  using Teuchos::null;
116  using Teuchos::rcp;
117  using Teuchos::rcp_dynamic_cast;
118  using Teuchos::rcp_const_cast;
119  using Teuchos::set_extra_data;
120  using Teuchos::get_optional_extra_data;
122  Teuchos::Time totalTimer(""), timer("");
123  totalTimer.start(true);
124 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR
125  Teuchos::TimeMonitor overallTimeMonitor(*overallTimer);
126 #endif
127  const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
128  const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
129  Teuchos::OSTab tab(out);
130  if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW))
131  *out << "\nEntering Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n";
132 #ifdef TEUCHOS_DEBUG
133  TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
134  TEUCHOS_TEST_FOR_EXCEPT(prec==NULL);
135 #endif
137  fwdOp = fwdOpSrc->getOp();
138 #ifdef TEUCHOS_DEBUG
139  TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL);
140 #endif
141  //
142  // Unwrap and get the forward Epetra_Operator object
143  //
145  EOpTransp epetraFwdOpTransp;
146  EApplyEpetraOpAs epetraFwdOpApplyAs;
147  EAdjointEpetraOp epetraFwdOpAdjointSupport;
148  double epetraFwdOpScalar;
149  epetraFwdOpViewExtractor_->getEpetraOpView(
150  fwdOp,
151  outArg(epetraFwdOp), outArg(epetraFwdOpTransp),
152  outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport),
153  outArg(epetraFwdOpScalar)
154  );
155  // Validate what we get is what we need
157  epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true);
159  epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error
160  ,"Error, incorrect apply mode for an Epetra_RowMatrix"
161  );
162  //
163  // Get the concrete preconditioner object
164  //
166  *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
167  //
168  // Get the EpetraLinearOp object that is used to implement the preconditoner linear op
169  //
171  epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true);
172  //
173  // Get the embedded Ifpack_Preconditioner object if it exists
174  //
176  ifpack_precOp;
177  if(epetra_precOp.get())
178  ifpack_precOp = rcp_dynamic_cast<Ifpack_Preconditioner>(epetra_precOp->epetra_op(),true);
179  //
180  // Get the attached forward operator if it exists and make sure that it matches
181  //
182  if(ifpack_precOp.get()) {
183  // ToDo: Get the forward operator and make sure that it matches what is
184  // already being used!
185  }
186  //
187  // Permform initialization if needed
188  //
189  //const bool startingOver = (ifpack_precOp.get() == NULL);
190  const bool startingOver = true;
191  // ToDo: Comment back in the above original version of startingOver to allow
192  // for resuse. Rob H. just pointed out to me that a memory leak is being
193  // created when you just call Ifpack_ILU::Compute() over and over again.
194  // Rob H. said that he will check in a fix the the development branch when
195  // he can.
196  if(startingOver) {
197  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
198  *out << "\nCreating the initial Ifpack_Preconditioner object of type \'"<<Ifpack::toString(precType_)<<"\' ...\n";
199  timer.start(true);
200 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR
201  Teuchos::TimeMonitor creationTimeMonitor(*creationTimer);
202 #endif
203  // Create the initial preconditioner
204  ifpack_precOp = rcp(
205  ::Ifpack::Create(
206  precType_
207  ,const_cast<Epetra_RowMatrix*>(&*epetraFwdRowMat)
208  ,overlap_
209  )
210  );
211  timer.stop();
212  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
213  OSTab(out).o() <<"=> Creation time = "<<timer.totalElapsedTime()<<" sec\n";
214  // Set parameters if the list exists
215  if(paramList_.get()) {
217  &ifpackSettingsPL = paramList_->sublist(IfpackSettings_name);
218  // Above will create new sublist if it does not exist!
219  TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->SetParameters(ifpackSettingsPL));
220  // Above, I have not idea how any error messages for a mistake will be
221  // reported back to the user!
222  }
223  // Initialize the structure for the preconditioner
224  TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->Initialize());
225  }
226  //
227  // Attach the epetraFwdOp to the ifpack_precOp to guarantee that it will not go away
228  //
229  set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ifpack_precOp),
230  Teuchos::POST_DESTROY, false);
231  //
232  // Update the factorization
233  //
234  {
235  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
236  *out << "\nComputing the preconditioner ...\n";
237 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR
238  Teuchos::TimeMonitor factorizationTimeMonitor(*factorizationTimer);
239 #endif
240  timer.start(true);
241  TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->Compute());
242  timer.stop();
243  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
244  OSTab(out).o() <<"=> Setup time = "<<timer.totalElapsedTime()<<" sec\n";
245  }
246  //
247  // Compute the conditioner number estimate if asked
248  //
249 
250  // ToDo: Implement
251 
252  //
253  // Attach fwdOp to the ifpack_precOp
254  //
255  set_extra_data(fwdOpSrc, "IFPF::fwdOpSrc", Teuchos::inOutArg(ifpack_precOp),
256  Teuchos::POST_DESTROY, false);
257  //
258  // Initialize the output EpetraLinearOp
259  //
260  if(startingOver) {
261  epetra_precOp = rcp(new EpetraLinearOp);
262  }
263  epetra_precOp->initialize(
264  ifpack_precOp
265  ,epetraFwdOpTransp
268  );
269  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_MEDIUM)) {
270  *out << "\nDescription of created preconditioner:\n";
271  OSTab tab2(out);
272  ifpack_precOp->Print(*out);
273  }
274 
275  //
276  // Initialize the preconditioner
277  //
278  defaultPrec->initializeUnspecified(
279  Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp)
280  );
281  totalTimer.stop();
282  if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW))
283  *out << "\nTotal time in IfpackPreconditionerFactory = "<<totalTimer.totalElapsedTime()<<" sec\n";
284  if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW))
285  *out << "\nLeaving Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n";
286 }
287 
289  PreconditionerBase<double> * /* prec */
290  ,Teuchos::RCP<const LinearOpSourceBase<double> > * /* fwdOpSrc */
291  ,ESupportSolveUse * /* supportSolveUse */
292  ) const
293 {
294  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement when needed!
295 }
296 
297 // Overridden from ParameterListAcceptor
298 
300 {
301  TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL);
302  paramList->validateParameters(*this->getValidParameters(),2);
303  // Note: The above validation will validate right down into the the sublist
304  // named IfpackSettings_name!
305  paramList_ = paramList;
306  overlap_ = paramList_->get(Overlap_name,Overlap_default);
307  std::ostringstream oss;
308  oss << "(sub)list \""<<paramList->name()<<"\"parameter \"Prec Type\"";
309  precType_ =
310  ( paramList_.get()
311  ? precTypeValidator->getIntegralValue(*paramList_,PrecType_name,PrecTypeName_default)
312  : PrecType_default
313  );
314  Teuchos::readVerboseObjectSublist(&*paramList_,this);
315 #ifdef TEUCHOS_DEBUG
316  // Validate my use of the parameters!
317  paramList->validateParameters(*this->getValidParameters(),1);
318 #endif
319 }
320 
323 {
324  return paramList_;
325 }
326 
329 {
330  Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_;
331  paramList_ = Teuchos::null;
332  return _paramList;
333 }
334 
337 {
338  return paramList_;
339 }
340 
343 {
344  using Teuchos::rcp;
345  using Teuchos::rcp_implicit_cast;
347  static Teuchos::RCP<Teuchos::ParameterList> validParamList;
348  if(validParamList.get()==NULL) {
349  validParamList = Teuchos::rcp(new Teuchos::ParameterList(Ifpack_name));
350  {
351  // Create the validator for the preconditioner type!
353  precTypeNames;
354  precTypeNames.insert(
355  precTypeNames.begin(),
358  );
360  precTypeValues;
361  precTypeValues.insert(
362  precTypeValues.begin(),
365  );
366  precTypeValidator = rcp(
368  precTypeNames,precTypeValues,PrecType_name
369  )
370  );
371  }
372  validParamList->set(
373  PrecType_name, PrecTypeName_default,
374  "Type of Ifpack preconditioner to use.",
375  rcp_implicit_cast<const PEV>(precTypeValidator)
376  );
377  validParamList->set(
378  Overlap_name, Overlap_default,
379  "Number of rows/columns overlapped between subdomains in different"
380  "\nprocesses in the additive Schwarz-type domain-decomposition preconditioners."
381  );
382  validParamList->set(
383  IfpackSettings_name, Ifpack_GetValidParameters(),
384  "Preconditioner settings that are passed onto the Ifpack preconditioners themselves."
385  );
386  // Note that in the above setParameterList(...) function that we actually
387  // validate down into the first level of this sublist. Really the
388  // Ifpack_Preconditioner objects themselves should do validation but we do
389  // it ourselves taking the return from the Ifpack_GetValidParameters()
390  // function as gospel!
391  Teuchos::setupVerboseObjectSublist(&*validParamList);
392  }
393  return validParamList;
394 }
395 
396 // Public functions overridden from Teuchos::Describable
397 
399 {
400  std::ostringstream oss;
401  oss << "Thyra::IfpackPreconditionerFactory{";
402  oss << "precType=\"" << ::Ifpack::toString(precType_) << "\"";
403  oss << ",overlap=" << overlap_;
404  oss << "}";
405  return oss.str();
406 }
407 
408 // private
409 
410 void IfpackPreconditionerFactory::initializeTimers()
411 {
412  if(!overallTimer.get()) {
413 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR
414  overallTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF");
415  creationTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF:Creation");
416  factorizationTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF:Factorization");
417 #endif
418  }
419 }
420 
421 } // namespace Thyra
const std::string & name() const
static const int numPrecTypes
EOpTransp
void initializeUnspecified(const Teuchos::RCP< LinearOpBase< Scalar > > &unspecifiedPrecOp)
basic_OSTab< char > OSTab
static const EPrecType precTypeValues[numPrecTypes]
Teuchos::RCP< PreconditionerBase< double > > createPrec() const
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool isCompatible(const LinearOpSourceBase< double > &fwdOpSrc) const
static const char * toString(const EPrecType precType)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
T_To & dyn_cast(T_From &from)
T * get() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void uninitializePrec(PreconditionerBase< double > *prec, Teuchos::RCP< const LinearOpSourceBase< double > > *fwdOpSrc, ESupportSolveUse *supportSolveUse) const
Ifpack_Preconditioner * Create(const std::string PrecType, Epetra_RowMatrix *Matrix, const int overlap=0, bool overrideSerialDefault=false)
static const char * precTypeNames[numPrecTypes]
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
Teuchos::RCP< LinearOpBase< Scalar > > getNonconstUnspecifiedPrecOp()
static RCP< Time > getNewTimer(const std::string &name)
IntegralType getIntegralValue(ParameterList const &paramList, std::string const &paramName)
void start(bool reset=false)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
double stop()
EAdjointEpetraOp
TypeTo implicit_cast(const TypeFrom &t)
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
ESupportSolveUse
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
#define TEUCHOS_ADD_STRINGTOINTEGRALVALIDATOR_CONVERTER(INTEGRALTYPE)
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
void initializePrec(const Teuchos::RCP< const LinearOpSourceBase< double > > &fwdOpSrc, PreconditionerBase< double > *prec, const ESupportSolveUse supportSolveUse) const
double totalElapsedTime(bool readCurrentTime=false) const
EApplyEpetraOpAs
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
EConj
virtual Teuchos::RCP< const LinearOpBase< Scalar > > getOp() const =0
iterator insert(iterator position, const value_type &x)
iterator begin()
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()

Generated on Fri Dec 20 2024 09:21:59 for Stratimikos by doxygen 1.8.5