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 #include "Ifpack_ConfigDefs.h"
00030 #include "Ifpack_CondestType.h"
00031 #include "Ifpack_ILU.h"
00032 #include "Epetra_ConfigDefs.h"
00033 #include "Epetra_Comm.h"
00034 #include "Epetra_Map.h"
00035 #include "Epetra_RowMatrix.h"
00036 #include "Epetra_Vector.h"
00037 #include "Epetra_MultiVector.h"
00038 #include "Epetra_CrsGraph.h"
00039 #include "Epetra_CrsMatrix.h"
00040 #include "Teuchos_ParameterList.hpp"
00041 #include "Teuchos_RefCountPtr.hpp"
00042
00043 using Teuchos::RefCountPtr;
00044 using Teuchos::rcp;
00045
00046 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00047 # include "Teuchos_TimeMonitor.hpp"
00048 #endif
00049
00050
00051 Ifpack_ILU::Ifpack_ILU(Epetra_RowMatrix* Matrix_in) :
00052 A_(rcp(Matrix_in,false)),
00053 Comm_(Matrix_in->Comm()),
00054 UseTranspose_(false),
00055 NumMyDiagonals_(0),
00056 RelaxValue_(0.0),
00057 Athresh_(0.0),
00058 Rthresh_(1.0),
00059 Condest_(-1.0),
00060 LevelOfFill_(0),
00061 IsInitialized_(false),
00062 IsComputed_(false),
00063 NumInitialize_(0),
00064 NumCompute_(0),
00065 NumApplyInverse_(0),
00066 InitializeTime_(0.0),
00067 ComputeTime_(0.0),
00068 ApplyInverseTime_(0.0),
00069 ComputeFlops_(0.0),
00070 ApplyInverseFlops_(0.0),
00071 Time_(Comm())
00072 {
00073 Teuchos::ParameterList List;
00074 SetParameters(List);
00075 }
00076
00077
00078 void Ifpack_ILU::Destroy()
00079 {
00080
00081 U_DomainMap_ = 0;
00082 L_RangeMap_ = 0;
00083 }
00084
00085
00086 int Ifpack_ILU::SetParameters(Teuchos::ParameterList& List)
00087 {
00088 RelaxValue_ = List.get("fact: relax value", RelaxValue_);
00089 Athresh_ = List.get("fact: absolute threshold", Athresh_);
00090 Rthresh_ = List.get("fact: relative threshold", Rthresh_);
00091 LevelOfFill_ = List.get("fact: level-of-fill", LevelOfFill_);
00092
00093
00094 sprintf(Label_, "IFPACK ILU (fill=%d, relax=%f, athr=%f, rthr=%f)",
00095 LevelOfFill(), RelaxValue(), AbsoluteThreshold(),
00096 RelativeThreshold());
00097 return(0);
00098 }
00099
00100
00101 int Ifpack_ILU::ComputeSetup()
00102 {
00103
00104 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00105 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::ComputeSetup");
00106 #endif
00107
00108 L_ = rcp(new Epetra_CrsMatrix(Copy, Graph().L_Graph()));
00109 U_ = rcp(new Epetra_CrsMatrix(Copy, Graph().U_Graph()));
00110 D_ = rcp(new Epetra_Vector(Graph().L_Graph().RowMap()));
00111 if ((L_.get() == 0) || (U_.get() == 0) || (D_.get() == 0))
00112 IFPACK_CHK_ERR(-5);
00113
00114
00115 int MaxNumEntries = Matrix().MaxNumEntries();
00116
00117
00118 U_DomainMap_ = &(Matrix().OperatorDomainMap());
00119 L_RangeMap_ = &(Matrix().OperatorRangeMap());
00120
00121
00122 int ierr = 0;
00123 int i, j;
00124 int NumIn, NumL, NumU;
00125 bool DiagFound;
00126 int NumNonzeroDiags = 0;
00127
00128 vector<int> InI(MaxNumEntries);
00129 vector<int> LI(MaxNumEntries);
00130 vector<int> UI(MaxNumEntries);
00131 vector<double> InV(MaxNumEntries);
00132 vector<double> LV(MaxNumEntries);
00133 vector<double> UV(MaxNumEntries);
00134
00135 bool ReplaceValues = (L_->StaticGraph() || L_->IndicesAreLocal());
00136
00137 if (ReplaceValues) {
00138 L_->PutScalar(0.0);
00139 U_->PutScalar(0.0);
00140 }
00141
00142 D_->PutScalar(0.0);
00143 double *DV;
00144 IFPACK_CHK_ERR(D_->ExtractView(&DV));
00145
00146
00147
00148 for (i=0; i< NumMyRows(); i++) {
00149
00150 IFPACK_CHK_ERR(Matrix().ExtractMyRowCopy(i, MaxNumEntries, NumIn, &InV[0], &InI[0]));
00151
00152
00153
00154 NumL = 0;
00155 NumU = 0;
00156 DiagFound = false;
00157
00158 for (j=0; j< NumIn; j++) {
00159 int k = InI[j];
00160
00161 if (k==i) {
00162 DiagFound = true;
00163 DV[i] += Rthresh_ * InV[j] + EPETRA_SGN(InV[j]) * Athresh_;
00164 }
00165
00166 else if (k < 0) {IFPACK_CHK_ERR(-4);}
00167
00168 else if (k < i) {
00169 LI[NumL] = k;
00170 LV[NumL] = InV[j];
00171 NumL++;
00172 }
00173 else if (k<NumMyRows()) {
00174 UI[NumU] = k;
00175 UV[NumU] = InV[j];
00176 NumU++;
00177 }
00178 }
00179
00180
00181
00182 if (DiagFound) NumNonzeroDiags++;
00183 else DV[i] = Athresh_;
00184
00185 if (NumL) {
00186 if (ReplaceValues) {
00187 (L_->ReplaceMyValues(i, NumL, &LV[0], &LI[0]));
00188 }
00189 else {
00190 IFPACK_CHK_ERR(L_->InsertMyValues(i, NumL, &LV[0], &LI[0]));
00191 }
00192 }
00193
00194 if (NumU) {
00195 if (ReplaceValues) {
00196 (U_->ReplaceMyValues(i, NumU, &UV[0], &UI[0]));
00197 }
00198 else {
00199 IFPACK_CHK_ERR(U_->InsertMyValues(i, NumU, &UV[0], &UI[0]));
00200 }
00201 }
00202
00203 }
00204
00205 if (!ReplaceValues) {
00206
00207
00208
00209
00210 IFPACK_CHK_ERR(L_->FillComplete((L_->RowMatrixColMap()), *L_RangeMap_));
00211 IFPACK_CHK_ERR(U_->FillComplete(*U_DomainMap_, U_->RowMatrixRowMap()));
00212 }
00213
00214
00215 int TotalNonzeroDiags = 0;
00216 IFPACK_CHK_ERR(Graph().L_Graph().RowMap().Comm().SumAll(&NumNonzeroDiags, &TotalNonzeroDiags, 1));
00217 NumMyDiagonals_ = NumNonzeroDiags;
00218 if (NumNonzeroDiags != NumMyRows()) ierr = 1;
00219
00220 IFPACK_CHK_ERR(ierr);
00221 return(ierr);
00222 }
00223
00224
00225 int Ifpack_ILU::Initialize()
00226 {
00227
00228 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00229 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::Initialize");
00230 #endif
00231
00232 Time_.ResetStartTime();
00233 IsInitialized_ = false;
00234
00235
00236 Destroy();
00237
00238 Epetra_CrsMatrix* CrsMatrix;
00239 CrsMatrix = dynamic_cast<Epetra_CrsMatrix*>(&*A_);
00240 if (CrsMatrix == 0) {
00241
00242
00243
00244
00245 int size = A_->MaxNumEntries();
00246 CrsGraph_ = rcp(new Epetra_CrsGraph(Copy,A_->RowMatrixRowMap(), size));
00247 if (CrsGraph_.get() == 0)
00248 IFPACK_CHK_ERR(-5);
00249
00250 vector<int> Indices(size);
00251 vector<double> Values(size);
00252
00253
00254
00255 for (int i = 0 ; i < A_->NumMyRows() ; ++i) {
00256 int NumEntries;
00257 int GlobalRow = A_->RowMatrixRowMap().GID(i);
00258 IFPACK_CHK_ERR(A_->ExtractMyRowCopy(i, size, NumEntries,
00259 &Values[0], &Indices[0]));
00260
00261 for (int j = 0 ; j < NumEntries ; ++j) {
00262 Indices[j] = A_->RowMatrixColMap().GID(Indices[j]);
00263 }
00264 IFPACK_CHK_ERR(CrsGraph_->InsertGlobalIndices(GlobalRow,NumEntries,
00265 &Indices[0]));
00266 }
00267
00268 IFPACK_CHK_ERR(CrsGraph_->FillComplete(A_->RowMatrixRowMap(),
00269 A_->RowMatrixRowMap()));
00270
00271
00272
00273 Graph_ = rcp(new Ifpack_IlukGraph(*CrsGraph_, LevelOfFill_, 0));
00274
00275 }
00276 else {
00277
00278 Graph_ = rcp(new Ifpack_IlukGraph(CrsMatrix->Graph(), LevelOfFill_, 0));
00279 }
00280
00281 if (Graph_.get() == 0)
00282 IFPACK_CHK_ERR(-5);
00283 IFPACK_CHK_ERR(Graph_->ConstructFilledGraph());
00284
00285 IsInitialized_ = true;
00286 NumInitialize_++;
00287 InitializeTime_ += Time_.ElapsedTime();
00288
00289 return(0);
00290 }
00291
00292
00293 int Ifpack_ILU::Compute()
00294 {
00295
00296 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00297 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::Compute");
00298 #endif
00299
00300 if (!IsInitialized())
00301 IFPACK_CHK_ERR(Initialize());
00302
00303 Time_.ResetStartTime();
00304 IsComputed_ = false;
00305
00306
00307 IFPACK_CHK_ERR(ComputeSetup());
00308
00309
00310
00311
00312 double MinDiagonalValue = Epetra_MinDouble;
00313 double MaxDiagonalValue = 1.0/MinDiagonalValue;
00314
00315 int ierr = 0;
00316 int i, j, k;
00317 int *LI, *UI;
00318 double *LV, *UV;
00319 int NumIn, NumL, NumU;
00320
00321
00322 int MaxNumEntries = L_->MaxNumEntries() + U_->MaxNumEntries() + 1;
00323
00324 vector<int> InI(MaxNumEntries+1);
00325 vector<double> InV(MaxNumEntries+1);
00326 vector<int> colflag(NumMyCols());
00327
00328 double *DV;
00329 ierr = D_->ExtractView(&DV);
00330
00331 #ifdef IFPACK_FLOPCOUNTERS
00332 int current_madds = 0;
00333 #endif
00334
00335
00336
00337
00338
00339
00340 int NumUU;
00341 int * UUI;
00342 double * UUV;
00343 for (j = 0; j < NumMyCols(); ++j) colflag[j] = - 1;
00344
00345 for (i = 0; i < NumMyRows(); ++i) {
00346
00347
00348
00349 NumIn = MaxNumEntries;
00350 IFPACK_CHK_ERR(L_->ExtractMyRowCopy(i, NumIn, NumL, &InV[0], &InI[0]));
00351 LV = &InV[0];
00352 LI = &InI[0];
00353
00354 InV[NumL] = DV[i];
00355 InI[NumL] = i;
00356
00357 IFPACK_CHK_ERR(U_->ExtractMyRowCopy(i, NumIn-NumL-1, NumU, &InV[NumL+1], &InI[NumL+1]));
00358 NumIn = NumL+NumU+1;
00359 UV = &InV[NumL+1];
00360 UI = &InI[NumL+1];
00361
00362
00363 for (j=0; j<NumIn; j++) colflag[InI[j]] = j;
00364
00365 double diagmod = 0.0;
00366
00367 for (int jj=0; jj<NumL; jj++) {
00368 j = InI[jj];
00369 double multiplier = InV[jj];
00370
00371 InV[jj] *= DV[j];
00372
00373 IFPACK_CHK_ERR(U_->ExtractMyRowView(j, NumUU, UUV, UUI));
00374
00375 if (RelaxValue_==0.0) {
00376 for (k=0; k<NumUU; k++) {
00377 int kk = colflag[UUI[k]];
00378 if (kk>-1) {
00379 InV[kk] -= multiplier*UUV[k];
00380 #ifdef IFPACK_FLOPCOUNTERS
00381 current_madds++;
00382 #endif
00383 }
00384 }
00385 }
00386 else {
00387 for (k=0; k<NumUU; k++) {
00388 int kk = colflag[UUI[k]];
00389 if (kk>-1) InV[kk] -= multiplier*UUV[k];
00390 else diagmod -= multiplier*UUV[k];
00391 #ifdef IFPACK_FLOPCOUNTERS
00392 current_madds++;
00393 #endif
00394 }
00395 }
00396 }
00397 if (NumL) {
00398 IFPACK_CHK_ERR(L_->ReplaceMyValues(i, NumL, LV, LI));
00399 }
00400
00401 DV[i] = InV[NumL];
00402
00403 if (RelaxValue_!=0.0) {
00404 DV[i] += RelaxValue_*diagmod;
00405
00406 }
00407
00408 if (fabs(DV[i]) > MaxDiagonalValue) {
00409 if (DV[i] < 0) DV[i] = - MinDiagonalValue;
00410 else DV[i] = MinDiagonalValue;
00411 }
00412 else
00413 DV[i] = 1.0/DV[i];
00414
00415 for (j=0; j<NumU; j++) UV[j] *= DV[i];
00416
00417 if (NumU) {
00418 IFPACK_CHK_ERR(U_->ReplaceMyValues(i, NumU, UV, UI));
00419 }
00420
00421
00422 for (j=0; j<NumIn; j++) colflag[InI[j]] = -1;
00423 }
00424
00425
00426
00427 if (!L_->LowerTriangular())
00428 IFPACK_CHK_ERR(-4);
00429 if (!U_->UpperTriangular())
00430 IFPACK_CHK_ERR(-4);
00431
00432 #ifdef IFPACK_FLOPCOUNTERS
00433
00434
00435 double current_flops = 2 * current_madds;
00436 double total_flops = 0;
00437
00438 IFPACK_CHK_ERR(Graph().L_Graph().RowMap().Comm().SumAll(¤t_flops, &total_flops, 1));
00439
00440
00441 total_flops += (double) L_->NumGlobalNonzeros();
00442 total_flops += (double) D_->GlobalLength();
00443 if (RelaxValue_!=0.0) total_flops += 2 * (double)D_->GlobalLength();
00444
00445
00446 ComputeFlops_ += total_flops;
00447 #endif
00448
00449 IsComputed_ = true;
00450 NumCompute_++;
00451 ComputeTime_ += Time_.ElapsedTime();
00452
00453 return(ierr);
00454
00455 }
00456
00457
00458
00459 int Ifpack_ILU::Solve(bool Trans, const Epetra_MultiVector& X,
00460 Epetra_MultiVector& Y) const
00461 {
00462
00463 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00464 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::ApplyInverse - Solve");
00465 #endif
00466
00467
00468 bool Upper = true;
00469 bool Lower = false;
00470 bool UnitDiagonal = true;
00471
00472 if (!Trans) {
00473
00474 IFPACK_CHK_ERR(L_->Solve(Lower, Trans, UnitDiagonal, X, Y));
00475
00476 IFPACK_CHK_ERR(Y.Multiply(1.0, *D_, Y, 0.0));
00477
00478 IFPACK_CHK_ERR(U_->Solve(Upper, Trans, UnitDiagonal, Y, Y));
00479 }
00480 else {
00481
00482 IFPACK_CHK_ERR(U_->Solve(Upper, Trans, UnitDiagonal, X, Y));
00483
00484 IFPACK_CHK_ERR(Y.Multiply(1.0, *D_, Y, 0.0));
00485 IFPACK_CHK_ERR(L_->Solve(Lower, Trans, UnitDiagonal, Y, Y));
00486 }
00487
00488
00489 return(0);
00490 }
00491
00492
00493
00494 int Ifpack_ILU::Multiply(bool Trans, const Epetra_MultiVector& X,
00495 Epetra_MultiVector& Y) const
00496 {
00497
00498 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00499 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::Multiply");
00500 #endif
00501
00502 if (!IsComputed())
00503 IFPACK_CHK_ERR(-3);
00504
00505 if (!Trans) {
00506 IFPACK_CHK_ERR(U_->Multiply(Trans, X, Y));
00507
00508 IFPACK_CHK_ERR(Y.Update(1.0, X, 1.0));
00509
00510 IFPACK_CHK_ERR(Y.ReciprocalMultiply(1.0, *D_, Y, 0.0));
00511 Epetra_MultiVector Y1temp(Y);
00512 IFPACK_CHK_ERR(L_->Multiply(Trans, Y1temp, Y));
00513
00514 IFPACK_CHK_ERR(Y.Update(1.0, Y1temp, 1.0));
00515 }
00516 else {
00517
00518 IFPACK_CHK_ERR(L_->Multiply(Trans, X, Y));
00519
00520 IFPACK_CHK_ERR(Y.Update(1.0, X, 1.0));
00521
00522 IFPACK_CHK_ERR(Y.ReciprocalMultiply(1.0, *D_, Y, 0.0));
00523 Epetra_MultiVector Y1temp(Y);
00524 IFPACK_CHK_ERR(U_->Multiply(Trans, Y1temp, Y));
00525
00526 IFPACK_CHK_ERR(Y.Update(1.0, Y1temp, 1.0));
00527 }
00528
00529 return(0);
00530 }
00531
00532
00533
00534 int Ifpack_ILU::ApplyInverse(const Epetra_MultiVector& X,
00535 Epetra_MultiVector& Y) const
00536 {
00537
00538 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00539 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::ApplyInverse");
00540 #endif
00541
00542 if (!IsComputed())
00543 IFPACK_CHK_ERR(-3);
00544
00545 if (X.NumVectors() != Y.NumVectors())
00546 IFPACK_CHK_ERR(-2);
00547
00548 Time_.ResetStartTime();
00549
00550
00551
00552 Teuchos::RefCountPtr< const Epetra_MultiVector > Xcopy;
00553 if (X.Pointers()[0] == Y.Pointers()[0])
00554 Xcopy = Teuchos::rcp( new Epetra_MultiVector(X) );
00555 else
00556 Xcopy = Teuchos::rcp( &X, false );
00557
00558 IFPACK_CHK_ERR(Solve(Ifpack_ILU::UseTranspose(), *Xcopy, Y));
00559
00560
00561 #ifdef IFPACK_FLOPCOUNTERS
00562 ApplyInverseFlops_ += X.NumVectors() * 4 *
00563 (L_->NumGlobalNonzeros() + U_->NumGlobalNonzeros());
00564 #endif
00565
00566 ++NumApplyInverse_;
00567 ApplyInverseTime_ += Time_.ElapsedTime();
00568
00569 return(0);
00570
00571 }
00572
00573
00574 double Ifpack_ILU::Condest(const Ifpack_CondestType CT,
00575 const int MaxIters, const double Tol,
00576 Epetra_RowMatrix* Matrix_in)
00577 {
00578
00579 #ifdef IFPACK_TEUCHOS_TIME_MONITOR
00580 TEUCHOS_FUNC_TIME_MONITOR("Ifpack_ILU::Condest");
00581 #endif
00582
00583 if (!IsComputed())
00584 return(-1.0);
00585
00586 Condest_ = Ifpack_Condest(*this, CT, MaxIters, Tol, Matrix_in);
00587
00588 return(Condest_);
00589 }
00590
00591
00592 std::ostream&
00593 Ifpack_ILU::Print(std::ostream& os) const
00594 {
00595 if (!Comm().MyPID()) {
00596 os << endl;
00597 os << "================================================================================" << endl;
00598 os << "Ifpack_ILU: " << Label() << endl << endl;
00599 os << "Level-of-fill = " << LevelOfFill() << endl;
00600 os << "Absolute threshold = " << AbsoluteThreshold() << endl;
00601 os << "Relative threshold = " << RelativeThreshold() << endl;
00602 os << "Relax value = " << RelaxValue() << endl;
00603 os << "Condition number estimate = " << Condest() << endl;
00604 os << "Global number of rows = " << A_->NumGlobalRows() << endl;
00605 if (IsComputed_) {
00606 os << "Number of rows of L, D, U = " << L_->NumGlobalRows() << endl;
00607 os << "Number of nonzeros of L + U = " << NumGlobalNonzeros() << endl;
00608 os << "nonzeros / rows = "
00609 << 1.0 * NumGlobalNonzeros() / U_->NumGlobalRows() << endl;
00610 }
00611 os << endl;
00612 os << "Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
00613 os << "----- ------- -------------- ------------ --------" << endl;
00614 os << "Initialize() " << std::setw(5) << NumInitialize()
00615 << " " << std::setw(15) << InitializeTime()
00616 << " 0.0 0.0" << endl;
00617 os << "Compute() " << std::setw(5) << NumCompute()
00618 << " " << std::setw(15) << ComputeTime()
00619 << " " << std::setw(15) << 1.0e-6 * ComputeFlops();
00620 if (ComputeTime() != 0.0)
00621 os << " " << std::setw(15) << 1.0e-6 * ComputeFlops() / ComputeTime() << endl;
00622 else
00623 os << " " << std::setw(15) << 0.0 << endl;
00624 os << "ApplyInverse() " << std::setw(5) << NumApplyInverse()
00625 << " " << std::setw(15) << ApplyInverseTime()
00626 << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops();
00627 if (ApplyInverseTime() != 0.0)
00628 os << " " << std::setw(15) << 1.0e-6 * ApplyInverseFlops() / ApplyInverseTime() << endl;
00629 else
00630 os << " " << std::setw(15) << 0.0 << endl;
00631 os << "================================================================================" << endl;
00632 os << endl;
00633 }
00634
00635 return(os);
00636 }