Epetra_FECrsGraph.cpp

Go to the documentation of this file.
00001 
00002 //@HEADER
00003 // ************************************************************************
00004 // 
00005 //               Epetra: Linear Algebra Services Package 
00006 //                 Copyright (2001) Sandia Corporation
00007 // 
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //  
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00026 // 
00027 // ************************************************************************
00028 //@HEADER
00029 
00030 #include "Epetra_FECrsGraph.h"
00031 #include "Epetra_Import.h"
00032 #include "Epetra_Export.h"
00033 #include "Epetra_Distributor.h"
00034 #include "Epetra_Util.h"
00035 #include "Epetra_Comm.h"
00036 #include "Epetra_HashTable.h"
00037 #include "Epetra_BlockMap.h"
00038 #include "Epetra_Map.h"
00039 #include "Epetra_RowMatrix.h"
00040 #include "Epetra_IntSerialDenseVector.h"
00041 #include "Epetra_SerialDenseVector.h"
00042 #include "Epetra_OffsetIndex.h"
00043 
00044 //-------------------------------------------------------------------------------
00045 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00046              const Epetra_BlockMap& RowMap,
00047              int* NumIndicesPerRow,
00048              bool ignoreNonLocalEntries)
00049   : Epetra_CrsGraph(CV, RowMap, NumIndicesPerRow),
00050     myFirstRow_(0),
00051     myNumRows_(0),
00052     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00053     numNonlocalRows_(0),
00054     nonlocalRows_(NULL),
00055     nonlocalRowLengths_(NULL),
00056     nonlocalRowAllocLengths_(NULL),
00057     nonlocalCols_(NULL)
00058 {
00059 }
00060 
00061 //-------------------------------------------------------------------------------
00062 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00063              const Epetra_BlockMap& RowMap,
00064              int NumIndicesPerRow,
00065              bool ignoreNonLocalEntries)
00066   : Epetra_CrsGraph(CV, RowMap, NumIndicesPerRow),
00067     myFirstRow_(0),
00068     myNumRows_(0),
00069     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00070     numNonlocalRows_(0),
00071     nonlocalRows_(NULL),
00072     nonlocalRowLengths_(NULL),
00073     nonlocalRowAllocLengths_(NULL),
00074     nonlocalCols_(NULL)
00075 {
00076   myFirstRow_ = RowMap.MinMyGID();
00077   myNumRows_ = RowMap.NumMyElements();
00078 }
00079 
00080 //-------------------------------------------------------------------------------
00081 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00082              const Epetra_BlockMap& RowMap,
00083              const Epetra_BlockMap& ColMap,
00084              int* NumIndicesPerRow,
00085              bool ignoreNonLocalEntries)
00086   : Epetra_CrsGraph(CV, RowMap, ColMap, NumIndicesPerRow),
00087     myFirstRow_(0),
00088     myNumRows_(0),
00089     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00090     numNonlocalRows_(0),
00091     nonlocalRows_(NULL),
00092     nonlocalRowLengths_(NULL),
00093     nonlocalRowAllocLengths_(NULL),
00094     nonlocalCols_(NULL)
00095 {
00096   myFirstRow_ = RowMap.MinMyGID();
00097   myNumRows_ = RowMap.NumMyElements();
00098 }
00099 
00100 //-------------------------------------------------------------------------------
00101 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00102              const Epetra_BlockMap& RowMap,
00103              const Epetra_BlockMap& ColMap,
00104              int NumIndicesPerRow,
00105              bool ignoreNonLocalEntries)
00106   : Epetra_CrsGraph(CV, RowMap, ColMap, NumIndicesPerRow),
00107     myFirstRow_(0),
00108     myNumRows_(0),
00109     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00110     numNonlocalRows_(0),
00111     nonlocalRows_(NULL),
00112     nonlocalRowLengths_(NULL),
00113     nonlocalRowAllocLengths_(NULL),
00114     nonlocalCols_(NULL)
00115 {
00116   myFirstRow_ = RowMap.MinMyGID();
00117   myNumRows_ = RowMap.NumMyElements();
00118 }
00119 
00120 //-------------------------------------------------------------------------------
00121 Epetra_FECrsGraph::~Epetra_FECrsGraph()
00122 {
00123   DeleteMemory();
00124 }
00125 
00126 //----------------------------------------------------------------------------
00127 void Epetra_FECrsGraph::DeleteMemory()
00128 {
00129   if (numNonlocalRows_ > 0) {
00130     for(int i=0; i<numNonlocalRows_; ++i) {
00131       delete [] nonlocalCols_[i];
00132     }
00133     delete [] nonlocalCols_;
00134     delete [] nonlocalRows_;
00135     delete [] nonlocalRowLengths_;
00136     delete [] nonlocalRowAllocLengths_;
00137     numNonlocalRows_ = 0;
00138   }
00139 }
00140 
00141 //----------------------------------------------------------------------------
00142 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const int* rows,
00143              int numCols, const int* cols)
00144 {
00145   int returncode = 0;
00146   int err = 0;
00147 
00148   Epetra_CrsGraph* thisgraph = static_cast<Epetra_CrsGraph*>(this);
00149 
00150   for(int i=0; i<numRows; ++i) {
00151     if (Map().MyGID(rows[i])) {
00152       err = thisgraph->InsertGlobalIndices(rows[i], numCols, (int*)cols);
00153     }
00154     else {
00155       err = InputNonlocalIndices(rows[i], numCols, cols);
00156     }
00157 
00158     if (err<0) return(err);
00159     if (err>0) returncode = err;
00160   }
00161 
00162   return(returncode);
00163 }
00164 
00165 //----------------------------------------------------------------------------
00166 int Epetra_FECrsGraph::InsertNonlocalRow(int row, int offset)
00167 {
00168   int alloc_len = numNonlocalRows_;
00169   EPETRA_CHK_ERR( Epetra_Util_insert(row, offset, nonlocalRows_, numNonlocalRows_,
00170              alloc_len, 1) );
00171 
00172   int tmp1 = numNonlocalRows_-1;
00173   int tmp2 = alloc_len-1;
00174 
00175   EPETRA_CHK_ERR( Epetra_Util_insert(0, offset, nonlocalRowLengths_,
00176              tmp1, tmp2, 1) );
00177 
00178   --tmp1;
00179   --tmp2;
00180   int initialAllocLen = 16;
00181   EPETRA_CHK_ERR( Epetra_Util_insert(initialAllocLen, offset,
00182              nonlocalRowAllocLengths_,
00183              tmp1, tmp2, 1) );
00184 
00185   int** newCols = new int*[numNonlocalRows_];
00186 
00187   newCols[offset] = new int[initialAllocLen];
00188 
00189   int index = 0;
00190   for(int i=0; i<numNonlocalRows_-1; ++i) {
00191     if (i == offset) {
00192       ++index;
00193     }
00194 
00195     newCols[index++] = nonlocalCols_[i];
00196   }
00197 
00198   delete [] nonlocalCols_;
00199 
00200   nonlocalCols_ = newCols;
00201 
00202   return(0);
00203 }
00204 
00205 //----------------------------------------------------------------------------
00206 int Epetra_FECrsGraph::InputNonlocalIndices(int row,
00207               int numCols,
00208               const int* cols)
00209 {
00210   int insertPoint = -1;
00211 
00212   //find offset of this row in our list of nonlocal rows.
00213   int rowoffset = Epetra_Util_binary_search(row, nonlocalRows_, numNonlocalRows_,
00214               insertPoint);
00215 
00216   if (rowoffset < 0) {
00217     EPETRA_CHK_ERR( InsertNonlocalRow(row, insertPoint) );
00218     rowoffset = insertPoint;
00219   }
00220 
00221   for(int i=0; i<numCols; ++i) {
00222     EPETRA_CHK_ERR( InputNonlocalIndex(rowoffset, cols[i]) );
00223   }
00224 
00225   return(0); 
00226 }
00227 
00228 //----------------------------------------------------------------------------
00229 int Epetra_FECrsGraph::InputNonlocalIndex(int rowoffset,
00230             int col)
00231 {
00232   int*& colIndices = nonlocalCols_[rowoffset];
00233 
00234   int insertPoint = -1;
00235   int coloffset = Epetra_Util_binary_search(col, colIndices,
00236               nonlocalRowLengths_[rowoffset],
00237               insertPoint);
00238 
00239   if (coloffset < 0) {
00240     //  insert col in colIndices
00241     EPETRA_CHK_ERR( Epetra_Util_insert(col, insertPoint, colIndices,
00242                nonlocalRowLengths_[rowoffset],
00243                nonlocalRowAllocLengths_[rowoffset]));
00244   }
00245 
00246   return(0);
00247 }
00248 
00249 //----------------------------------------------------------------------------
00250 int Epetra_FECrsGraph::GlobalAssemble(bool callFillComplete)
00251 {
00252   if (Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) {
00253     if (callFillComplete) {
00254       EPETRA_CHK_ERR( FillComplete() );
00255     }
00256     return(0);
00257   }
00258 
00259   int i, j;
00260 
00261   //In this method we need to gather all the non-local (overlapping) data
00262   //that's been input on each processor, into the
00263   //non-overlapping distribution defined by the map that 'this' graph was
00264   //constructed with.
00265 
00266   //First build a map that describes our nonlocal data.
00267   //We'll use the arbitrary distribution constructor of Map.
00268 
00269   Epetra_Map* sourceMap = new Epetra_Map(-1, numNonlocalRows_, nonlocalRows_,
00270            Map().IndexBase(), Map().Comm());
00271 
00272   //If sourceMap has global size 0, then no nonlocal data exists and we can
00273   //skip most of this function.
00274   if (sourceMap->NumGlobalElements() < 1) {
00275     if (callFillComplete) {
00276       EPETRA_CHK_ERR( FillComplete() );
00277     }
00278     delete sourceMap;
00279     return(0);
00280   }
00281 
00282   //We also need to build a column-map, containing the columns in our
00283   //nonlocal data. To do that, create a list of all column-indices that
00284   //occur in our nonlocal rows.
00285 
00286   int numCols = 0, allocLen = 0;
00287   int* cols = NULL;
00288   int insertPoint = -1;
00289 
00290   for(i=0; i<numNonlocalRows_; ++i) {
00291     for(j=0; j<nonlocalRowLengths_[i]; ++j) {
00292       int col = nonlocalCols_[i][j];
00293       int offset = Epetra_Util_binary_search(col, cols, numCols, insertPoint);
00294       if (offset < 0) {
00295   EPETRA_CHK_ERR( Epetra_Util_insert(col, insertPoint, cols,
00296              numCols, allocLen) );
00297       }
00298     }
00299   }
00300 
00301   Epetra_Map* colMap = new Epetra_Map(-1, numCols, cols,
00302               Map().IndexBase(), Map().Comm());
00303 
00304   delete [] cols;
00305   numCols = 0;
00306   allocLen = 0;
00307 
00308   //now we need to create a graph with sourceMap and colMap, and fill it with
00309   //our nonlocal data so we can then export it to the correct owning processors.
00310 
00311   Epetra_CrsGraph* tempGrph = new Epetra_CrsGraph(Copy, *sourceMap, *colMap,
00312               nonlocalRowLengths_);
00313 
00314 
00315   //Next we need to make sure the 'indices-are-global' attribute of tempGrph
00316   //is set to true, in case this processor doesn't end up calling the
00317   //InsertGlobalIndices method...
00318 
00319   tempGrph->SetIndicesAreGlobal(true);
00320 
00321   for(i=0; i<numNonlocalRows_; ++i) {
00322     EPETRA_CHK_ERR( tempGrph->InsertGlobalIndices(nonlocalRows_[i],
00323               nonlocalRowLengths_[i],
00324               nonlocalCols_[i]) );
00325   }
00326 
00327   //Now we need to call FillComplete on our temp graph. We need to
00328   //pass a DomainMap and RangeMap, which are not the same as the RowMap
00329   //and ColMap that we constructed the graph with.
00330 
00331   EPETRA_CHK_ERR(tempGrph->FillComplete(RowMap(), *sourceMap));
00332 
00333   Epetra_Export* exporter = new Epetra_Export(*sourceMap, RowMap());
00334 
00335   EPETRA_CHK_ERR(Export(*tempGrph, *exporter, Add));
00336 
00337   if(callFillComplete) {
00338     EPETRA_CHK_ERR(FillComplete());
00339   }
00340 
00341   //now reset the values in our nonlocal data
00342   for(i=0; i<numNonlocalRows_; ++i) {
00343     for(j=0; j<nonlocalRowLengths_[i]; ++j) {
00344       nonlocalCols_[i][j] = 0;
00345     }
00346     nonlocalRowLengths_[i] = 0;
00347   }
00348 
00349   delete exporter;
00350   delete tempGrph;
00351   delete sourceMap;
00352   delete colMap;
00353 
00354   return(0);
00355 }
00356 
00357 //----------------------------------------------------------------------------
00358 int Epetra_FECrsGraph::GlobalAssemble(const Epetra_Map& domain_map,
00359                                       const Epetra_Map& range_map,
00360                                       bool callFillComplete)
00361 {
00362   if (Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) {
00363     if (callFillComplete) {
00364       EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
00365     }
00366     return(0);
00367   }
00368 
00369   int i, j;
00370 
00371   //In this method we need to gather all the non-local (overlapping) data
00372   //that's been input on each processor, into the
00373   //non-overlapping distribution defined by the map that 'this' graph was
00374   //constructed with.
00375 
00376   //First build a map that describes our nonlocal data.
00377   //We'll use the arbitrary distribution constructor of Map.
00378 
00379   Epetra_Map* sourceMap = new Epetra_Map(-1, numNonlocalRows_, nonlocalRows_,
00380                                          Map().IndexBase(), Map().Comm());
00381 
00382   //If sourceMap has global size 0, then no nonlocal data exists and we can
00383   //skip most of this function.
00384   if (sourceMap->NumGlobalElements() < 1) {
00385     if (callFillComplete) {
00386       EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
00387     }
00388     delete sourceMap;
00389     return(0);
00390   }
00391 
00392   //We also need to build a column-map, containing the columns in our
00393   //nonlocal data. To do that, create a list of all column-indices that
00394   //occur in our nonlocal rows.
00395 
00396   int numCols = 0, allocLen = 0;
00397   int* cols = NULL;
00398   int insertPoint = -1;
00399 
00400   for(i=0; i<numNonlocalRows_; ++i) {
00401     for(j=0; j<nonlocalRowLengths_[i]; ++j) {
00402       int col = nonlocalCols_[i][j];
00403       int offset = Epetra_Util_binary_search(col, cols, numCols, insertPoint);
00404       if (offset < 0) {
00405         EPETRA_CHK_ERR( Epetra_Util_insert(col, insertPoint, cols,
00406                                            numCols, allocLen) );
00407       }
00408     }
00409   }
00410 
00411   Epetra_Map* colMap = new Epetra_Map(-1, numCols, cols,
00412                                       Map().IndexBase(), Map().Comm());
00413 
00414   delete [] cols;
00415   numCols = 0;
00416   allocLen = 0;
00417 
00418   //now we need to create a graph with sourceMap and colMap, and fill it with
00419   //our nonlocal data so we can then export it to the correct owning processors
00420 
00421   Epetra_CrsGraph* tempGrph = new Epetra_CrsGraph(Copy, *sourceMap, *colMap,
00422                                                   nonlocalRowLengths_);
00423 
00424   //Next we need to make sure the 'indices-are-global' attribute of tempGrph
00425   //is set to true, in case this processor doesn't end up calling the
00426   //InsertGlobalIndices method...
00427 
00428   tempGrph->SetIndicesAreGlobal(true);
00429 
00430   for(i=0; i<numNonlocalRows_; ++i) {
00431     EPETRA_CHK_ERR( tempGrph->InsertGlobalIndices(nonlocalRows_[i],
00432                                                   nonlocalRowLengths_[i],
00433                                                   nonlocalCols_[i]) );
00434   }
00435 
00436   //Now we need to call FillComplete on our temp graph. We need to
00437   //pass a DomainMap and RangeMap.
00438 
00439   EPETRA_CHK_ERR(tempGrph->FillComplete(domain_map, range_map));
00440 
00441   Epetra_Export* exporter = new Epetra_Export(*sourceMap, RowMap());
00442 
00443   EPETRA_CHK_ERR(Export(*tempGrph, *exporter, Add));
00444 
00445   if(callFillComplete) {
00446     EPETRA_CHK_ERR(FillComplete(domain_map, range_map));
00447   }
00448 
00449   //now reset the values in our nonlocal data
00450   for(i=0; i<numNonlocalRows_; ++i) {
00451     for(j=0; j<nonlocalRowLengths_[i]; ++j) {
00452       nonlocalCols_[i][j] = 0;
00453     }
00454     nonlocalRowLengths_[i] = 0;
00455   }
00456 
00457   delete exporter;
00458   delete tempGrph;
00459   delete sourceMap;
00460   delete colMap;
00461 
00462   return(0);
00463 }
00464 

Generated on Wed May 12 21:41:05 2010 for Epetra Package Browser (Single Doxygen Collection) by  doxygen 1.4.7