|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Stratimikos: Thyra-based strategies for linear solvers 00005 // Copyright (2006) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #include "Thyra_IfpackPreconditionerFactory.hpp" 00043 #include "Thyra_EpetraOperatorViewExtractorStd.hpp" 00044 #include "Thyra_EpetraLinearOp.hpp" 00045 #include "Thyra_DefaultPreconditioner.hpp" 00046 #include "Ifpack_ValidParameters.h" 00047 #include "Ifpack_Preconditioner.h" 00048 #include "Ifpack.h" 00049 #include "Epetra_RowMatrix.h" 00050 #include "Teuchos_TimeMonitor.hpp" 00051 #include "Teuchos_dyn_cast.hpp" 00052 #include "Teuchos_implicit_cast.hpp" 00053 #include "Teuchos_StandardParameterEntryValidators.hpp" 00054 #include "Teuchos_VerboseObjectParameterListHelpers.hpp" 00055 #include "Teuchos_ValidatorXMLConverterDB.hpp" 00056 #include "Teuchos_StaticSetupMacro.hpp" 00057 00058 00059 namespace { 00060 00061 Teuchos::RCP<Teuchos::Time> overallTimer, creationTimer, factorizationTimer; 00062 00063 const std::string Ifpack_name = "Ifpack"; 00064 00065 const std::string IfpackSettings_name = "Ifpack Settings"; 00066 00067 const std::string PrecType_name = "Prec Type"; 00068 Teuchos::RCP<Teuchos::StringToIntegralParameterEntryValidator<Ifpack::EPrecType> > 00069 precTypeValidator; // Will be setup below! 00070 const Ifpack::EPrecType PrecType_default = Ifpack::ILU; 00071 const std::string PrecTypeName_default = Ifpack::precTypeNames[PrecType_default]; 00072 00073 const std::string Overlap_name = "Overlap"; 00074 const int Overlap_default = 0; 00075 00076 00077 TEUCHOS_STATIC_SETUP() 00078 { 00079 TEUCHOS_ADD_STRINGTOINTEGRALVALIDATOR_CONVERTER(Ifpack::EPrecType); 00080 } 00081 00082 00083 } // namespace 00084 00085 namespace Thyra { 00086 00087 // Constructors/initializers/accessors 00088 00089 IfpackPreconditionerFactory::IfpackPreconditionerFactory() 00090 :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())) 00091 ,precType_(PrecType_default) 00092 ,overlap_(Overlap_default) 00093 { 00094 initializeTimers(); 00095 getValidParameters(); // Make sure validators get created! 00096 } 00097 00098 // Overridden from PreconditionerFactoryBase 00099 00100 bool IfpackPreconditionerFactory::isCompatible( 00101 const LinearOpSourceBase<double> &fwdOpSrc 00102 ) const 00103 { 00104 using Teuchos::outArg; 00105 Teuchos::RCP<const Epetra_Operator> epetraFwdOp; 00106 EOpTransp epetraFwdOpTransp; 00107 EApplyEpetraOpAs epetraFwdOpApplyAs; 00108 EAdjointEpetraOp epetraFwdOpAdjointSupport; 00109 double epetraFwdOpScalar; 00110 epetraFwdOpViewExtractor_->getEpetraOpView( 00111 fwdOpSrc.getOp(), 00112 outArg(epetraFwdOp), outArg(epetraFwdOpTransp), 00113 outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport), 00114 outArg(epetraFwdOpScalar) 00115 ); 00116 if( !dynamic_cast<const Epetra_RowMatrix*>(&*epetraFwdOp) ) 00117 return false; 00118 return true; 00119 } 00120 00121 bool IfpackPreconditionerFactory::applySupportsConj(EConj conj) const 00122 { 00123 return true; 00124 } 00125 00126 bool IfpackPreconditionerFactory::applyTransposeSupportsConj(EConj conj) const 00127 { 00128 return false; // See comment below 00129 } 00130 00131 Teuchos::RCP<PreconditionerBase<double> > 00132 IfpackPreconditionerFactory::createPrec() const 00133 { 00134 return Teuchos::rcp(new DefaultPreconditioner<double>()); 00135 } 00136 00137 void IfpackPreconditionerFactory::initializePrec( 00138 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc 00139 ,PreconditionerBase<double> *prec 00140 ,const ESupportSolveUse supportSolveUse 00141 ) const 00142 { 00143 using Teuchos::outArg; 00144 using Teuchos::OSTab; 00145 using Teuchos::dyn_cast; 00146 using Teuchos::RCP; 00147 using Teuchos::null; 00148 using Teuchos::rcp; 00149 using Teuchos::rcp_dynamic_cast; 00150 using Teuchos::rcp_const_cast; 00151 using Teuchos::set_extra_data; 00152 using Teuchos::get_optional_extra_data; 00153 using Teuchos::implicit_cast; 00154 Teuchos::Time totalTimer(""), timer(""); 00155 totalTimer.start(true); 00156 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR 00157 Teuchos::TimeMonitor overallTimeMonitor(*overallTimer); 00158 #endif 00159 const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream(); 00160 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); 00161 Teuchos::OSTab tab(out); 00162 if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) 00163 *out << "\nEntering Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n"; 00164 #ifdef TEUCHOS_DEBUG 00165 TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL); 00166 TEUCHOS_TEST_FOR_EXCEPT(prec==NULL); 00167 #endif 00168 Teuchos::RCP<const LinearOpBase<double> > 00169 fwdOp = fwdOpSrc->getOp(); 00170 #ifdef TEUCHOS_DEBUG 00171 TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL); 00172 #endif 00173 // 00174 // Unwrap and get the forward Epetra_Operator object 00175 // 00176 Teuchos::RCP<const Epetra_Operator> epetraFwdOp; 00177 EOpTransp epetraFwdOpTransp; 00178 EApplyEpetraOpAs epetraFwdOpApplyAs; 00179 EAdjointEpetraOp epetraFwdOpAdjointSupport; 00180 double epetraFwdOpScalar; 00181 epetraFwdOpViewExtractor_->getEpetraOpView( 00182 fwdOp, 00183 outArg(epetraFwdOp), outArg(epetraFwdOpTransp), 00184 outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport), 00185 outArg(epetraFwdOpScalar) 00186 ); 00187 // Validate what we get is what we need 00188 RCP<const Epetra_RowMatrix> 00189 epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true); 00190 TEUCHOS_TEST_FOR_EXCEPTION( 00191 epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error 00192 ,"Error, incorrect apply mode for an Epetra_RowMatrix" 00193 ); 00194 // 00195 // Get the concrete preconditioner object 00196 // 00197 DefaultPreconditioner<double> 00198 *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec); 00199 // 00200 // Get the EpetraLinearOp object that is used to implement the preconditoner linear op 00201 // 00202 RCP<EpetraLinearOp> 00203 epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true); 00204 // 00205 // Get the embedded Ifpack_Preconditioner object if it exists 00206 // 00207 Teuchos::RCP<Ifpack_Preconditioner> 00208 ifpack_precOp; 00209 if(epetra_precOp.get()) 00210 ifpack_precOp = rcp_dynamic_cast<Ifpack_Preconditioner>(epetra_precOp->epetra_op(),true); 00211 // 00212 // Get the attached forward operator if it exists and make sure that it matches 00213 // 00214 if(ifpack_precOp.get()) { 00215 // ToDo: Get the forward operator and make sure that it matches what is 00216 // already being used! 00217 } 00218 // 00219 // Permform initialization if needed 00220 // 00221 //const bool startingOver = (ifpack_precOp.get() == NULL); 00222 const bool startingOver = true; 00223 // ToDo: Comment back in the above original version of startingOver to allow 00224 // for resuse. Rob H. just pointed out to me that a memory leak is being 00225 // created when you just call Ifpack_ILU::Compute() over and over again. 00226 // Rob H. said that he will check in a fix the the development branch when 00227 // he can. 00228 if(startingOver) { 00229 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) 00230 *out << "\nCreating the initial Ifpack_Preconditioner object of type \'"<<Ifpack::toString(precType_)<<"\' ...\n"; 00231 timer.start(true); 00232 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR 00233 Teuchos::TimeMonitor creationTimeMonitor(*creationTimer); 00234 #endif 00235 // Create the initial preconditioner 00236 ifpack_precOp = rcp( 00237 ::Ifpack::Create( 00238 precType_ 00239 ,const_cast<Epetra_RowMatrix*>(&*epetraFwdRowMat) 00240 ,overlap_ 00241 ) 00242 ); 00243 timer.stop(); 00244 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) 00245 OSTab(out).o() <<"=> Creation time = "<<timer.totalElapsedTime()<<" sec\n"; 00246 // Set parameters if the list exists 00247 if(paramList_.get()) { 00248 Teuchos::ParameterList 00249 &ifpackSettingsPL = paramList_->sublist(IfpackSettings_name); 00250 // Above will create new sublist if it does not exist! 00251 TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->SetParameters(ifpackSettingsPL)); 00252 // Above, I have not idea how any error messages for a mistake will be 00253 // reported back to the user! 00254 } 00255 // Initialize the structure for the preconditioner 00256 TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->Initialize()); 00257 } 00258 // 00259 // Attach the epetraFwdOp to the ifpack_precOp to guarantee that it will not go away 00260 // 00261 set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ifpack_precOp), 00262 Teuchos::POST_DESTROY, false); 00263 // 00264 // Update the factorization 00265 // 00266 { 00267 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) 00268 *out << "\nComputing the preconditioner ...\n"; 00269 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR 00270 Teuchos::TimeMonitor factorizationTimeMonitor(*factorizationTimer); 00271 #endif 00272 timer.start(true); 00273 TEUCHOS_TEST_FOR_EXCEPT(0!=ifpack_precOp->Compute()); 00274 timer.stop(); 00275 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) 00276 OSTab(out).o() <<"=> Setup time = "<<timer.totalElapsedTime()<<" sec\n"; 00277 } 00278 // 00279 // Compute the conditioner number estimate if asked 00280 // 00281 00282 // ToDo: Implement 00283 00284 // 00285 // Attach fwdOp to the ifpack_precOp 00286 // 00287 set_extra_data(fwdOpSrc, "IFPF::fwdOpSrc", Teuchos::inOutArg(ifpack_precOp), 00288 Teuchos::POST_DESTROY, false); 00289 // 00290 // Initialize the output EpetraLinearOp 00291 // 00292 if(startingOver) { 00293 epetra_precOp = rcp(new EpetraLinearOp); 00294 } 00295 epetra_precOp->initialize( 00296 ifpack_precOp 00297 ,epetraFwdOpTransp 00298 ,EPETRA_OP_APPLY_APPLY_INVERSE 00299 ,EPETRA_OP_ADJOINT_SUPPORTED 00300 ); 00301 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_MEDIUM)) { 00302 *out << "\nDescription of created preconditioner:\n"; 00303 OSTab tab2(out); 00304 ifpack_precOp->Print(*out); 00305 } 00306 00307 // 00308 // Initialize the preconditioner 00309 // 00310 defaultPrec->initializeUnspecified( 00311 Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp) 00312 ); 00313 totalTimer.stop(); 00314 if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) 00315 *out << "\nTotal time in IfpackPreconditionerFactory = "<<totalTimer.totalElapsedTime()<<" sec\n"; 00316 if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) 00317 *out << "\nLeaving Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n"; 00318 } 00319 00320 void IfpackPreconditionerFactory::uninitializePrec( 00321 PreconditionerBase<double> *prec 00322 ,Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc 00323 ,ESupportSolveUse *supportSolveUse 00324 ) const 00325 { 00326 TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement when needed! 00327 } 00328 00329 // Overridden from ParameterListAcceptor 00330 00331 void IfpackPreconditionerFactory::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList) 00332 { 00333 TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL); 00334 paramList->validateParameters(*this->getValidParameters(),2); 00335 // Note: The above validation will validate right down into the the sublist 00336 // named IfpackSettings_name! 00337 paramList_ = paramList; 00338 overlap_ = paramList_->get(Overlap_name,Overlap_default); 00339 std::ostringstream oss; 00340 oss << "(sub)list \""<<paramList->name()<<"\"parameter \"Prec Type\""; 00341 precType_ = 00342 ( paramList_.get() 00343 ? precTypeValidator->getIntegralValue(*paramList_,PrecType_name,PrecTypeName_default) 00344 : PrecType_default 00345 ); 00346 Teuchos::readVerboseObjectSublist(&*paramList_,this); 00347 #ifdef TEUCHOS_DEBUG 00348 // Validate my use of the parameters! 00349 paramList->validateParameters(*this->getValidParameters(),1); 00350 #endif 00351 } 00352 00353 Teuchos::RCP<Teuchos::ParameterList> 00354 IfpackPreconditionerFactory::getNonconstParameterList() 00355 { 00356 return paramList_; 00357 } 00358 00359 Teuchos::RCP<Teuchos::ParameterList> 00360 IfpackPreconditionerFactory::unsetParameterList() 00361 { 00362 Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_; 00363 paramList_ = Teuchos::null; 00364 return _paramList; 00365 } 00366 00367 Teuchos::RCP<const Teuchos::ParameterList> 00368 IfpackPreconditionerFactory::getParameterList() const 00369 { 00370 return paramList_; 00371 } 00372 00373 Teuchos::RCP<const Teuchos::ParameterList> 00374 IfpackPreconditionerFactory::getValidParameters() const 00375 { 00376 using Teuchos::rcp; 00377 using Teuchos::rcp_implicit_cast; 00378 typedef Teuchos::ParameterEntryValidator PEV; 00379 static Teuchos::RCP<Teuchos::ParameterList> validParamList; 00380 if(validParamList.get()==NULL) { 00381 validParamList = Teuchos::rcp(new Teuchos::ParameterList(Ifpack_name)); 00382 { 00383 // Create the validator for the preconditioner type! 00384 Teuchos::Array<std::string> 00385 precTypeNames; 00386 precTypeNames.insert( 00387 precTypeNames.begin(), 00388 &Ifpack::precTypeNames[0], 00389 &Ifpack::precTypeNames[0] + Ifpack::numPrecTypes 00390 ); 00391 Teuchos::Array<Ifpack::EPrecType> 00392 precTypeValues; 00393 precTypeValues.insert( 00394 precTypeValues.begin(), 00395 &Ifpack::precTypeValues[0], 00396 &Ifpack::precTypeValues[0] + Ifpack::numPrecTypes 00397 ); 00398 precTypeValidator = rcp( 00399 new Teuchos::StringToIntegralParameterEntryValidator<Ifpack::EPrecType>( 00400 precTypeNames,precTypeValues,PrecType_name 00401 ) 00402 ); 00403 } 00404 validParamList->set( 00405 PrecType_name, PrecTypeName_default, 00406 "Type of Ifpack preconditioner to use.", 00407 rcp_implicit_cast<const PEV>(precTypeValidator) 00408 ); 00409 validParamList->set( 00410 Overlap_name, Overlap_default, 00411 "Number of rows/columns overlapped between subdomains in different" 00412 "\nprocesses in the additive Schwarz-type domain-decomposition preconditioners." 00413 ); 00414 validParamList->sublist( 00415 IfpackSettings_name, false, 00416 "Preconditioner settings that are passed onto the Ifpack preconditioners themselves." 00417 ).setParameters(Ifpack_GetValidParameters()); 00418 // Note that in the above setParameterList(...) function that we actually 00419 // validate down into the first level of this sublist. Really the 00420 // Ifpack_Preconditioner objects themselves should do validation but we do 00421 // it ourselves taking the return from the Ifpack_GetValidParameters() 00422 // function as gospel! 00423 Teuchos::setupVerboseObjectSublist(&*validParamList); 00424 } 00425 return validParamList; 00426 } 00427 00428 // Public functions overridden from Teuchos::Describable 00429 00430 std::string IfpackPreconditionerFactory::description() const 00431 { 00432 std::ostringstream oss; 00433 oss << "Thyra::IfpackPreconditionerFactory{"; 00434 oss << "precType=\"" << ::Ifpack::toString(precType_) << "\""; 00435 oss << ",overlap=" << overlap_; 00436 oss << "}"; 00437 return oss.str(); 00438 } 00439 00440 // private 00441 00442 void IfpackPreconditionerFactory::initializeTimers() 00443 { 00444 if(!overallTimer.get()) { 00445 #ifdef STRATIMIKOS_TEUCHOS_TIME_MONITOR 00446 overallTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF"); 00447 creationTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF:Creation"); 00448 factorizationTimer = Teuchos::TimeMonitor::getNewTimer("Stratimikos: IfpackPF:Factorization"); 00449 #endif 00450 } 00451 } 00452 00453 } // namespace Thyra
1.7.6.1