IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
Ifpack_RCMReordering.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 "Teuchos_ParameterList.hpp"
00045 #include "Teuchos_RefCountPtr.hpp"
00046 #include "Epetra_MultiVector.h"
00047 #include "Ifpack_Graph.h"
00048 #include "Epetra_RowMatrix.h"
00049 #include "Ifpack_Graph_Epetra_RowMatrix.h"
00050 #include "Ifpack_RCMReordering.h"
00051 
00052 //==============================================================================
00053 Ifpack_RCMReordering::
00054 Ifpack_RCMReordering() :
00055   RootNode_(0),
00056   NumMyRows_(0),
00057   IsComputed_(false)
00058 {
00059 }
00060 
00061 //==============================================================================
00062 Ifpack_RCMReordering::
00063 Ifpack_RCMReordering(const Ifpack_RCMReordering& RHS) :
00064   RootNode_(RHS.RootNode()),
00065   NumMyRows_(RHS.NumMyRows()),
00066   IsComputed_(RHS.IsComputed())
00067 {
00068   Reorder_.resize(NumMyRows());
00069   InvReorder_.resize(NumMyRows());
00070   for (int i = 0 ; i < NumMyRows() ; ++i) {
00071     Reorder_[i] = RHS.Reorder(i);
00072     InvReorder_[i] = RHS.InvReorder(i);
00073   }
00074 }
00075 
00076 //==============================================================================
00077 Ifpack_RCMReordering& Ifpack_RCMReordering::
00078 operator=(const Ifpack_RCMReordering& RHS)
00079 {
00080   if (this == &RHS) {
00081     return (*this);
00082   }
00083 
00084   NumMyRows_ = RHS.NumMyRows(); // set number of local rows
00085   RootNode_ = RHS.RootNode(); // set root node
00086   IsComputed_ = RHS.IsComputed();
00087   // resize vectors, and copy values from RHS
00088   Reorder_.resize(NumMyRows()); 
00089   InvReorder_.resize(NumMyRows());
00090   if (IsComputed()) {
00091     for (int i = 0 ; i < NumMyRows_ ; ++i) {
00092       Reorder_[i] = RHS.Reorder(i);
00093       InvReorder_[i] = RHS.InvReorder(i);
00094     }
00095   }
00096   return (*this);
00097 }
00098 
00099 //==============================================================================
00100 int Ifpack_RCMReordering::
00101 SetParameter(const string Name, const int Value)
00102 {
00103   if (Name == "reorder: root node")
00104     RootNode_ = Value;
00105   return(0);
00106 }
00107 
00108 //==============================================================================
00109 int Ifpack_RCMReordering::
00110 SetParameter(const string Name, const double Value)
00111 {
00112   return(0);
00113 }
00114 
00115 //==============================================================================
00116 int Ifpack_RCMReordering::
00117 SetParameters(Teuchos::ParameterList& List)
00118 {
00119   RootNode_ = List.get("reorder: root node", RootNode_);
00120   return(0);
00121 }
00122 
00123 //==============================================================================
00124 int Ifpack_RCMReordering::Compute(const Epetra_RowMatrix& Matrix)
00125 {
00126   Ifpack_Graph_Epetra_RowMatrix Graph(Teuchos::rcp(&Matrix,false));
00127 
00128   IFPACK_CHK_ERR(Compute(Graph));
00129 
00130   return(0);
00131 }
00132 
00133 //==============================================================================
00134 int Ifpack_RCMReordering::Compute(const Ifpack_Graph& Graph)
00135 {
00136   IsComputed_ = false;
00137   NumMyRows_ = Graph.NumMyRows();
00138   
00139   if ((RootNode_ < 0) || (RootNode_ >= NumMyRows_))
00140     RootNode_ = 0;
00141     
00142   Reorder_.resize(NumMyRows_);
00143 
00144   // the case where one processor holds no chunk of the graph happens...
00145   if (!NumMyRows_) {
00146     InvReorder_.resize(NumMyRows_);
00147     IsComputed_ = true;
00148     return(0);
00149   }
00150 
00151   for (int i = 0 ; i < NumMyRows_ ; ++i)
00152     Reorder_[i] = -1;
00153 
00154   std::vector<int> tmp;
00155   tmp.push_back(RootNode_);
00156 
00157   int count = NumMyRows_ - 1;
00158   int Length = Graph.MaxMyNumEntries();
00159   std::vector<int> Indices(Length);
00160   
00161   Reorder_[RootNode_] = count;
00162   count--;
00163 
00164   // stop when no nodes have been added in the previous level
00165 
00166   while (tmp.size()) {
00167 
00168     std::vector<int> tmp2;
00169 
00170     // for each node in the previous level, look for non-marked
00171     // neighbors. 
00172     for (int i = 0 ; i < (int)tmp.size() ; ++i) {
00173       int NumEntries;
00174       IFPACK_CHK_ERR(Graph.ExtractMyRowCopy(tmp[i], Length,
00175                          NumEntries, &Indices[0]));
00176 
00177       if (Length > 1)
00178     std::sort(Indices.begin(), Indices.begin() + Length);
00179 
00180       for (int j = 0 ; j < NumEntries ; ++j) {
00181     int col = Indices[j];
00182     if (col >= NumMyRows_) 
00183       continue;
00184 
00185     if (Reorder_[col] == -1) {
00186       Reorder_[col] = count;
00187       count--;
00188       if (col != tmp[i]) {
00189         tmp2.push_back(col);
00190       }
00191     }
00192       }
00193     }
00194 
00195     // if no nodes have been found but we still have
00196     // rows to walk through, to localize the next -1 
00197     // and restart.
00198     // FIXME: I can replace with STL
00199     if ((tmp2.size() == 0) && (count != -1)) {
00200       for (int i = 0 ; i < NumMyRows_ ; ++i)
00201     if (Reorder_[i] == -1) {
00202       tmp2.push_back(i);
00203       Reorder_[i] = count--;
00204       break;
00205     }
00206     }
00207 
00208     // prepare for the next level
00209     tmp = tmp2;
00210   }
00211 
00212   // check nothing went wrong
00213   for (int i = 0 ; i < NumMyRows_ ; ++i) {
00214     if (Reorder_[i] == -1)
00215       IFPACK_CHK_ERR(-1);
00216   }
00217   
00218   // build inverse reorder (will be used by ExtractMyRowCopy() 
00219   InvReorder_.resize(NumMyRows_);
00220 
00221   for (int i = 0 ; i < NumMyRows_ ; ++i)
00222     InvReorder_[i] = -1;
00223 
00224   for (int i = 0 ; i < NumMyRows_ ; ++i)
00225     InvReorder_[Reorder_[i]] = i;
00226 
00227   for (int i = 0 ; i < NumMyRows_ ; ++i) {
00228     if (InvReorder_[i] == -1)
00229       IFPACK_CHK_ERR(-1);
00230   }
00231 
00232   IsComputed_ = true;
00233   return(0);
00234 }
00235 
00236 //==============================================================================
00237 int Ifpack_RCMReordering::Reorder(const int i) const
00238 {
00239 #ifdef IFPACK_ABC
00240   if (!IsComputed())
00241     IFPACK_CHK_ERR(-1);
00242   if ((i < 0) || (i >= NumMyRows_))
00243     IFPACK_CHK_ERR(-1);
00244 #endif
00245 
00246   return(Reorder_[i]);
00247 }
00248 
00249 //==============================================================================
00250 int Ifpack_RCMReordering::InvReorder(const int i) const
00251 {
00252 #ifdef IFPACK_ABC
00253   if (!IsComputed())
00254     IFPACK_CHK_ERR(-1);
00255   if ((i < 0) || (i >= NumMyRows_))
00256     IFPACK_CHK_ERR(-1);
00257 #endif
00258 
00259   return(InvReorder_[i]);
00260 }
00261 //==============================================================================
00262 int Ifpack_RCMReordering::P(const Epetra_MultiVector& Xorig,
00263                 Epetra_MultiVector& X) const
00264 {  
00265   int NumVectors = X.NumVectors();
00266 
00267   for (int j = 0 ; j < NumVectors ; ++j) {
00268     for (int i = 0 ; i < NumMyRows_ ; ++i) {
00269       int np = Reorder_[i];
00270       X[j][np] = Xorig[j][i];
00271     }
00272   }
00273 
00274   return(0);
00275 }
00276 
00277 //==============================================================================
00278 int Ifpack_RCMReordering::Pinv(const Epetra_MultiVector& Xorig,
00279                    Epetra_MultiVector& X) const
00280 {
00281   int NumVectors = X.NumVectors();
00282 
00283   for (int j = 0 ; j < NumVectors ; ++j) {
00284     for (int i = 0 ; i < NumMyRows_ ; ++i) {
00285       int np = Reorder_[i];
00286       X[j][i] = Xorig[j][np];
00287     }
00288   }
00289 
00290   return(0);
00291 }
00292 
00293 //==============================================================================
00294 ostream& Ifpack_RCMReordering::Print(std::ostream& os) const
00295 {
00296   os << "*** Ifpack_RCMReordering" << endl << endl;
00297   if (!IsComputed())
00298     os << "*** Reordering not yet computed." << endl;
00299   
00300   os << "*** Number of local rows = " << NumMyRows_ << endl;
00301   os << "*** Root node = " << RootNode_ << endl;
00302   os << endl;
00303   os << "Local Row\tReorder[i]\tInvReorder[i]" << endl;
00304   for (int i = 0 ; i < NumMyRows_ ; ++i) {
00305     os << '\t' << i << "\t\t" << Reorder_[i] << "\t\t" << InvReorder_[i] << endl;
00306   }
00307    
00308   return(os);
00309 }
 All Classes Files Functions Variables Enumerations Friends