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_Polynomial.h"
00053 #include "Ifpack_Utils.h"
00054 #include "Ifpack_Condest.h"
00055 #include "Teuchos_LAPACK.hpp"
00056 #include "Teuchos_SerialDenseMatrix.hpp"
00057 #include <complex>
00058 #ifdef HAVE_IFPACK_AZTECOO
00059 #include "Ifpack_DiagPreconditioner.h"
00060 #include "AztecOO.h"
00061 #endif
00062
00063 #ifdef HAVE_IFPACK_EPETRAEXT
00064 #include "Epetra_CrsMatrix.h"
00065 #include "EpetraExt_PointToBlockDiagPermute.h"
00066 #endif
00067
00068
00069 #define ABS(x) ((x)>0?(x):-(x))
00070
00071
00072 inline void Apply_Transpose(Teuchos::RCP<const Epetra_Operator> Operator_,const Epetra_MultiVector &X,Epetra_MultiVector &Y){
00073 Epetra_Operator * Operator=const_cast<Epetra_Operator*>(&*Operator_);
00074 Operator->SetUseTranspose(true);
00075 Operator->Apply(X,Y);
00076 Operator->SetUseTranspose(false);
00077 }
00078
00079
00080
00081
00082
00083
00084
00085 Ifpack_Polynomial::
00086 Ifpack_Polynomial(const Epetra_Operator* Operator) :
00087 IsInitialized_(false),
00088 IsComputed_(false),
00089 IsIndefinite_(false),
00090 IsComplex_(false),
00091 NumInitialize_(0),
00092 NumCompute_(0),
00093 NumApplyInverse_(0),
00094 InitializeTime_(0.0),
00095 ComputeTime_(0.0),
00096 ApplyInverseTime_(0.0),
00097 ComputeFlops_(0.0),
00098 ApplyInverseFlops_(0.0),
00099 PolyDegree_(3),
00100 LSPointsReal_(10),
00101 LSPointsImag_(10),
00102 UseTranspose_(false),
00103 Condest_(-1.0),
00104 ComputeCondest_(false),
00105 RealEigRatio_(10.0),
00106 ImagEigRatio_(10.0),
00107 Label_(),
00108 LambdaRealMin_(0.0),
00109 LambdaRealMax_(-1.0),
00110 LambdaImagMin_(0.0),
00111 LambdaImagMax_(0.0),
00112 MinDiagonalValue_(0.0),
00113 NumMyRows_(0),
00114 NumMyNonzeros_(0),
00115 NumGlobalRows_(0),
00116 NumGlobalNonzeros_(0),
00117 Operator_(Teuchos::rcp(Operator,false)),
00118 UseBlockMode_(false),
00119 SolveNormalEquations_(false),
00120 IsRowMatrix_(false),
00121 ZeroStartingSolution_(true)
00122 {
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 Ifpack_Polynomial::
00135 Ifpack_Polynomial(const Epetra_RowMatrix* Operator) :
00136 IsInitialized_(false),
00137 IsComputed_(false),
00138 IsIndefinite_(false),
00139 IsComplex_(false),
00140 NumInitialize_(0),
00141 NumCompute_(0),
00142 NumApplyInverse_(0),
00143 InitializeTime_(0.0),
00144 ComputeTime_(0.0),
00145 ApplyInverseTime_(0.0),
00146 ComputeFlops_(0.0),
00147 ApplyInverseFlops_(0.0),
00148 PolyDegree_(3),
00149 LSPointsReal_(10),
00150 LSPointsImag_(10),
00151 UseTranspose_(false),
00152 Condest_(-1.0),
00153 ComputeCondest_(false),
00154 RealEigRatio_(10.0),
00155 ImagEigRatio_(10.0),
00156 EigMaxIters_(10),
00157 Label_(),
00158 LambdaRealMin_(0.0),
00159 LambdaRealMax_(-1.0),
00160 LambdaImagMin_(0.0),
00161 LambdaImagMax_(0.0),
00162 MinDiagonalValue_(0.0),
00163 NumMyRows_(0),
00164 NumMyNonzeros_(0),
00165 NumGlobalRows_(0),
00166 NumGlobalNonzeros_(0),
00167 Operator_(Teuchos::rcp(Operator,false)),
00168 Matrix_(Teuchos::rcp(Operator,false)),
00169 UseBlockMode_(false),
00170 SolveNormalEquations_(false),
00171 IsRowMatrix_(true),
00172 ZeroStartingSolution_(true)
00173 {
00174 }
00175
00176
00177 int Ifpack_Polynomial::SetParameters(Teuchos::ParameterList& List)
00178 {
00179
00180 RealEigRatio_ = List.get("polynomial: real eigenvalue ratio", RealEigRatio_);
00181 ImagEigRatio_ = List.get("polynomial: imag eigenvalue ratio", ImagEigRatio_);
00182 LambdaRealMin_ = List.get("polynomial: min real part", LambdaRealMin_);
00183 LambdaRealMax_ = List.get("polynomial: max real part", LambdaRealMax_);
00184 LambdaImagMin_ = List.get("polynomial: min imag part", LambdaImagMin_);
00185 LambdaImagMax_ = List.get("polynomial: max imag part", LambdaImagMax_);
00186 PolyDegree_ = List.get("polynomial: degree",PolyDegree_);
00187 LSPointsReal_ = List.get("polynomial: real interp points",LSPointsReal_);
00188 LSPointsImag_ = List.get("polynomial: imag interp points",LSPointsImag_);
00189 IsIndefinite_ = List.get("polynomial: indefinite",IsIndefinite_);
00190 IsComplex_ = List.get("polynomial: complex",IsComplex_);
00191 MinDiagonalValue_ = List.get("polynomial: min diagonal value",
00192 MinDiagonalValue_);
00193 ZeroStartingSolution_ = List.get("polynomial: zero starting solution",
00194 ZeroStartingSolution_);
00195
00196 Epetra_Vector* ID = List.get("polynomial: operator inv diagonal",
00197 (Epetra_Vector*)0);
00198 EigMaxIters_ = List.get("polynomial: eigenvalue max iterations",EigMaxIters_);
00199
00200 #ifdef HAVE_IFPACK_EPETRAEXT
00201
00202 UseBlockMode_ = List.get("polynomial: use block mode",UseBlockMode_);
00203 if(!List.isParameter("polynomial: block list")) UseBlockMode_=false;
00204 else{
00205 BlockList_ = List.get("polynomial: block list",BlockList_);
00206
00207
00208
00209 Teuchos::ParameterList Blist;
00210 Blist=BlockList_.get("blockdiagmatrix: list",Blist);
00211 string dummy("invert");
00212 string ApplyMode=Blist.get("apply mode",dummy);
00213 if(ApplyMode==string("multiply")){
00214 Blist.set("apply mode","invert");
00215 BlockList_.set("blockdiagmatrix: list",Blist);
00216 }
00217 }
00218 #endif
00219
00220 SolveNormalEquations_ = List.get("polynomial: solve normal equations",SolveNormalEquations_);
00221
00222 if (ID != 0)
00223 {
00224 InvDiagonal_ = Teuchos::rcp( new Epetra_Vector(*ID) );
00225 }
00226
00227 SetLabel();
00228
00229 return(0);
00230 }
00231
00232
00233 const Epetra_Comm& Ifpack_Polynomial::Comm() const
00234 {
00235 return(Operator_->Comm());
00236 }
00237
00238
00239 const Epetra_Map& Ifpack_Polynomial::OperatorDomainMap() const
00240 {
00241 return(Operator_->OperatorDomainMap());
00242 }
00243
00244
00245 const Epetra_Map& Ifpack_Polynomial::OperatorRangeMap() const
00246 {
00247 return(Operator_->OperatorRangeMap());
00248 }
00249
00250
00251 int Ifpack_Polynomial::
00252 Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00253 {
00254 if (IsComputed() == false)
00255 IFPACK_CHK_ERR(-3);
00256
00257 if (X.NumVectors() != Y.NumVectors())
00258 IFPACK_CHK_ERR(-2);
00259
00260 if (IsRowMatrix_)
00261 {
00262 IFPACK_CHK_ERR(Matrix_->Multiply(UseTranspose(),X,Y));
00263 }
00264 else
00265 {
00266 IFPACK_CHK_ERR(Operator_->Apply(X,Y));
00267 }
00268
00269 return(0);
00270 }
00271
00272
00273 int Ifpack_Polynomial::Initialize()
00274 {
00275 IsInitialized_ = false;
00276
00277 if (Operator_ == Teuchos::null)
00278 IFPACK_CHK_ERR(-2);
00279
00280 if (Time_ == Teuchos::null)
00281 Time_ = Teuchos::rcp( new Epetra_Time(Comm()) );
00282
00283 if (IsRowMatrix_)
00284 {
00285 if (Matrix().NumGlobalRows64() != Matrix().NumGlobalCols64())
00286 IFPACK_CHK_ERR(-2);
00287
00288 NumMyRows_ = Matrix_->NumMyRows();
00289 NumMyNonzeros_ = Matrix_->NumMyNonzeros();
00290 NumGlobalRows_ = Matrix_->NumGlobalRows64();
00291 NumGlobalNonzeros_ = Matrix_->NumGlobalNonzeros64();
00292 }
00293 else
00294 {
00295 if (Operator_->OperatorDomainMap().NumGlobalElements64() !=
00296 Operator_->OperatorRangeMap().NumGlobalElements64())
00297 IFPACK_CHK_ERR(-2);
00298 }
00299
00300 ++NumInitialize_;
00301 InitializeTime_ += Time_->ElapsedTime();
00302 IsInitialized_ = true;
00303 return(0);
00304 }
00305
00306
00307 int Ifpack_Polynomial::Compute()
00308 {
00309 if (!IsInitialized())
00310 IFPACK_CHK_ERR(Initialize());
00311
00312 Time_->ResetStartTime();
00313
00314
00315 IsComputed_ = false;
00316 Condest_ = -1.0;
00317
00318 if (PolyDegree_ <= 0)
00319 IFPACK_CHK_ERR(-2);
00320
00321 #ifdef HAVE_IFPACK_EPETRAEXT
00322
00323 if(IsRowMatrix_ && InvDiagonal_ == Teuchos::null && UseBlockMode_){
00324 const Epetra_CrsMatrix *CrsMatrix=dynamic_cast<const Epetra_CrsMatrix*>(&*Matrix_);
00325
00326
00327 if(!CrsMatrix) UseBlockMode_=false;
00328 else{
00329 int ierr;
00330 InvBlockDiagonal_=Teuchos::rcp(new EpetraExt_PointToBlockDiagPermute(*CrsMatrix));
00331 if(InvBlockDiagonal_==Teuchos::null) IFPACK_CHK_ERR(-6);
00332
00333 ierr=InvBlockDiagonal_->SetParameters(BlockList_);
00334 if(ierr) IFPACK_CHK_ERR(-7);
00335
00336 ierr=InvBlockDiagonal_->Compute();
00337 if(ierr) IFPACK_CHK_ERR(-8);
00338 }
00339 }
00340 #endif
00341 if (IsRowMatrix_ && InvDiagonal_ == Teuchos::null && !UseBlockMode_)
00342 {
00343 InvDiagonal_ = Teuchos::rcp( new Epetra_Vector(Matrix().Map()) );
00344
00345 if (InvDiagonal_ == Teuchos::null)
00346 IFPACK_CHK_ERR(-5);
00347
00348 IFPACK_CHK_ERR(Matrix().ExtractDiagonalCopy(*InvDiagonal_));
00349
00350
00351
00352 for (int i = 0 ; i < NumMyRows_ ; ++i) {
00353 double diag = (*InvDiagonal_)[i];
00354 if (IFPACK_ABS(diag) < MinDiagonalValue_)
00355 (*InvDiagonal_)[i] = MinDiagonalValue_;
00356 else
00357 (*InvDiagonal_)[i] = 1.0 / diag;
00358 }
00359 }
00360
00361
00362 double lambda_real_min, lambda_real_max, lambda_imag_min, lambda_imag_max;
00363 if (LambdaRealMax_ == -1) {
00364
00365 GMRES(Matrix(), *InvDiagonal_, EigMaxIters_, lambda_real_min, lambda_real_max, lambda_imag_min, lambda_imag_max);
00366 LambdaRealMin_=lambda_real_min; LambdaImagMin_=lambda_imag_min;
00367 LambdaRealMax_=lambda_real_max; LambdaImagMax_=lambda_imag_max;
00368
00369
00370
00371
00372 }
00373
00374
00375
00376
00377
00378 std::complex<double> zero(0.0,0.0);
00379 std::complex<double> one(1.0,0.0);
00380
00381
00382 double lenx = LambdaRealMax_-LambdaRealMin_;
00383 int nx = ceil(lenx*((double) LSPointsReal_));
00384 if (nx<2) { nx = 2; }
00385 double hx = lenx/((double) nx);
00386 std::vector<double> xs;
00387 if(abs(lenx)>1.0e-8) {
00388 for( int pt=0; pt<=nx; pt++ ) {
00389 xs.push_back(hx*pt+LambdaRealMin_);
00390 }
00391 }
00392 else {
00393 xs.push_back(LambdaRealMax_);
00394 nx=1;
00395 }
00396 double leny = LambdaImagMax_-LambdaImagMin_;
00397 int ny = ceil(leny*((double) LSPointsImag_));
00398 if (ny<2) { ny = 2; }
00399 double hy = leny/((double) ny);
00400 std::vector<double> ys;
00401 if(abs(leny)>1.0e-8) {
00402 for( int pt=0; pt<=ny; pt++ ) {
00403 ys.push_back(hy*pt+LambdaImagMin_);
00404 }
00405 }
00406 else {
00407 ys.push_back(LambdaImagMax_);
00408 ny=1;
00409 }
00410 std::vector< std::complex<double> > cpts;
00411 for( int jj=0; jj<ny; jj++ ) {
00412 for( int ii=0; ii<nx; ii++ ) {
00413 std::complex<double> cpt(xs[ii],ys[jj]);
00414 cpts.push_back(cpt);
00415 }
00416 }
00417 cpts.push_back(zero);
00418
00419 #ifdef HAVE_TEUCHOS_COMPLEX
00420
00421
00422 Teuchos::SerialDenseMatrix<int, std::complex<double> > Vmatrix(cpts.size(),PolyDegree_+1);
00423 Vmatrix.putScalar(zero);
00424 for (int jj = 0; jj <= PolyDegree_; ++jj) {
00425 for (int ii = 0; ii < static_cast<int> (cpts.size ()) - 1; ++ii) {
00426 if (jj > 0) {
00427 Vmatrix(ii,jj) = pow(cpts[ii],jj);
00428 }
00429 else {
00430 Vmatrix(ii,jj) = one;
00431 }
00432 }
00433 }
00434 Vmatrix(cpts.size()-1,0)=one;
00435
00436
00437 Teuchos::SerialDenseMatrix< int,std::complex<double> > RHS(cpts.size(),1);
00438 RHS.putScalar(zero);
00439 RHS(cpts.size()-1,0)=one;
00440
00441
00442 Teuchos::LAPACK< int, std::complex<double> > lapack;
00443 const int N = Vmatrix.numCols();
00444 Teuchos::Array<double> singularValues(N);
00445 Teuchos::Array<double> rwork(1);
00446 rwork.resize (std::max (1, 5 * N));
00447 std::complex<double> lworkScalar(1.0,0.0);
00448 int info = 0;
00449 lapack.GELS('N', Vmatrix.numRows(), Vmatrix.numCols(), RHS.numCols(),
00450 Vmatrix.values(), Vmatrix.numRows(), RHS.values(), RHS.numRows(),
00451 &lworkScalar, -1, &info);
00452 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
00453 "_GELSS workspace query returned INFO = "
00454 << info << " != 0.");
00455 const int lwork = static_cast<int> (real(lworkScalar));
00456 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
00457 "_GELSS workspace query returned LWORK = "
00458 << lwork << " < 0.");
00459
00460 Teuchos::Array< std::complex<double> > work (std::max (1, lwork));
00461
00462 lapack.GELS('N', Vmatrix.numRows(), Vmatrix.numCols(), RHS.numCols(),
00463 Vmatrix.values(), Vmatrix.numRows(), RHS.values(), RHS.numRows(),
00464 &work[0], lwork, &info);
00465
00466 coeff_.resize(PolyDegree_+1);
00467 std::complex<double> c0=RHS(0,0);
00468 for(int ii=0; ii<=PolyDegree_; ii++) {
00469
00470
00471
00472
00473 coeff_[ii]=real(RHS(ii,0)/c0);
00474
00475 }
00476
00477 #else
00478
00479
00480 Teuchos::SerialDenseMatrix< int, double > Vmatrix(xs.size()+1,PolyDegree_+1);
00481 Vmatrix.putScalar(0.0);
00482 for( int jj=0; jj<=PolyDegree_; jj++) {
00483 for( int ii=0; ii<xs.size(); ii++) {
00484 if(jj>0) {
00485 Vmatrix(ii,jj)=pow(xs[ii],jj);
00486 }
00487 else {
00488 Vmatrix(ii,jj)=1.0;
00489 }
00490 }
00491 }
00492 Vmatrix(xs.size(),0)=1.0;
00493
00494
00495 Teuchos::SerialDenseMatrix< int, double > RHS(xs.size()+1,1);
00496 RHS.putScalar(0.0);
00497 RHS(xs.size(),0)=1.0;
00498
00499
00500 Teuchos::LAPACK< int, double > lapack;
00501 const int N = Vmatrix.numCols();
00502 Teuchos::Array<double> singularValues(N);
00503 Teuchos::Array<double> rwork(1);
00504 rwork.resize (std::max (1, 5 * N));
00505 double lworkScalar(1.0);
00506 int info = 0;
00507 lapack.GELS('N', Vmatrix.numRows(), Vmatrix.numCols(), RHS.numCols(),
00508 Vmatrix.values(), Vmatrix.numRows(), RHS.values(), RHS.numRows(),
00509 &lworkScalar, -1, &info);
00510 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
00511 "_GELSS workspace query returned INFO = "
00512 << info << " != 0.");
00513 const int lwork = static_cast<int> (lworkScalar);
00514 TEUCHOS_TEST_FOR_EXCEPTION(lwork < 0, std::logic_error,
00515 "_GELSS workspace query returned LWORK = "
00516 << lwork << " < 0.");
00517
00518 Teuchos::Array< double > work (std::max (1, lwork));
00519
00520 lapack.GELS('N', Vmatrix.numRows(), Vmatrix.numCols(), RHS.numCols(),
00521 Vmatrix.values(), Vmatrix.numRows(), RHS.values(), RHS.numRows(),
00522 &work[0], lwork, &info);
00523
00524 coeff_.resize(PolyDegree_+1);
00525 double c0=RHS(0,0);
00526 for(int ii=0; ii<=PolyDegree_; ii++) {
00527
00528
00529
00530
00531 coeff_[ii]=RHS(ii,0)/c0;
00532 }
00533
00534 #endif
00535
00536 #ifdef IFPACK_FLOPCOUNTERS
00537 ComputeFlops_ += NumMyRows_;
00538 #endif
00539
00540 ++NumCompute_;
00541 ComputeTime_ += Time_->ElapsedTime();
00542 IsComputed_ = true;
00543
00544 return(0);
00545 }
00546
00547
00548 ostream& Ifpack_Polynomial::Print(ostream & os) const
00549 {
00550
00551 double MyMinVal, MyMaxVal;
00552 double MinVal, MaxVal;
00553
00554 if (IsComputed_) {
00555 InvDiagonal_->MinValue(&MyMinVal);
00556 InvDiagonal_->MaxValue(&MyMaxVal);
00557 Comm().MinAll(&MyMinVal,&MinVal,1);
00558 Comm().MinAll(&MyMaxVal,&MaxVal,1);
00559 }
00560
00561 if (!Comm().MyPID()) {
00562 os << endl;
00563 os << "================================================================================" << endl;
00564 os << "Ifpack_Polynomial" << endl;
00565 os << "Degree of polynomial = " << PolyDegree_ << endl;
00566 os << "Condition number estimate = " << Condest() << endl;
00567 os << "Global number of rows = " << Operator_->OperatorRangeMap().NumGlobalElements64() << endl;
00568 if (IsComputed_) {
00569 os << "Minimum value on stored inverse diagonal = " << MinVal << endl;
00570 os << "Maximum value on stored inverse diagonal = " << MaxVal << endl;
00571 }
00572 if (ZeroStartingSolution_)
00573 os << "Using zero starting solution" << endl;
00574 else
00575 os << "Using input starting solution" << endl;
00576 os << endl;
00577 os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
00578 os << "----- ------- -------------- ------------ --------" << endl;
00579 os << "Initialize() " << std::setw(5) << NumInitialize_
00580 << " " << std::setw(15) << InitializeTime_
00581 << " 0.0 0.0" << endl;
00582 os << "Compute() " << std::setw(5) << NumCompute_
00583 << " " << std::setw(15) << ComputeTime_
00584 << " " << std::setw(15) << 1.0e-6 * ComputeFlops_;
00585 if (ComputeTime_ != 0.0)
00586 os << " " << std::setw(15) << 1.0e-6 * ComputeFlops_ / ComputeTime_ << endl;
00587 else
00588 os << " " << std::setw(15) << 0.0 << endl;
00589 os << "ApplyInverse() " << std::setw(5) << NumApplyInverse_
00590 << " " << std::setw(15) << ApplyInverseTime_
00591 << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_;
00592 if (ApplyInverseTime_ != 0.0)
00593 os << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops_ / ApplyInverseTime_ << endl;
00594 else
00595 os << " " << std::setw(15) << 0.0 << endl;
00596 os << "================================================================================" << endl;
00597 os << endl;
00598 }
00599
00600 return(os);
00601 }
00602
00603
00604 double Ifpack_Polynomial::
00605 Condest(const Ifpack_CondestType CT,
00606 const int MaxIters, const double Tol,
00607 Epetra_RowMatrix* Matrix_in)
00608 {
00609 if (!IsComputed())
00610 return(-1.0);
00611
00612
00613
00614 Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
00615
00616 return(Condest_);
00617 }
00618
00619
00620 void Ifpack_Polynomial::SetLabel()
00621 {
00622 Label_ = "IFPACK (Least squares polynomial), degree=" + Ifpack_toString(PolyDegree_);
00623 }
00624
00625
00626 int Ifpack_Polynomial::
00627 ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00628 {
00629
00630 if (!IsComputed())
00631 IFPACK_CHK_ERR(-3);
00632
00633 if (PolyDegree_ == 0)
00634 return 0;
00635
00636 int nVec = X.NumVectors();
00637 if (nVec != Y.NumVectors())
00638 IFPACK_CHK_ERR(-2);
00639
00640 Time_->ResetStartTime();
00641
00642 Epetra_MultiVector Xcopy(X);
00643 if(ZeroStartingSolution_==true) {
00644 Y.PutScalar(0.0);
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654 Y.Update(-coeff_[1], Xcopy, 1.0);
00655 for (int ii = 2; ii < static_cast<int> (coeff_.size ()); ++ii) {
00656 const Epetra_MultiVector V(Xcopy);
00657 Operator_->Apply(V,Xcopy);
00658 Xcopy.Multiply(1.0, *InvDiagonal_, Xcopy, 0.0);
00659
00660 Y.Update(-coeff_[ii], Xcopy, 1.0);
00661 }
00662
00663
00664 ++NumApplyInverse_;
00665 ApplyInverseTime_ += Time_->ElapsedTime();
00666 return(0);
00667 }
00668
00669
00670 int Ifpack_Polynomial::
00671 PowerMethod(const Epetra_Operator& Operator,
00672 const Epetra_Vector& InvPointDiagonal,
00673 const int MaximumIterations,
00674 double& lambda_max)
00675 {
00676
00677 lambda_max = 0.0;
00678 double RQ_top, RQ_bottom, norm;
00679 Epetra_Vector x(Operator.OperatorDomainMap());
00680 Epetra_Vector y(Operator.OperatorRangeMap());
00681 x.Random();
00682 x.Norm2(&norm);
00683 if (norm == 0.0) IFPACK_CHK_ERR(-1);
00684
00685 x.Scale(1.0 / norm);
00686
00687 for (int iter = 0; iter < MaximumIterations; ++iter)
00688 {
00689 Operator.Apply(x, y);
00690 IFPACK_CHK_ERR(y.Multiply(1.0, InvPointDiagonal, y, 0.0));
00691 IFPACK_CHK_ERR(y.Dot(x, &RQ_top));
00692 IFPACK_CHK_ERR(x.Dot(x, &RQ_bottom));
00693 lambda_max = RQ_top / RQ_bottom;
00694 IFPACK_CHK_ERR(y.Norm2(&norm));
00695 if (norm == 0.0) IFPACK_CHK_ERR(-1);
00696 IFPACK_CHK_ERR(x.Update(1.0 / norm, y, 0.0));
00697 }
00698
00699 return(0);
00700 }
00701
00702
00703 int Ifpack_Polynomial::
00704 CG(const Epetra_Operator& Operator,
00705 const Epetra_Vector& InvPointDiagonal,
00706 const int MaximumIterations,
00707 double& lambda_min, double& lambda_max)
00708 {
00709 #ifdef HAVE_IFPACK_AZTECOO
00710 Epetra_Vector x(Operator.OperatorDomainMap());
00711 Epetra_Vector y(Operator.OperatorRangeMap());
00712 x.Random();
00713 y.PutScalar(0.0);
00714
00715 Epetra_LinearProblem LP(const_cast<Epetra_Operator*>(&Operator), &x, &y);
00716 AztecOO solver(LP);
00717 solver.SetAztecOption(AZ_solver, AZ_cg_condnum);
00718 solver.SetAztecOption(AZ_output, AZ_none);
00719
00720 Ifpack_DiagPreconditioner diag(Operator.OperatorDomainMap(),
00721 Operator.OperatorRangeMap(),
00722 InvPointDiagonal);
00723 solver.SetPrecOperator(&diag);
00724 solver.Iterate(MaximumIterations, 1e-10);
00725
00726 const double* status = solver.GetAztecStatus();
00727
00728 lambda_min = status[AZ_lambda_min];
00729 lambda_max = status[AZ_lambda_max];
00730
00731 return(0);
00732 #else
00733 cout << "You need to configure IFPACK with support for AztecOO" << endl;
00734 cout << "to use the CG estimator. This may require --enable-aztecoo" << endl;
00735 cout << "in your configure script." << endl;
00736 IFPACK_CHK_ERR(-1);
00737 #endif
00738 }
00739
00740
00741 #ifdef HAVE_IFPACK_EPETRAEXT
00742 int Ifpack_Polynomial::
00743 PowerMethod(const int MaximumIterations, double& lambda_max)
00744 {
00745
00746 if(!UseBlockMode_) IFPACK_CHK_ERR(-1);
00747
00748 lambda_max = 0.0;
00749 double RQ_top, RQ_bottom, norm;
00750 Epetra_Vector x(Operator_->OperatorDomainMap());
00751 Epetra_Vector y(Operator_->OperatorRangeMap());
00752 Epetra_Vector z(Operator_->OperatorRangeMap());
00753 x.Random();
00754 x.Norm2(&norm);
00755 if (norm == 0.0) IFPACK_CHK_ERR(-1);
00756
00757 x.Scale(1.0 / norm);
00758
00759 for (int iter = 0; iter < MaximumIterations; ++iter)
00760 {
00761 Operator_->Apply(x, z);
00762 InvBlockDiagonal_->ApplyInverse(z,y);
00763 if(SolveNormalEquations_){
00764 InvBlockDiagonal_->ApplyInverse(y,z);
00765 Apply_Transpose(Operator_,z, y);
00766 }
00767
00768 IFPACK_CHK_ERR(y.Dot(x, &RQ_top));
00769 IFPACK_CHK_ERR(x.Dot(x, &RQ_bottom));
00770 lambda_max = RQ_top / RQ_bottom;
00771 IFPACK_CHK_ERR(y.Norm2(&norm));
00772 if (norm == 0.0) IFPACK_CHK_ERR(-1);
00773 IFPACK_CHK_ERR(x.Update(1.0 / norm, y, 0.0));
00774 }
00775
00776 return(0);
00777 }
00778 #endif
00779
00780
00781 #ifdef HAVE_IFPACK_EPETRAEXT
00782 int Ifpack_Polynomial::
00783 CG(const int MaximumIterations,
00784 double& lambda_min, double& lambda_max)
00785 {
00786 IFPACK_CHK_ERR(-1);
00787
00788
00789 if(!UseBlockMode_) IFPACK_CHK_ERR(-1);
00790
00791 #ifdef HAVE_IFPACK_AZTECOO
00792 Epetra_Vector x(Operator_->OperatorDomainMap());
00793 Epetra_Vector y(Operator_->OperatorRangeMap());
00794 x.Random();
00795 y.PutScalar(0.0);
00796 Epetra_LinearProblem LP(const_cast<Epetra_RowMatrix*>(&*Matrix_), &x, &y);
00797
00798 AztecOO solver(LP);
00799 solver.SetAztecOption(AZ_solver, AZ_cg_condnum);
00800 solver.SetAztecOption(AZ_output, AZ_none);
00801
00802 solver.SetPrecOperator(&*InvBlockDiagonal_);
00803 solver.Iterate(MaximumIterations, 1e-10);
00804
00805 const double* status = solver.GetAztecStatus();
00806
00807 lambda_min = status[AZ_lambda_min];
00808 lambda_max = status[AZ_lambda_max];
00809
00810 return(0);
00811 #else
00812 cout << "You need to configure IFPACK with support for AztecOO" << endl;
00813 cout << "to use the CG estimator. This may require --enable-aztecoo" << endl;
00814 cout << "in your configure script." << endl;
00815 IFPACK_CHK_ERR(-1);
00816 #endif
00817 }
00818 #endif
00819
00820
00821 int Ifpack_Polynomial::
00822 GMRES(const Epetra_Operator& Operator,
00823 const Epetra_Vector& InvPointDiagonal,
00824 const int MaximumIterations,
00825 double& lambda_real_min, double& lambda_real_max,
00826 double& lambda_imag_min, double& lambda_imag_max)
00827 {
00828 #ifdef HAVE_IFPACK_AZTECOO
00829 Epetra_Vector x(Operator_->OperatorDomainMap());
00830 Epetra_Vector y(Operator_->OperatorRangeMap());
00831 x.Random();
00832 y.PutScalar(0.0);
00833 Epetra_LinearProblem LP(const_cast<Epetra_RowMatrix*>(&*Matrix_), &x, &y);
00834 AztecOO solver(LP);
00835 solver.SetAztecOption(AZ_solver, AZ_gmres_condnum);
00836 solver.SetAztecOption(AZ_output, AZ_none);
00837 Ifpack_DiagPreconditioner diag(Operator.OperatorDomainMap(),
00838 Operator.OperatorRangeMap(),
00839 InvPointDiagonal);
00840 solver.SetPrecOperator(&diag);
00841 solver.Iterate(MaximumIterations, 1e-10);
00842 const double* status = solver.GetAztecStatus();
00843 lambda_real_min = status[AZ_lambda_real_min];
00844 lambda_real_max = status[AZ_lambda_real_max];
00845 lambda_imag_min = status[AZ_lambda_imag_min];
00846 lambda_imag_max = status[AZ_lambda_imag_max];
00847 return(0);
00848 #else
00849 cout << "You need to configure IFPACK with support for AztecOO" << endl;
00850 cout << "to use the GMRES estimator. This may require --enable-aztecoo" << endl;
00851 cout << "in your configure script." << endl;
00852 IFPACK_CHK_ERR(-1);
00853 #endif
00854 }