Stratimikos Version of the Day
Loading...
Searching...
No Matches
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
27namespace {
28
29Teuchos::RCP<Teuchos::Time> overallTimer, creationTimer, factorizationTimer;
30
31const std::string Ifpack_name = "Ifpack";
32
33const std::string IfpackSettings_name = "Ifpack Settings";
34
35const std::string PrecType_name = "Prec Type";
36Teuchos::RCP<Teuchos::StringToIntegralParameterEntryValidator<Ifpack::EPrecType> >
37precTypeValidator; // Will be setup below!
38const Ifpack::EPrecType PrecType_default = Ifpack::ILU;
39const std::string PrecTypeName_default = Ifpack::precTypeNames[PrecType_default];
40
41const std::string Overlap_name = "Overlap";
42const int Overlap_default = 0;
43
44
45TEUCHOS_STATIC_SETUP()
46{
47 TEUCHOS_ADD_STRINGTOINTEGRALVALIDATOR_CONVERTER(Ifpack::EPrecType);
48}
49
50
51} // namespace
52
53namespace 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;
73 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
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
99Teuchos::RCP<PreconditionerBase<double> >
101{
102 return Teuchos::rcp(new DefaultPreconditioner<double>());
103}
104
106 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc
107 ,PreconditionerBase<double> *prec
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;
121 using Teuchos::implicit_cast;
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
136 Teuchos::RCP<const LinearOpBase<double> >
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 //
144 Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
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
156 RCP<const Epetra_RowMatrix>
157 epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true);
158 TEUCHOS_TEST_FOR_EXCEPTION(
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 //
165 DefaultPreconditioner<double>
166 *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
167 //
168 // Get the EpetraLinearOp object that is used to implement the preconditoner linear op
169 //
170 RCP<EpetraLinearOp>
171 epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true);
172 //
173 // Get the embedded Ifpack_Preconditioner object if it exists
174 //
175 Teuchos::RCP<Ifpack_Preconditioner>
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(
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()) {
216 Teuchos::ParameterList
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
266 ,EPETRA_OP_APPLY_APPLY_INVERSE
267 ,EPETRA_OP_ADJOINT_SUPPORTED
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
299void IfpackPreconditionerFactory::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList)
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
321Teuchos::RCP<Teuchos::ParameterList>
326
327Teuchos::RCP<Teuchos::ParameterList>
329{
330 Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_;
331 paramList_ = Teuchos::null;
332 return _paramList;
333}
334
335Teuchos::RCP<const Teuchos::ParameterList>
337{
338 return paramList_;
339}
340
341Teuchos::RCP<const Teuchos::ParameterList>
343{
344 using Teuchos::rcp;
345 using Teuchos::rcp_implicit_cast;
346 typedef Teuchos::ParameterEntryValidator PEV;
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!
352 Teuchos::Array<std::string>
353 precTypeNames;
354 precTypeNames.insert(
355 precTypeNames.begin(),
358 );
359 Teuchos::Array<Ifpack::EPrecType>
360 precTypeValues;
361 precTypeValues.insert(
362 precTypeValues.begin(),
365 );
366 precTypeValidator = rcp(
367 new Teuchos::StringToIntegralParameterEntryValidator<Ifpack::EPrecType>(
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
410void 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
static const int numPrecTypes
static const char * precTypeNames[numPrecTypes]
static const char * toString(const EPrecType precType)
Ifpack_Preconditioner * Create(const std::string PrecType, Epetra_RowMatrix *Matrix, const int overlap=0, bool overrideSerialDefault=false)
static const EPrecType precTypeValues[numPrecTypes]
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
void uninitializePrec(PreconditionerBase< double > *prec, Teuchos::RCP< const LinearOpSourceBase< double > > *fwdOpSrc, ESupportSolveUse *supportSolveUse) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Teuchos::RCP< PreconditionerBase< double > > createPrec() const
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
bool isCompatible(const LinearOpSourceBase< double > &fwdOpSrc) const
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
void initializePrec(const Teuchos::RCP< const LinearOpSourceBase< double > > &fwdOpSrc, PreconditionerBase< double > *prec, const ESupportSolveUse supportSolveUse) const

Generated for Stratimikos by doxygen 1.9.8