00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "Ifpack_ConfigDefs.h"
00044 #include <iomanip>
00045 #include "Epetra_Operator.h"
00046 #include "Epetra_RowMatrix.h"
00047 #include "Epetra_Comm.h"
00048 #include "Epetra_Map.h"
00049 #include "Epetra_MultiVector.h"
00050 #include "Epetra_Vector.h"
00051 #include "Epetra_Time.h"
00052 #include "Ifpack_Krylov.h"
00053 #include "Ifpack_Utils.h"
00054 #include "Ifpack_Condest.h"
00055 #ifdef HAVE_IFPACK_AZTECOO
00056 #include "AztecOO.h"
00057 #endif
00058
00059 #ifdef HAVE_IFPACK_EPETRAEXT
00060 #include "Epetra_CrsMatrix.h"
00061 #include "EpetraExt_PointToBlockDiagPermute.h"
00062 #endif
00063
00064
00065
00066
00067 Ifpack_Krylov::
00068 Ifpack_Krylov(Epetra_Operator* Operator) :
00069 IsInitialized_(false),
00070 IsComputed_(false),
00071 NumInitialize_(0),
00072 NumCompute_(0),
00073 NumApplyInverse_(0),
00074 InitializeTime_(0.0),
00075 ComputeTime_(0.0),
00076 ApplyInverseTime_(0.0),
00077 ComputeFlops_(0.0),
00078 ApplyInverseFlops_(0.0),
00079 Iterations_(5),
00080 Tolerance_(1e-6),
00081 SolverType_(1),
00082 PreconditionerType_(1),
00083 NumSweeps_(0),
00084 BlockSize_(1),
00085 DampingParameter_(1.0),
00086 UseTranspose_(false),
00087 Condest_(-1.0),
00088 ComputeCondest_(false),
00089 Label_(),
00090 NumMyRows_(0),
00091 NumMyNonzeros_(0),
00092 NumGlobalRows_(0),
00093 NumGlobalNonzeros_(0),
00094 Operator_(Teuchos::rcp(Operator,false)),
00095 IsRowMatrix_(false),
00096 ZeroStartingSolution_(true)
00097 {
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 Ifpack_Krylov::
00110 Ifpack_Krylov(Epetra_RowMatrix* Operator) :
00111 IsInitialized_(false),
00112 IsComputed_(false),
00113 NumInitialize_(0),
00114 NumCompute_(0),
00115 NumApplyInverse_(0),
00116 InitializeTime_(0.0),
00117 ComputeTime_(0.0),
00118 ApplyInverseTime_(0.0),
00119 ComputeFlops_(0.0),
00120 ApplyInverseFlops_(0.0),
00121 Iterations_(5),
00122 Tolerance_(1e-6),
00123 SolverType_(1),
00124 PreconditionerType_(1),
00125 NumSweeps_(0),
00126 BlockSize_(1),
00127 DampingParameter_(1.0),
00128 UseTranspose_(false),
00129 Condest_(-1.0),
00130 ComputeCondest_(false),
00131 Label_(),
00132 NumMyRows_(0),
00133 NumMyNonzeros_(0),
00134 NumGlobalRows_(0),
00135 NumGlobalNonzeros_(0),
00136 Operator_(Teuchos::rcp(Operator,false)),
00137 Matrix_(Teuchos::rcp(Operator,false)),
00138 IsRowMatrix_(true),
00139 ZeroStartingSolution_(true)
00140 {
00141 }
00142
00143
00144 int Ifpack_Krylov::SetParameters(Teuchos::ParameterList& List)
00145 {
00146 Iterations_ = List.get("krylov: iterations",Iterations_);
00147 Tolerance_ = List.get("krylov: tolerance",Tolerance_);
00148 SolverType_ = List.get("krylov: solver",SolverType_);
00149 PreconditionerType_ = List.get("krylov: preconditioner",PreconditionerType_);
00150 NumSweeps_ = List.get("krylov: number of sweeps",NumSweeps_);
00151 BlockSize_ = List.get("krylov: block size",BlockSize_);
00152 DampingParameter_ = List.get("krylov: damping parameter",DampingParameter_);
00153 ZeroStartingSolution_ = List.get("krylov: zero starting solution",ZeroStartingSolution_);
00154 SetLabel();
00155 return(0);
00156 }
00157
00158
00159 const Epetra_Comm& Ifpack_Krylov::Comm() const
00160 {
00161 return(Operator_->Comm());
00162 }
00163
00164
00165 const Epetra_Map& Ifpack_Krylov::OperatorDomainMap() const
00166 {
00167 return(Operator_->OperatorDomainMap());
00168 }
00169
00170
00171 const Epetra_Map& Ifpack_Krylov::OperatorRangeMap() const
00172 {
00173 return(Operator_->OperatorRangeMap());
00174 }
00175
00176
00177 int Ifpack_Krylov::
00178 Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00179 {
00180 if (IsComputed() == false)
00181 IFPACK_CHK_ERR(-3);
00182
00183 if (X.NumVectors() != Y.NumVectors())
00184 IFPACK_CHK_ERR(-2);
00185
00186 if (IsRowMatrix_)
00187 {
00188 IFPACK_CHK_ERR(Matrix_->Multiply(UseTranspose(),X,Y));
00189 }
00190 else
00191 {
00192 IFPACK_CHK_ERR(Operator_->Apply(X,Y));
00193 }
00194
00195 return(0);
00196 }
00197
00198
00199 int Ifpack_Krylov::Initialize()
00200 {
00201 IsInitialized_ = false;
00202
00203 if (Operator_ == Teuchos::null)
00204 IFPACK_CHK_ERR(-2);
00205
00206 if (Time_ == Teuchos::null)
00207 Time_ = Teuchos::rcp( new Epetra_Time(Comm()) );
00208
00209 if (IsRowMatrix_)
00210 {
00211 if (Matrix().NumGlobalRows64() != Matrix().NumGlobalCols64())
00212 IFPACK_CHK_ERR(-2);
00213
00214 NumMyRows_ = Matrix_->NumMyRows();
00215 NumMyNonzeros_ = Matrix_->NumMyNonzeros();
00216 NumGlobalRows_ = Matrix_->NumGlobalRows64();
00217 NumGlobalNonzeros_ = Matrix_->NumGlobalNonzeros64();
00218 }
00219 else
00220 {
00221 if (Operator_->OperatorDomainMap().NumGlobalElements64() !=
00222 Operator_->OperatorRangeMap().NumGlobalElements64())
00223 IFPACK_CHK_ERR(-2);
00224 }
00225
00226 ++NumInitialize_;
00227 InitializeTime_ += Time_->ElapsedTime();
00228 IsInitialized_ = true;
00229 return(0);
00230 }
00231
00232
00233 int Ifpack_Krylov::Compute()
00234 {
00235 if (!IsInitialized())
00236 IFPACK_CHK_ERR(Initialize());
00237
00238 Time_->ResetStartTime();
00239
00240 #ifdef HAVE_IFPACK_AZTECOO
00241
00242 AztecSolver_ = Teuchos::rcp( new AztecOO );
00243 if(IsRowMatrix_==true) {
00244 AztecSolver_ -> SetUserMatrix(&*Matrix_);
00245 }
00246 else {
00247 AztecSolver_ -> SetUserOperator(&*Operator_);
00248 }
00249 if(SolverType_==0) {
00250 AztecSolver_ -> SetAztecOption(AZ_solver, AZ_cg);
00251 }
00252 else {
00253 AztecSolver_ -> SetAztecOption(AZ_solver, AZ_gmres);
00254 }
00255 AztecSolver_ -> SetAztecOption(AZ_output, AZ_none);
00256
00257 Teuchos::ParameterList List;
00258 List.set("relaxation: damping factor", DampingParameter_);
00259 List.set("relaxation: sweeps",NumSweeps_);
00260 if(PreconditionerType_==0) { }
00261 else if(PreconditionerType_==1) { List.set("relaxation: type", "Jacobi" ); }
00262 else if(PreconditionerType_==2) { List.set("relaxation: type", "Gauss-Seidel" ); }
00263 else if(PreconditionerType_==3) { List.set("relaxation: type", "symmetric Gauss-Seidel"); }
00264 if(BlockSize_==1) {
00265 IfpackPrec_ = Teuchos::rcp( new Ifpack_PointRelaxation(&*Matrix_) );
00266 }
00267 else {
00268 IfpackPrec_ = Teuchos::rcp( new Ifpack_BlockRelaxation< Ifpack_DenseContainer > (&*Matrix_) );
00269 int NumRows;
00270 if(IsRowMatrix_==true) {
00271 NumRows = Matrix_->NumMyRows();
00272 }
00273 else {
00274 long long NumRows_LL = Operator_->OperatorDomainMap().NumGlobalElements64();
00275 if(NumRows_LL > std::numeric_limits<int>::max())
00276 throw "Ifpack_Krylov::Compute: NumGlobalElements don't fit an int";
00277 else
00278 NumRows = static_cast<int>(NumRows_LL);
00279 }
00280 List.set("partitioner: type", "linear");
00281 List.set("partitioner: local parts", NumRows/BlockSize_);
00282 }
00283 if(PreconditionerType_>0) {
00284 IfpackPrec_ -> SetParameters(List);
00285 IfpackPrec_ -> Initialize();
00286 IfpackPrec_ -> Compute();
00287 AztecSolver_ -> SetPrecOperator(&*IfpackPrec_);
00288 }
00289 #else
00290 cout << "You need to configure IFPACK with support for AztecOO" << endl;
00291 cout << "to use this preconditioner. This may require --enable-aztecoo" << endl;
00292 cout << "in your configure script." << endl;
00293 IFPACK_CHK_ERR(-1);
00294 #endif
00295
00296
00297 IsComputed_ = false;
00298 Condest_ = -1.0;
00299 ++NumCompute_;
00300 ComputeTime_ += Time_->ElapsedTime();
00301 IsComputed_ = true;
00302
00303 return(0);
00304 }
00305
00306
00307 ostream& Ifpack_Krylov::Print(ostream & os) const
00308 {
00309
00310 if (!Comm().MyPID()) {
00311 os << endl;
00312 os << "================================================================================" << endl;
00313 os << "Ifpack_Krylov" << endl;
00314 os << "Number of iterations = " << Iterations_ << endl;
00315 os << "Residual Tolerance = " << Tolerance_ << endl;
00316 os << "Solver type (O for CG, 1 for GMRES) = " << SolverType_ << endl;
00317 os << "Preconditioner type = " << PreconditionerType_ << endl;
00318 os << "(0 for none, 1 for Jacobi, 2 for GS, 3 for SGS )" << endl;
00319 os << "Condition number estimate = " << Condest() << endl;
00320 os << "Global number of rows = " << Operator_->OperatorRangeMap().NumGlobalElements64() << endl;
00321 if (ZeroStartingSolution_)
00322 os << "Using zero starting solution" << endl;
00323 else
00324 os << "Using input starting solution" << endl;
00325 os << endl;
00326 os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
00327 os << "----- ------- -------------- ------------ --------" << endl;
00328 os << "Initialize() " << std::setw(5) << NumInitialize_
00329 << " " << std::setw(15) << InitializeTime_
00330 << " 0.0 0.0" << endl;
00331 os << "Compute() " << std::setw(5) << NumCompute_
00332 << " " << std::setw(15) << ComputeTime_
00333 << " " << std::setw(15) << 1.0e-6 * ComputeFlops_;
00334 if (ComputeTime_ != 0.0)
00335 os << " " << std::setw(15) << 1.0e-6 * ComputeFlops_ / ComputeTime_ << endl;
00336 else
00337 os << " " << std::setw(15) << 0.0 << endl;
00338 os << "ApplyInverse() " << std::setw(5) << NumApplyInverse_
00339 << " " << std::setw(15) << ApplyInverseTime_
00340 << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_;
00341 if (ApplyInverseTime_ != 0.0)
00342 os << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_ / ApplyInverseTime_ << endl;
00343 else
00344 os << " " << std::setw(15) << 0.0 << endl;
00345 os << "================================================================================" << endl;
00346 os << endl;
00347 }
00348
00349 return(os);
00350 }
00351
00352
00353 double Ifpack_Krylov::
00354 Condest(const Ifpack_CondestType CT,
00355 const int MaxIters, const double Tol,
00356 Epetra_RowMatrix* Matrix_in)
00357 {
00358 if (!IsComputed())
00359 return(-1.0);
00360
00361
00362
00363 Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
00364
00365 return(Condest_);
00366 }
00367
00368
00369 void Ifpack_Krylov::SetLabel()
00370 {
00371 Label_ = "IFPACK (Krylov smoother), iterations=" + Ifpack_toString(Iterations_);
00372 }
00373
00374
00375 int Ifpack_Krylov::
00376 ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00377 {
00378
00379 if (!IsComputed())
00380 IFPACK_CHK_ERR(-3);
00381
00382 if (Iterations_ == 0)
00383 return 0;
00384
00385 int nVec = X.NumVectors();
00386 if (nVec != Y.NumVectors())
00387 IFPACK_CHK_ERR(-2);
00388
00389 Time_->ResetStartTime();
00390
00391
00392
00393 Teuchos::RCP<Epetra_MultiVector> Xcopy = Teuchos::rcp( new Epetra_MultiVector(X) );
00394 if(ZeroStartingSolution_==true) {
00395 Y.PutScalar(0.0);
00396 }
00397
00398 #ifdef HAVE_IFPACK_AZTECOO
00399 AztecSolver_ -> SetLHS(&Y);
00400 AztecSolver_ -> SetRHS(&*Xcopy);
00401 AztecSolver_ -> Iterate(Iterations_,Tolerance_);
00402 #else
00403 cout << "You need to configure IFPACK with support for AztecOO" << endl;
00404 cout << "to use this preconditioner. This may require --enable-aztecoo" << endl;
00405 cout << "in your configure script." << endl;
00406 IFPACK_CHK_ERR(-1);
00407 #endif
00408
00409
00410 ++NumApplyInverse_;
00411 ApplyInverseTime_ += Time_->ElapsedTime();
00412 return(0);
00413 }