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 #include "Ifpack_ConfigDefs.h"
00031 #include "Ifpack_Preconditioner.h"
00032 #include "Ifpack_IC.h"
00033 #include "Ifpack_IC_Utils.h"
00034 #include "Ifpack_Condest.h"
00035 #include "Epetra_Comm.h"
00036 #include "Epetra_Map.h"
00037 #include "Epetra_RowMatrix.h"
00038 #include "Epetra_CrsMatrix.h"
00039 #include "Epetra_Vector.h"
00040 #include "Epetra_MultiVector.h"
00041 #include "Epetra_Util.h"
00042 #include "Teuchos_ParameterList.hpp"
00043 #include "Teuchos_RefCountPtr.hpp"
00044 using Teuchos::RefCountPtr;
00045 using Teuchos::rcp;
00046
00047
00048 Ifpack_IC::Ifpack_IC(Epetra_RowMatrix* A) :
00049 A_(rcp(A,false)),
00050 Comm_(A->Comm()),
00051 UseTranspose_(false),
00052 Condest_(-1.0),
00053 Athresh_(0.0),
00054 Rthresh_(1.0),
00055 Droptol_(0.0),
00056 Lfil_(0),
00057 Aict_(0),
00058 Lict_(0),
00059 Ldiag_(0),
00060 IsInitialized_(false),
00061 IsComputed_(false),
00062 NumInitialize_(0),
00063 NumCompute_(0),
00064 NumApplyInverse_(0),
00065 InitializeTime_(0.0),
00066 ComputeTime_(0),
00067 ApplyInverseTime_(0),
00068 ComputeFlops_(0.0),
00069 ApplyInverseFlops_(0.0)
00070 {
00071 Teuchos::ParameterList List;
00072 SetParameters(List);
00073
00074 }
00075
00076 Ifpack_IC::~Ifpack_IC()
00077 {
00078 if (Lict_ != 0) {
00079 Ifpack_AIJMatrix * Lict = (Ifpack_AIJMatrix *) Lict_;
00080 delete [] Lict->ptr;
00081 delete [] Lict->col;
00082 delete [] Lict->val;
00083 delete Lict;
00084 }
00085 if (Aict_ != 0) {
00086 Ifpack_AIJMatrix * Aict = (Ifpack_AIJMatrix *) Aict_;
00087 delete Aict;
00088 }
00089 if (Ldiag_ != 0) delete [] Ldiag_;
00090
00091 IsInitialized_ = false;
00092 IsComputed_ = false;
00093 }
00094
00095
00096 int Ifpack_IC::SetParameters(Teuchos::ParameterList& List)
00097 {
00098
00099 Lfil_ = List.get("fact: level-of-fill",Lfil_);
00100 Athresh_ = List.get("fact: absolute threshold", Athresh_);
00101 Rthresh_ = List.get("fact: relative threshold", Rthresh_);
00102 Droptol_ = List.get("fact: drop tolerance", Droptol_);
00103
00104
00105 sprintf(Label_, "IFPACK IC (fill=%d, drop=%f)",
00106 Lfil_, Droptol_);
00107 return(0);
00108 }
00109
00110
00111 int Ifpack_IC::Initialize()
00112 {
00113
00114 IsInitialized_ = false;
00115
00116
00117 IsInitialized_ = true;
00118 return(0);
00119 }
00120
00121
00122 int Ifpack_IC::ComputeSetup()
00123 {
00124
00125 U_ = rcp(new Epetra_CrsMatrix(Copy, Matrix().RowMatrixRowMap(),
00126 Matrix().RowMatrixRowMap(), 0));
00127 D_ = rcp(new Epetra_Vector(Matrix().RowMatrixRowMap()));
00128
00129 if (U_.get() == 0 || D_.get() == 0)
00130 IFPACK_CHK_ERR(-5);
00131
00132 int ierr = 0;
00133 int i, j;
00134 int NumIn, NumL, NumU;
00135 bool DiagFound;
00136 int NumNonzeroDiags = 0;
00137
00138
00139 int MaxNumEntries = Matrix().MaxNumEntries();
00140
00141 vector<int> InI(MaxNumEntries);
00142 vector<int> UI(MaxNumEntries);
00143 vector<double> InV(MaxNumEntries);
00144 vector<double> UV(MaxNumEntries);
00145
00146 double *DV;
00147 ierr = D_->ExtractView(&DV);
00148
00149
00150
00151 int NumRows = Matrix().NumMyRows();
00152
00153 for (i=0; i< NumRows; i++) {
00154
00155 Matrix().ExtractMyRowCopy(i, MaxNumEntries, NumIn, &InV[0], &InI[0]);
00156
00157
00158 NumL = 0;
00159 NumU = 0;
00160 DiagFound = false;
00161
00162 for (j=0; j< NumIn; j++) {
00163 int k = InI[j];
00164
00165 if (k==i) {
00166 DiagFound = true;
00167
00168 DV[i] += Rthresh_ * InV[j] + EPETRA_SGN(InV[j]) * Athresh_;
00169 }
00170
00171 else if (k < 0) return(-1);
00172 else if (i<k && k<NumRows) {
00173 UI[NumU] = k;
00174 UV[NumU] = InV[j];
00175 NumU++;
00176 }
00177 }
00178
00179
00180
00181 if (DiagFound) NumNonzeroDiags++;
00182 if (NumU) U_->InsertMyValues(i, NumU, &UV[0], &UI[0]);
00183
00184 }
00185
00186 U_->FillComplete(Matrix().OperatorDomainMap(),
00187 Matrix().OperatorRangeMap());
00188
00189 int ierr1 = 0;
00190 if (NumNonzeroDiags<U_->NumMyRows()) ierr1 = 1;
00191 Matrix().Comm().MaxAll(&ierr1, &ierr, 1);
00192 IFPACK_CHK_ERR(ierr);
00193
00194 return(0);
00195 }
00196
00197
00198 int Ifpack_IC::Compute() {
00199
00200 if (!IsInitialized())
00201 IFPACK_CHK_ERR(Initialize());
00202
00203 IsComputed_ = false;
00204
00205
00206 IFPACK_CHK_ERR(ComputeSetup());
00207
00208 int i;
00209
00210 int m, n, nz, Nrhs, ldrhs, ldlhs;
00211 int * ptr=0, * ind;
00212 double * val, * rhs, * lhs;
00213
00214 int ierr = Epetra_Util_ExtractHbData(U_.get(), 0, 0, m, n, nz, ptr, ind,
00215 val, Nrhs, rhs, ldrhs, lhs, ldlhs);
00216 if (ierr < 0)
00217 IFPACK_CHK_ERR(ierr);
00218
00219 Ifpack_AIJMatrix * Aict;
00220 if (Aict_==0) {
00221 Aict = new Ifpack_AIJMatrix;
00222 Aict_ = (void *) Aict;
00223 }
00224 else Aict = (Ifpack_AIJMatrix *) Aict_;
00225 Ifpack_AIJMatrix * Lict;
00226 if (Lict_==0) {
00227 Lict = new Ifpack_AIJMatrix;
00228 Lict_ = (void *) Lict;
00229 }
00230 else {
00231 Lict = (Ifpack_AIJMatrix *) Lict_;
00232 Ifpack_AIJMatrix_dealloc( Lict );
00233 }
00234 if (Ldiag_ != 0) delete [] Ldiag_;
00235 Aict->val = val;
00236 Aict->col = ind;
00237 Aict->ptr = ptr;
00238 double *DV;
00239 EPETRA_CHK_ERR(D_->ExtractView(&DV));
00240
00241 crout_ict(m, Aict, DV, Droptol_, Lfil_, Lict, &Ldiag_);
00242
00243
00244 delete [] ptr;
00245
00246
00247 U_ = rcp(new Epetra_CrsMatrix(View, A_->RowMatrixRowMap(), A_->RowMatrixRowMap(),0));
00248 D_ = rcp(new Epetra_Vector(View, A_->RowMatrixRowMap(), Ldiag_));
00249
00250 ptr = Lict->ptr;
00251 ind = Lict->col;
00252 val = Lict->val;
00253
00254 for (i=0; i< m; i++) {
00255 int NumEntries = ptr[i+1]-ptr[i];
00256 int * Indices = ind+ptr[i];
00257 double * Values = val+ptr[i];
00258 U_->InsertMyValues(i, NumEntries, Values, Indices);
00259 }
00260
00261 U_->FillComplete(A_->OperatorDomainMap(), A_->OperatorRangeMap());
00262 D_->Reciprocal(*D_);
00263
00264 #ifdef IFPACK_FLOPCOUNTERS
00265 double current_flops = 2 * nz;
00266 double total_flops = 0;
00267
00268 A_->Comm().SumAll(¤t_flops, &total_flops, 1);
00269
00270 ComputeFlops_ += total_flops;
00271
00272 ComputeFlops_ += (double) U_->NumGlobalNonzeros();
00273 ComputeFlops_ += (double) D_->GlobalLength();
00274 #endif
00275
00276 IsComputed_ = true;
00277
00278 return(0);
00279
00280 }
00281
00282
00283
00284 int Ifpack_IC::ApplyInverse(const Epetra_MultiVector& X,
00285 Epetra_MultiVector& Y) const
00286 {
00287
00288 if (!IsComputed())
00289 IFPACK_CHK_ERR(-3);
00290
00291 if (X.NumVectors() != Y.NumVectors())
00292 IFPACK_CHK_ERR(-2);
00293
00294 bool Upper = true;
00295 bool UnitDiagonal = true;
00296
00297
00298
00299 RefCountPtr< const Epetra_MultiVector > Xcopy;
00300 if (X.Pointers()[0] == Y.Pointers()[0])
00301 Xcopy = rcp( new Epetra_MultiVector(X) );
00302 else
00303 Xcopy = rcp( &X, false );
00304
00305 U_->Solve(Upper, true, UnitDiagonal, *Xcopy, Y);
00306 Y.Multiply(1.0, *D_, Y, 0.0);
00307 U_->Solve(Upper, false, UnitDiagonal, Y, Y);
00308
00309 ++NumApplyInverse_;
00310 #ifdef IFPACK_FLOPCOUNTERS
00311 ApplyInverseFlops_ += 4.0 * U_->NumGlobalNonzeros();
00312 ApplyInverseFlops_ += D_->GlobalLength();
00313 #endif
00314 return(0);
00315
00316 }
00317
00318
00319
00320 int Ifpack_IC::Apply(const Epetra_MultiVector& X,
00321 Epetra_MultiVector& Y) const
00322 {
00323
00324 if (X.NumVectors() != Y.NumVectors())
00325 IFPACK_CHK_ERR(-2);
00326
00327 Epetra_MultiVector * X1 = (Epetra_MultiVector *) &X;
00328 Epetra_MultiVector * Y1 = (Epetra_MultiVector *) &Y;
00329
00330 U_->Multiply(false, *X1, *Y1);
00331 Y1->Update(1.0, *X1, 1.0);
00332 Y1->ReciprocalMultiply(1.0, *D_, *Y1, 0.0);
00333 Epetra_MultiVector Y1temp(*Y1);
00334 U_->Multiply(true, Y1temp, *Y1);
00335 Y1->Update(1.0, Y1temp, 1.0);
00336 return(0);
00337 }
00338
00339
00340 double Ifpack_IC::Condest(const Ifpack_CondestType CT,
00341 const int MaxIters, const double Tol,
00342 Epetra_RowMatrix* Matrix_in)
00343 {
00344 if (!IsComputed())
00345 return(-1.0);
00346
00347 if (Condest_ == -1.0)
00348 Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
00349
00350 return(Condest_);
00351 }
00352
00353
00354 std::ostream&
00355 Ifpack_IC::Print(std::ostream& os) const
00356 {
00357 if (!Comm().MyPID()) {
00358 os << endl;
00359 os << "================================================================================" << endl;
00360 os << "Ifpack_IC: " << Label() << endl << endl;
00361 os << "Level-of-fill = " << LevelOfFill() << endl;
00362 os << "Absolute threshold = " << AbsoluteThreshold() << endl;
00363 os << "Relative threshold = " << RelativeThreshold() << endl;
00364 os << "Drop tolerance = " << DropTolerance() << endl;
00365 os << "Condition number estimate = " << Condest() << endl;
00366 os << "Global number of rows = " << A_->NumGlobalRows() << endl;
00367 if (IsComputed_) {
00368 os << "Number of nonzeros of H = " << U_->NumGlobalNonzeros() << endl;
00369 os << "nonzeros / rows = "
00370 << 1.0 * U_->NumGlobalNonzeros() / U_->NumGlobalRows() << endl;
00371 }
00372 os << endl;
00373 os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
00374 os << "----- ------- -------------- ------------ --------" << endl;
00375 os << "Initialize() " << std::setw(5) << NumInitialize()
00376 << " " << std::setw(15) << InitializeTime()
00377 << " 0.0 0.0" << endl;
00378 os << "Compute() " << std::setw(5) << NumCompute()
00379 << " " << std::setw(15) << ComputeTime()
00380 << " " << std::setw(15) << 1.0e-6 * ComputeFlops();
00381 if (ComputeTime() != 0.0)
00382 os << " " << std::setw(15) << 1.0e-6 * ComputeFlops() / ComputeTime() << endl;
00383 else
00384 os << " " << std::setw(15) << 0.0 << endl;
00385 os << "ApplyInverse() " << std::setw(5) << NumApplyInverse()
00386 << " " << std::setw(15) << ApplyInverseTime()
00387 << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops();
00388 if (ApplyInverseTime() != 0.0)
00389 os << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops() / ApplyInverseTime() << endl;
00390 else
00391 os << " " << std::setw(15) << 0.0 << endl;
00392 os << "================================================================================" << endl;
00393 os << endl;
00394 }
00395
00396
00397 return(os);
00398 }