|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 /* 00002 // @HEADER 00003 // *********************************************************************** 00004 // 00005 // Stratimikos: Thyra-based strategies for linear solvers 00006 // Copyright (2006) Sandia Corporation 00007 // 00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00009 // license for use of this work by or on behalf of the U.S. Government. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00039 // 00040 // *********************************************************************** 00041 // @HEADER 00042 */ 00043 00044 #include "Thyra_AmesosLinearOpWithSolve.hpp" 00045 #include "Thyra_EpetraThyraWrappers.hpp" 00046 #include "Thyra_MultiVectorStdOps.hpp" 00047 #include "Epetra_MultiVector.h" 00048 #include "Teuchos_TimeMonitor.hpp" 00049 00050 00051 namespace Thyra { 00052 00053 00054 // Constructors/initializers/accessors 00055 00056 00057 AmesosLinearOpWithSolve::AmesosLinearOpWithSolve(): 00058 amesosSolverTransp_(Thyra::NOTRANS), 00059 amesosSolverScalar_(1.0) 00060 {} 00061 00062 00063 AmesosLinearOpWithSolve::AmesosLinearOpWithSolve( 00064 const Teuchos::RCP<const LinearOpBase<double> > &fwdOp, 00065 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00066 const Teuchos::RCP<Epetra_LinearProblem> &epetraLP, 00067 const Teuchos::RCP<Amesos_BaseSolver> &amesosSolver, 00068 const EOpTransp amesosSolverTransp, 00069 const double amesosSolverScalar 00070 ) 00071 { 00072 this->initialize(fwdOp,fwdOpSrc,epetraLP,amesosSolver, 00073 amesosSolverTransp,amesosSolverScalar); 00074 } 00075 00076 00077 void AmesosLinearOpWithSolve::initialize( 00078 const Teuchos::RCP<const LinearOpBase<double> > &fwdOp, 00079 const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, 00080 const Teuchos::RCP<Epetra_LinearProblem> &epetraLP, 00081 const Teuchos::RCP<Amesos_BaseSolver> &amesosSolver, 00082 const EOpTransp amesosSolverTransp, 00083 const double amesosSolverScalar 00084 ) 00085 { 00086 #ifdef TEUCHOS_DEBUG 00087 TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL); 00088 TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL); 00089 TEUCHOS_TEST_FOR_EXCEPT(epetraLP.get()==NULL); 00090 TEUCHOS_TEST_FOR_EXCEPT(amesosSolver.get()==NULL); 00091 TEUCHOS_TEST_FOR_EXCEPT(epetraLP->GetLHS()!=NULL); 00092 TEUCHOS_TEST_FOR_EXCEPT(epetraLP->GetRHS()!=NULL); 00093 #endif 00094 fwdOp_ = fwdOp; 00095 fwdOpSrc_ = fwdOpSrc; 00096 epetraLP_ = epetraLP; 00097 amesosSolver_ = amesosSolver; 00098 amesosSolverTransp_ = amesosSolverTransp; 00099 amesosSolverScalar_ = amesosSolverScalar; 00100 const std::string fwdOpLabel = fwdOp_->getObjectLabel(); 00101 if(fwdOpLabel.length()) 00102 this->setObjectLabel( "lows("+fwdOpLabel+")" ); 00103 } 00104 00105 00106 Teuchos::RCP<const LinearOpSourceBase<double> > 00107 AmesosLinearOpWithSolve::extract_fwdOpSrc() 00108 { 00109 Teuchos::RCP<const LinearOpSourceBase<double> > 00110 _fwdOpSrc = fwdOpSrc_; 00111 fwdOpSrc_ = Teuchos::null; 00112 return _fwdOpSrc; 00113 } 00114 00115 00116 void AmesosLinearOpWithSolve::uninitialize( 00117 Teuchos::RCP<const LinearOpBase<double> > *fwdOp, 00118 Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc, 00119 Teuchos::RCP<Epetra_LinearProblem> *epetraLP, 00120 Teuchos::RCP<Amesos_BaseSolver> *amesosSolver, 00121 EOpTransp *amesosSolverTransp, 00122 double *amesosSolverScalar 00123 ) 00124 { 00125 00126 if(fwdOp) *fwdOp = fwdOp_; 00127 if(fwdOpSrc) *fwdOpSrc = fwdOpSrc_; 00128 if(epetraLP) *epetraLP = epetraLP_; 00129 if(amesosSolver) *amesosSolver = amesosSolver_; 00130 if(amesosSolverTransp) *amesosSolverTransp = amesosSolverTransp_; 00131 if(amesosSolverScalar) *amesosSolverScalar = amesosSolverScalar_; 00132 00133 fwdOp_ = Teuchos::null; 00134 fwdOpSrc_ = Teuchos::null; 00135 epetraLP_ = Teuchos::null; 00136 amesosSolver_ = Teuchos::null; 00137 amesosSolverTransp_ = NOTRANS; 00138 amesosSolverScalar_ = 0.0; 00139 00140 } 00141 00142 00143 // Overridden from LinearOpBase 00144 00145 00146 Teuchos::RCP< const VectorSpaceBase<double> > 00147 AmesosLinearOpWithSolve::range() const 00148 { 00149 return ( fwdOp_.get() ? fwdOp_->range() : Teuchos::null ); 00150 } 00151 00152 00153 Teuchos::RCP< const VectorSpaceBase<double> > 00154 AmesosLinearOpWithSolve::domain() const 00155 { 00156 return ( fwdOp_.get() ? fwdOp_->domain() : Teuchos::null ); 00157 } 00158 00159 00160 Teuchos::RCP<const LinearOpBase<double> > 00161 AmesosLinearOpWithSolve::clone() const 00162 { 00163 return Teuchos::null; // Not supported yet but could be 00164 } 00165 00166 00167 // Overridden from Teuchos::Describable 00168 00169 00170 std::string AmesosLinearOpWithSolve::description() const 00171 { 00172 std::ostringstream oss; 00173 oss << Teuchos::Describable::description(); 00174 if(!is_null(amesosSolver_)) { 00175 oss 00176 << "{fwdOp="<<fwdOp_->description() 00177 << ",amesosSolver="<<typeName(*amesosSolver_)<<"}"; 00178 } 00179 return oss.str(); 00180 } 00181 00182 00183 void AmesosLinearOpWithSolve::describe( 00184 Teuchos::FancyOStream &out, 00185 const Teuchos::EVerbosityLevel verbLevel 00186 ) const 00187 { 00188 using Teuchos::OSTab; 00189 using Teuchos::typeName; 00190 using Teuchos::describe; 00191 switch(verbLevel) { 00192 case Teuchos::VERB_DEFAULT: 00193 case Teuchos::VERB_LOW: 00194 out << this->description() << std::endl; 00195 break; 00196 case Teuchos::VERB_MEDIUM: 00197 case Teuchos::VERB_HIGH: 00198 case Teuchos::VERB_EXTREME: 00199 { 00200 out 00201 << Teuchos::Describable::description() << "{" 00202 << "rangeDim=" << this->range()->dim() 00203 << ",domainDim="<< this->domain()->dim() << "}\n"; 00204 OSTab tab(out); 00205 if(!is_null(fwdOp_)) { 00206 out << "fwdOp = " << describe(*fwdOp_,verbLevel); 00207 } 00208 if(!is_null(amesosSolver_)) { 00209 out << "amesosSolver=" << typeName(*amesosSolver_) << "\n"; 00210 } 00211 break; 00212 } 00213 default: 00214 TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here! 00215 } 00216 } 00217 00218 00219 // protected 00220 00221 00222 // Overridden from LinearOpBase 00223 00224 00225 bool AmesosLinearOpWithSolve::opSupportedImpl(EOpTransp M_trans) const 00226 { 00227 return ::Thyra::opSupported(*fwdOp_,M_trans); 00228 } 00229 00230 00231 void AmesosLinearOpWithSolve::applyImpl( 00232 const EOpTransp M_trans, 00233 const MultiVectorBase<double> &X, 00234 const Ptr<MultiVectorBase<double> > &Y, 00235 const double alpha, 00236 const double beta 00237 ) const 00238 { 00239 Thyra::apply( *fwdOp_, M_trans, X, Y, alpha, beta ); 00240 } 00241 00242 00243 // Overridden from LinearOpWithSolveBase 00244 00245 00246 bool AmesosLinearOpWithSolve::solveSupportsImpl(EOpTransp M_trans) const 00247 { 00248 if (Thyra::real_trans(M_trans) == Thyra::NOTRANS) { 00249 // Assume every amesos solver supports a basic forward solve! 00250 return true; 00251 } 00252 // Query the amesos solver to see if it supports the transpose operation. 00253 // NOTE: Amesos_BaseSolver makes you change the state of the object to 00254 // determine if the object supports an adjoint solver. This is a bad design 00255 // but I have no control over that. This is why you see this hacked 00256 // oldUseTranspose variable and logic. NOTE: This function meets the basic 00257 // guarantee but if setUseTransplse(...) throws, then the state of 00258 // UseTranspose() may be different. 00259 const bool oldUseTranspose = amesosSolver_->UseTranspose(); 00260 const bool supportsAdjoint = (amesosSolver_->SetUseTranspose(true) == 0); 00261 amesosSolver_->SetUseTranspose(oldUseTranspose); 00262 return supportsAdjoint; 00263 } 00264 00265 00266 bool AmesosLinearOpWithSolve::solveSupportsSolveMeasureTypeImpl( 00267 EOpTransp M_trans, const SolveMeasureType& solveMeasureType 00268 ) const 00269 { 00270 return true; // I am a direct solver so I should be able to do it all! 00271 } 00272 00273 00274 SolveStatus<double> 00275 AmesosLinearOpWithSolve::solveImpl( 00276 const EOpTransp M_trans, 00277 const MultiVectorBase<double> &B, 00278 const Ptr<MultiVectorBase<double> > &X, 00279 const Ptr<const SolveCriteria<double> > solveCriteria 00280 ) const 00281 { 00282 using Teuchos::rcpFromPtr; 00283 using Teuchos::rcpFromRef; 00284 using Teuchos::OSTab; 00285 00286 Teuchos::Time totalTimer(""); 00287 totalTimer.start(true); 00288 00289 THYRA_FUNC_TIME_MONITOR("Stratimikos: AmesosLOWS"); 00290 00291 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream(); 00292 Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); 00293 OSTab tab = this->getOSTab(); 00294 if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE)) 00295 *out << "\nSolving block system using Amesos solver " 00296 << typeName(*amesosSolver_) << " ...\n\n"; 00297 00298 // 00299 // Get the op(...) range and domain maps 00300 // 00301 const EOpTransp amesosOpTransp = real_trans(trans_trans(amesosSolverTransp_,M_trans)); 00302 const Epetra_Operator *amesosOp = epetraLP_->GetOperator(); 00303 const Epetra_Map 00304 &opRangeMap = ( amesosOpTransp == NOTRANS 00305 ? amesosOp->OperatorRangeMap() : amesosOp->OperatorDomainMap() ), 00306 &opDomainMap = ( amesosOpTransp == NOTRANS 00307 ? amesosOp->OperatorDomainMap() : amesosOp->OperatorRangeMap() ); 00308 00309 // 00310 // Get Epetra_MultiVector views of B and X 00311 // 00312 Teuchos::RCP<const Epetra_MultiVector> 00313 epetra_B = get_Epetra_MultiVector(opRangeMap, rcpFromRef(B)); 00314 Teuchos::RCP<Epetra_MultiVector> 00315 epetra_X = get_Epetra_MultiVector(opDomainMap, rcpFromPtr(X)); 00316 00317 // 00318 // Set B and X in the linear problem 00319 // 00320 epetraLP_->SetLHS(&*epetra_X); 00321 epetraLP_->SetRHS(const_cast<Epetra_MultiVector*>(&*epetra_B)); 00322 // Above should be okay but cross your fingers! 00323 00324 // 00325 // Solve the linear system 00326 // 00327 const bool oldUseTranspose = amesosSolver_->UseTranspose(); 00328 amesosSolver_->SetUseTranspose(amesosOpTransp==TRANS); 00329 const int err = amesosSolver_->Solve(); 00330 TEUCHOS_TEST_FOR_EXCEPTION( 0!=err, CatastrophicSolveFailure, 00331 "Error, the function Solve() on the amesos solver of type\n" 00332 "\'"<<typeName(*amesosSolver_)<<"\' failed with error code "<<err<<"!" 00333 ); 00334 amesosSolver_->SetUseTranspose(oldUseTranspose); 00335 00336 // 00337 // Unset B and X 00338 // 00339 epetraLP_->SetLHS(NULL); 00340 epetraLP_->SetRHS(NULL); 00341 epetra_X = Teuchos::null; 00342 epetra_B = Teuchos::null; 00343 00344 // 00345 // Scale X if needed 00346 // 00347 if(amesosSolverScalar_!=1.0) 00348 Thyra::scale(1.0/amesosSolverScalar_, X); 00349 00350 // 00351 // Set the solve status if requested 00352 // 00353 SolveStatus<double> solveStatus; 00354 solveStatus.solveStatus = SOLVE_STATUS_CONVERGED; 00355 solveStatus.achievedTol = SolveStatus<double>::unknownTolerance(); 00356 solveStatus.message = 00357 std::string("Solver ")+typeName(*amesosSolver_)+std::string(" converged!"); 00358 00359 // 00360 // Report the overall time 00361 // 00362 if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW)) 00363 *out 00364 << "\nTotal solve time = "<<totalTimer.totalElapsedTime()<<" sec\n"; 00365 00366 return solveStatus; 00367 00368 } 00369 00370 00371 } // end namespace Thyra
1.7.6.1