IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_LocalFilter.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 
00045 #include "Epetra_MultiVector.h"
00046 #include "Epetra_Vector.h"
00047 #include "Epetra_RowMatrix.h"
00048 #include "Epetra_Map.h"
00049 #include "Epetra_BlockMap.h"
00050 #include "Ifpack_LocalFilter.h"
00051 
00052 //==============================================================================
00053 Ifpack_LocalFilter::Ifpack_LocalFilter(const Teuchos::RefCountPtr<const Epetra_RowMatrix>& Matrix) :
00054   Matrix_(Matrix),
00055   NumRows_(0),
00056   NumNonzeros_(0),
00057   MaxNumEntries_(0),
00058   MaxNumEntriesA_(0)
00059 {
00060   sprintf(Label_,"%s","Ifpack_LocalFilter");
00061 
00062 #ifdef HAVE_MPI
00063   SerialComm_ = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_SELF) );
00064 #else
00065   SerialComm_ = Teuchos::rcp( new Epetra_SerialComm );
00066 #endif
00067 
00068   // localized matrix has all the local rows of Matrix
00069   NumRows_ = Matrix->NumMyRows();
00070 
00071 #if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
00072   // build a linear map, based on the serial communicator
00073   Map_ = Teuchos::rcp( new Epetra_Map(NumRows_,0,*SerialComm_) );
00074 #endif
00075 
00076   // NumEntries_ will contain the actual number of nonzeros
00077   // for each localized row (that is, without external nodes,
00078   // and always with the diagonal entry)
00079   NumEntries_.resize(NumRows_);
00080 
00081   // want to store the diagonal vector. FIXME: am I really useful?
00082   Diagonal_ = Teuchos::rcp( new Epetra_Vector(*Map_) );
00083   if (Diagonal_ == Teuchos::null) IFPACK_CHK_ERRV(-5);
00084   
00085   // store this for future access to ExtractMyRowCopy().
00086   // This is the # of nonzeros in the non-local matrix
00087   MaxNumEntriesA_ = Matrix->MaxNumEntries();
00088   // tentative value for MaxNumEntries. This is the number of
00089   // nonzeros in the local matrix
00090   MaxNumEntries_ = Matrix->MaxNumEntries();
00091 
00092   // ExtractMyRowCopy() will use these vectors
00093   Indices_.resize(MaxNumEntries_);
00094   Values_.resize(MaxNumEntries_);
00095 
00096   // now compute:
00097   // - the number of nonzero per row
00098   // - the total number of nonzeros
00099   // - the diagonal entries
00100 
00101   // compute nonzeros (total and per-row), and store the
00102   // diagonal entries (already modified)
00103   int ActualMaxNumEntries = 0;
00104 
00105   for (int i = 0 ; i < NumRows_ ; ++i) {
00106     
00107     NumEntries_[i] = 0;
00108     int Nnz, NewNnz = 0;
00109     IFPACK_CHK_ERRV(ExtractMyRowCopy(i,MaxNumEntries_,Nnz,&Values_[0],&Indices_[0]));
00110 
00111     for (int j = 0 ; j < Nnz ; ++j) {
00112       if (Indices_[j] < NumRows_ ) ++NewNnz;
00113 
00114       if (Indices_[j] == i)
00115     (*Diagonal_)[i] = Values_[j];
00116     }
00117 
00118     if (NewNnz > ActualMaxNumEntries)
00119       ActualMaxNumEntries = NewNnz;
00120 
00121     NumNonzeros_ += NewNnz;
00122     NumEntries_[i] = NewNnz;
00123 
00124   }
00125  
00126   MaxNumEntries_ = ActualMaxNumEntries;
00127 }
00128 
00129 //==============================================================================
00130 int Ifpack_LocalFilter::
00131 ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, 
00132          double *Values, int * Indices) const
00133 {
00134   if ((MyRow < 0) || (MyRow >= NumRows_)) {
00135     IFPACK_CHK_ERR(-1); // range not valid
00136   }
00137 
00138   if (Length < NumEntries_[MyRow])
00139     return(-1);
00140 
00141   // always extract using the object Values_ and Indices_.
00142   // This is because I need more space than that given by
00143   // the user (for the external nodes)
00144   int Nnz;
00145   int ierr = Matrix_->ExtractMyRowCopy(MyRow,MaxNumEntriesA_,Nnz,
00146                        &Values_[0],&Indices_[0]);
00147 
00148   IFPACK_CHK_ERR(ierr);
00149 
00150   // populate the user's vectors, add diagonal if not found
00151   NumEntries = 0;
00152 
00153   for (int j = 0 ; j < Nnz ; ++j) {
00154     // only local indices
00155     if (Indices_[j] < NumRows_ ) {
00156       Indices[NumEntries] = Indices_[j];
00157       Values[NumEntries] = Values_[j];
00158       ++NumEntries;
00159     }
00160   }
00161     
00162   return(0);
00163 
00164 }
00165 
00166 //==============================================================================
00167 int Ifpack_LocalFilter::ExtractDiagonalCopy(Epetra_Vector & Diagonal) const
00168 {
00169   if (!Diagonal.Map().SameAs(*Map_))
00170     IFPACK_CHK_ERR(-1);
00171   Diagonal = *Diagonal_;
00172   return(0);
00173 }
00174 
00175 //==============================================================================
00176 int Ifpack_LocalFilter::Apply(const Epetra_MultiVector& X,
00177       Epetra_MultiVector& Y) const 
00178 {
00179 
00180   // skip expensive checks, I suppose input data are ok
00181 
00182   Y.PutScalar(0.0);
00183   int NumVectors = Y.NumVectors();
00184 
00185   double** X_ptr;
00186   double** Y_ptr;
00187   X.ExtractView(&X_ptr);
00188   Y.ExtractView(&Y_ptr);
00189 
00190   for (int i = 0 ; i < NumRows_ ; ++i) {
00191     
00192     int Nnz;
00193     int ierr = Matrix_->ExtractMyRowCopy(i,MaxNumEntriesA_,Nnz,&Values_[0],
00194                                          &Indices_[0]);
00195     IFPACK_CHK_ERR(ierr);
00196 
00197     for (int j = 0 ; j < Nnz ; ++j) {
00198       if (Indices_[j] < NumRows_ ) {
00199     for (int k = 0 ; k < NumVectors ; ++k)
00200       Y_ptr[k][i] += Values_[j] * X_ptr[k][Indices_[j]];
00201       }
00202     }
00203   }
00204 
00205   return(0);
00206 }
00207 
00208 //==============================================================================
00209 int Ifpack_LocalFilter::ApplyInverse(const Epetra_MultiVector& X,
00210          Epetra_MultiVector& Y) const
00211 {
00212   IFPACK_CHK_ERR(-1); // not implemented
00213 }
00214 
00215 //==============================================================================
00216 const Epetra_BlockMap& Ifpack_LocalFilter::Map() const
00217 {
00218   return(*Map_);
00219 }
 All Classes Files Functions Variables Enumerations Friends