IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_SparsityFilter.cpp
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2002) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
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   // use this filter only on serial matrices
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   // only square serial matrices
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   // default value is to not consider bandwidth
00083   if (AllowedBandwidth_ == -1)
00084     AllowedBandwidth_ = NumRows_;
00085   
00086   // computes the number of nonzero elements per row in the 
00087   // dropped matrix. Stores this number in NumEntries_.
00088   // Also, computes the global number of nonzeros.
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   // this `if' is to define the cut-off value
00124   if (Nnz > AllowedEntries_) {
00125  
00126     std::vector<double> Values2(Nnz);
00127     int count = 0;
00128     for (int i = 0 ; i < Nnz ; ++i) {
00129       // skip diagonal entry (which is always inserted)
00130       if (Indices_[i] == MyRow)
00131     continue;
00132       // put absolute value
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     // sort in descending order
00141     std::sort(Values2.rbegin(),Values2.rend());
00142     // get the cut-off value
00143     Threshold = Values2[AllowedEntries_ - 1];
00144 
00145   }
00146 
00147   // loop over all nonzero elements of row MyRow,
00148   // and drop elements below specified threshold.
00149   // Also, add value to zero diagonal
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       // no transpose first
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       // transpose here
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 }
 All Classes Files Functions Variables Enumerations Friends