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 "Ifpack_SparsityFilter.h"
00045 #include "Epetra_ConfigDefs.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
00052
00053 Ifpack_SparsityFilter::Ifpack_SparsityFilter(const Teuchos::RefCountPtr<Epetra_RowMatrix>& Matrix,
00054 int AllowedEntries,
00055 int AllowedBandwidth) :
00056 A_(Matrix),
00057 MaxNumEntries_(0),
00058 MaxNumEntriesA_(0),
00059 AllowedBandwidth_(AllowedBandwidth),
00060 AllowedEntries_(AllowedEntries),
00061 NumNonzeros_(0),
00062 NumRows_(0)
00063 {
00064
00065 if (A_->Comm().NumProc() != 1) {
00066 cerr << "Ifpack_SparsityFilter can be used with Comm().NumProc() == 1" << endl;
00067 cerr << "only. This class is a tool for Ifpack_AdditiveSchwarz," << endl;
00068 cerr << "and it is not meant to be used otherwise." << endl;
00069 exit(EXIT_FAILURE);
00070 }
00071
00072
00073 if ((A_->NumMyRows() != A_->NumMyCols()) ||
00074 (A_->NumMyRows() != A_->NumGlobalRows64()))
00075 IFPACK_CHK_ERRV(-1);
00076
00077 NumRows_ = A_->NumMyRows();
00078 MaxNumEntriesA_ = A_->MaxNumEntries();
00079 Indices_.resize(MaxNumEntriesA_);
00080 Values_.resize(MaxNumEntriesA_);
00081
00082
00083 if (AllowedBandwidth_ == -1)
00084 AllowedBandwidth_ = NumRows_;
00085
00086
00087
00088
00089 std::vector<int> Ind(MaxNumEntriesA_);
00090 std::vector<double> Val(MaxNumEntriesA_);
00091
00092 NumEntries_.resize(NumRows_);
00093 for (int i = 0 ; i < NumRows_ ; ++i)
00094 NumEntries_[i] = MaxNumEntriesA_;
00095
00096 for (int i = 0 ; i < A_->NumMyRows() ; ++i) {
00097 int Nnz;
00098 IFPACK_CHK_ERRV(ExtractMyRowCopy(i,MaxNumEntriesA_,Nnz,
00099 &Val[0], &Ind[0]));
00100
00101 NumEntries_[i] = Nnz;
00102 NumNonzeros_ += Nnz;
00103 if (Nnz > MaxNumEntries_)
00104 MaxNumEntries_ = Nnz;
00105
00106 }
00107 }
00108
00109
00110 int Ifpack_SparsityFilter::
00111 ExtractMyRowCopy(int MyRow, int Length, int & NumEntries,
00112 double *Values, int * Indices) const
00113 {
00114 if (Length < NumEntries_[MyRow])
00115 IFPACK_CHK_ERR(-1);
00116
00117 int Nnz;
00118 IFPACK_CHK_ERR(A_->ExtractMyRowCopy(MyRow,MaxNumEntriesA_,Nnz,
00119 &Values_[0],&Indices_[0]));
00120
00121 double Threshold = 0.0;
00122
00123
00124 if (Nnz > AllowedEntries_) {
00125
00126 std::vector<double> Values2(Nnz);
00127 int count = 0;
00128 for (int i = 0 ; i < Nnz ; ++i) {
00129
00130 if (Indices_[i] == MyRow)
00131 continue;
00132
00133 Values2[count] = IFPACK_ABS(Values_[i]);
00134 count++;
00135 }
00136
00137 for (int i = count ; i < Nnz ; ++i)
00138 Values2[i] = 0.0;
00139
00140
00141 std::sort(Values2.rbegin(),Values2.rend());
00142
00143 Threshold = Values2[AllowedEntries_ - 1];
00144
00145 }
00146
00147
00148
00149
00150 NumEntries = 0;
00151
00152 for (int i = 0 ; i < Nnz ; ++i) {
00153
00154 if (IFPACK_ABS(Indices_[i] - MyRow) > AllowedBandwidth_)
00155 continue;
00156
00157 if ((Indices_[i] != MyRow) && (IFPACK_ABS(Values_[i]) < Threshold))
00158 continue;
00159
00160 Values[NumEntries] = Values_[i];
00161 Indices[NumEntries] = Indices_[i];
00162
00163 NumEntries++;
00164 if (NumEntries > AllowedEntries_)
00165 break;
00166 }
00167
00168 return(0);
00169 }
00170
00171
00172 int Ifpack_SparsityFilter::
00173 ExtractDiagonalCopy(Epetra_Vector & Diagonal) const
00174 {
00175 int ierr = A_->ExtractDiagonalCopy(Diagonal);
00176 IFPACK_RETURN(ierr);
00177 }
00178
00179
00180 int Ifpack_SparsityFilter::
00181 Multiply(bool TransA, const Epetra_MultiVector& X,
00182 Epetra_MultiVector& Y) const
00183 {
00184
00185 int NumVectors = X.NumVectors();
00186 if (NumVectors != Y.NumVectors())
00187 IFPACK_CHK_ERR(-1);
00188
00189 Y.PutScalar(0.0);
00190
00191 std::vector<int> Indices(MaxNumEntries_);
00192 std::vector<double> Values(MaxNumEntries_);
00193
00194 for (int i = 0 ; i < A_->NumMyRows() ; ++i) {
00195
00196 int Nnz;
00197 ExtractMyRowCopy(i,MaxNumEntries_,Nnz,
00198 &Values[0], &Indices[0]);
00199 if (!TransA) {
00200
00201 for (int j = 0 ; j < NumVectors ; ++j) {
00202 for (int k = 0 ; k < Nnz ; ++k) {
00203 Y[j][i] += Values[k] * X[j][Indices[k]];
00204 }
00205 }
00206 }
00207 else {
00208
00209 for (int j = 0 ; j < NumVectors ; ++j) {
00210 for (int k = 0 ; k < Nnz ; ++k) {
00211 Y[j][Indices[k]] += Values[k] * X[j][i];
00212 }
00213 }
00214 }
00215 }
00216
00217 return(0);
00218 }
00219
00220
00221 int Ifpack_SparsityFilter::
00222 Solve(bool Upper, bool Trans, bool UnitDiagonal,
00223 const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00224 {
00225 IFPACK_CHK_ERR(-98);
00226 }
00227
00228
00229 int Ifpack_SparsityFilter::
00230 Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00231 {
00232 int ierr = Multiply(UseTranspose(),X,Y);
00233 IFPACK_RETURN(ierr);
00234 }
00235
00236
00237 int Ifpack_SparsityFilter::
00238 ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00239 {
00240 IFPACK_CHK_ERR(-98);
00241 }