Epetra Package Browser (Single Doxygen Collection) Development
Epetra_FECrsGraph.cpp
Go to the documentation of this file.
00001 
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //               Epetra: Linear Algebra Services Package
00006 //                 Copyright 2011 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ************************************************************************
00041 //@HEADER
00042 
00043 #include "Epetra_ConfigDefs.h"
00044 #include "Epetra_FECrsGraph.h"
00045 #include "Epetra_Import.h"
00046 #include "Epetra_Export.h"
00047 #include "Epetra_Distributor.h"
00048 #include "Epetra_Util.h"
00049 #include "Epetra_Comm.h"
00050 #include "Epetra_HashTable.h"
00051 #include "Epetra_BlockMap.h"
00052 #include "Epetra_Map.h"
00053 #include "Epetra_RowMatrix.h"
00054 #include "Epetra_IntSerialDenseVector.h"
00055 #include "Epetra_SerialDenseVector.h"
00056 #include "Epetra_OffsetIndex.h"
00057 
00058 //-------------------------------------------------------------------------------
00059 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00060              const Epetra_BlockMap& rowMap,
00061              int* numIndicesPerRow,
00062              bool ignoreNonLocalEntries,
00063              bool buildNonlocalGraph)
00064   : Epetra_CrsGraph(CV, rowMap, numIndicesPerRow),
00065     myFirstRow_(0),
00066     myNumRows_(0),
00067     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00068     nonlocalGraph_ (NULL),
00069     buildNonlocalGraph_ (buildNonlocalGraph)
00070 {
00071 }
00072 
00073 //-------------------------------------------------------------------------------
00074 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00075              const Epetra_BlockMap& rowMap,
00076              int numIndicesPerRow,
00077              bool ignoreNonLocalEntries,
00078              bool buildNonlocalGraph)
00079   : Epetra_CrsGraph(CV, rowMap, numIndicesPerRow),
00080     myFirstRow_(0),
00081     myNumRows_(0),
00082     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00083     nonlocalGraph_ (NULL),
00084     buildNonlocalGraph_ (buildNonlocalGraph)
00085 {
00086   myFirstRow_ = rowMap.MinMyGID64();
00087   myNumRows_ = rowMap.NumMyElements();
00088 }
00089 
00090 //-------------------------------------------------------------------------------
00091 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00092              const Epetra_BlockMap& rowMap,
00093              const Epetra_BlockMap& colMap,
00094              int* numIndicesPerRow,
00095              bool ignoreNonLocalEntries,
00096              bool buildNonlocalGraph)
00097   : Epetra_CrsGraph(CV, rowMap, colMap, numIndicesPerRow),
00098     myFirstRow_(0),
00099     myNumRows_(0),
00100     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00101     nonlocalGraph_ (NULL),
00102     buildNonlocalGraph_ (buildNonlocalGraph)
00103 {
00104   myFirstRow_ = rowMap.MinMyGID64();
00105   myNumRows_ = rowMap.NumMyElements();
00106 }
00107 
00108 //-------------------------------------------------------------------------------
00109 Epetra_FECrsGraph::Epetra_FECrsGraph(Epetra_DataAccess CV,
00110              const Epetra_BlockMap& rowMap,
00111              const Epetra_BlockMap& colMap,
00112              int numIndicesPerRow,
00113              bool ignoreNonLocalEntries,
00114              bool buildNonlocalGraph)
00115   : Epetra_CrsGraph(CV, rowMap, colMap, numIndicesPerRow),
00116     myFirstRow_(0),
00117     myNumRows_(0),
00118     ignoreNonLocalEntries_(ignoreNonLocalEntries),
00119     nonlocalGraph_ (NULL),
00120     buildNonlocalGraph_ (buildNonlocalGraph)
00121 {
00122   myFirstRow_ = rowMap.MinMyGID64();
00123   myNumRows_ = rowMap.NumMyElements();
00124 }
00125 
00126 //-------------------------------------------------------------------------------
00127 Epetra_FECrsGraph::~Epetra_FECrsGraph()
00128 {
00129   DeleteMemory();
00130 }
00131 
00132 //----------------------------------------------------------------------------
00133 void Epetra_FECrsGraph::DeleteMemory()
00134 {
00135   if (nonlocalGraph_ != 0)
00136     delete nonlocalGraph_;
00137   // nothing else to do here, since the STL map has an appropriate
00138   // destructor
00139 }
00140 
00141 //----------------------------------------------------------------------------
00142 template<typename int_type>
00143 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const int_type* rows,
00144              int numCols, const int_type* cols)
00145 {
00146   int returncode = 0;
00147   int err = 0;
00148 
00149   Epetra_CrsGraph* thisgraph = static_cast<Epetra_CrsGraph*>(this);
00150 
00151   for(int i=0; i<numRows; ++i) {
00152     const int LID = thisgraph->LRID(rows[i]);
00153     if (LID > -1) {
00154       thisgraph->SetIndicesAreGlobal(true);
00155       err = thisgraph->InsertIndicesIntoSorted(LID, numCols,
00156           const_cast<int_type*>(cols));
00157     }
00158     else {
00159        nonlocalRowData<int_type>()[rows[i]].AddEntries(numCols,cols);
00160     }
00161 
00162     if (err < 0) return (err);
00163     if (err > 0) returncode = err;
00164   }
00165 
00166   return(returncode);
00167 }
00168 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00169 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const int* rows, int numCols, const int* cols)
00170 {
00171   if(RowMap().GlobalIndicesInt())
00172   return InsertGlobalIndices<int>(numRows, rows, numCols, cols);
00173   else
00174   throw ReportError("Epetra_FECrsGraph::InsertGlobalIndices int version called for a matrix that is not int.", -1);
00175 }
00176 #endif
00177 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00178 int Epetra_FECrsGraph::InsertGlobalIndices(int numRows, const long long* rows, int numCols, const long long* cols)
00179 {
00180   if(RowMap().GlobalIndicesLongLong())
00181   return InsertGlobalIndices<long long>(numRows, rows, numCols, cols);
00182   else
00183   throw ReportError("Epetra_FECrsGraph::InsertGlobalIndices long long version called for a matrix that is not long long.", -1);
00184 }
00185 #endif
00186 
00187 //----------------------------------------------------------------------------
00188 int Epetra_FECrsGraph::GlobalAssemble(bool callFillComplete)
00189 {
00190   return GlobalAssemble (static_cast<Epetra_Map&>(this->CrsGraphData_->RowMap_),
00191       static_cast<Epetra_Map&>(this->CrsGraphData_->RowMap_),
00192       callFillComplete);
00193 }
00194 
00195 //----------------------------------------------------------------------------
00196 template<typename int_type>
00197 int Epetra_FECrsGraph::GlobalAssemble(const Epetra_Map& domain_map,
00198                                       const Epetra_Map& range_map,
00199                                       bool callFillComplete)
00200 {
00201   if (Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) {
00202     if (callFillComplete) {
00203       EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
00204     }
00205     return(0);
00206   }
00207 
00208   //In this method we need to gather all the non-local (overlapping) data
00209   //that's been input on each processor, into the
00210   //non-overlapping distribution defined by the map that 'this' graph was
00211   //constructed with.
00212 
00213   // First build a map that describes our nonlocal data.
00214   // We'll use the arbitrary distribution constructor of Map.
00215   // Start by extracting the column numbers from the STL map.
00216 
00217   std::map<int_type,Epetra_CrsGraphData::EntriesInOneRow<int_type> >& nonlocalRowData_var = nonlocalRowData<int_type>();
00218 
00219   const int numRows = (int) nonlocalRowData_var.size();
00220   int_type * presentRowIndices = new int_type[numRows];
00221   typename std::map<int_type,Epetra_CrsGraphData::EntriesInOneRow<int_type> >::iterator nonlocalRows
00222     = nonlocalRowData<int_type>().begin();
00223   for (int i=0 ; nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows, ++i)
00224     presentRowIndices[i] = (int_type) nonlocalRows->first;
00225 
00226   Epetra_Map* sourceMap = new Epetra_Map((int_type) -1, (int) nonlocalRowData<int_type>().size(),
00227           presentRowIndices,
00228                                          (int_type) Map().IndexBase64(), Map().Comm());
00229 
00230   //If sourceMap has global size 0, then no nonlocal data exists and we can
00231   //skip most of this function.
00232   if (sourceMap->NumGlobalElements64() < 1) {
00233     if (callFillComplete) {
00234       EPETRA_CHK_ERR( FillComplete(domain_map, range_map) );
00235     }
00236     delete [] presentRowIndices;
00237     delete sourceMap;
00238     return(0);
00239   }
00240 
00241   //We also need to build a column-map, containing the columns in our
00242   //nonlocal data. To do that, create a list of all column-indices that
00243   //occur in our nonlocal rows. This is most easily done using the
00244   //EntriesInOneRow struct, since that is sorted.
00245   Epetra_CrsGraphData::EntriesInOneRow<int_type> allColumns;
00246   for (nonlocalRows = nonlocalRowData_var.begin();
00247        nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
00248     allColumns.AddEntries((int) nonlocalRows->second.entries_.size(),
00249        nonlocalRows->second.entries_.size() ? &nonlocalRows->second.entries_[0] : 0);
00250 
00251   Epetra_Map* colMap = new Epetra_Map((int_type) -1, (int) allColumns.entries_.size(),
00252              allColumns.entries_.size() ? &allColumns.entries_[0] : 0,
00253                                       (int_type) Map().IndexBase64(), Map().Comm());
00254 
00255   //now we need to create a graph with sourceMap and colMap, and fill it with
00256   //our nonlocal data so we can then export it to the correct owning processors
00257 
00258   int * rowLengths = new int[numRows];
00259   {
00260     int i = 0;
00261     for (nonlocalRows = nonlocalRowData_var.begin();
00262   nonlocalRows != nonlocalRowData_var.end() ; ++nonlocalRows, ++i)
00263       rowLengths[i] = (int) nonlocalRows->second.entries_.size();
00264   }
00265 
00266   Epetra_CrsGraph* tempGrph = NULL;
00267   if (buildNonlocalGraph_) {
00268     nonlocalGraph_ = new Epetra_CrsGraph(Copy, *sourceMap, *colMap, rowLengths);
00269     tempGrph = nonlocalGraph_;
00270   }
00271   else
00272     tempGrph = new Epetra_CrsGraph(Copy, *sourceMap, *colMap, rowLengths);
00273 
00274   //Next we need to make sure the 'indices-are-global' attribute of tempGrph
00275   //is set to true, in case this processor doesn't end up calling the
00276   //InsertGlobalIndices method...
00277 
00278   tempGrph->SetIndicesAreGlobal(true);
00279 
00280   for (nonlocalRows = nonlocalRowData_var.begin();
00281        nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
00282     EPETRA_CHK_ERR( tempGrph->InsertGlobalIndices(nonlocalRows->first,
00283              (int) nonlocalRows->second.entries_.size(),
00284              nonlocalRows->second.entries_.size() ? &nonlocalRows->second.entries_[0] : 0) );
00285 
00286 
00287   //Now we need to call FillComplete on our temp graph. We need to
00288   //pass a DomainMap and RangeMap.
00289 
00290   EPETRA_CHK_ERR(tempGrph->FillComplete(domain_map, range_map));
00291 
00292   if (buildNonlocalGraph_)
00293     tempGrph->OptimizeStorage();
00294 
00295   Epetra_Export* exporter = new Epetra_Export(*sourceMap, RowMap());
00296 
00297   EPETRA_CHK_ERR(Export(*tempGrph, *exporter, Add));
00298 
00299   if(callFillComplete) {
00300     EPETRA_CHK_ERR(FillComplete(domain_map, range_map));
00301   }
00302 
00303   //now reset the values in our nonlocal data
00304   for (nonlocalRows = nonlocalRowData_var.begin();
00305        nonlocalRows != nonlocalRowData_var.end(); ++nonlocalRows)
00306     nonlocalRows->second.entries_.clear();
00307   nonlocalRowData_var.clear();
00308 
00309   delete [] rowLengths;
00310   delete [] presentRowIndices;
00311   delete exporter;
00312   if (!buildNonlocalGraph_)
00313     delete tempGrph;
00314   delete sourceMap;
00315   delete colMap;
00316 
00317   return(0);
00318 }
00319 
00320 int Epetra_FECrsGraph::GlobalAssemble(const Epetra_Map& domain_map,
00321                                       const Epetra_Map& range_map,
00322                                       bool callFillComplete)
00323 {
00324   if(!domain_map.GlobalIndicesTypeMatch(range_map))
00325      throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot be called with different indices types for domainMap and rangeMap", -1);
00326 
00327   if(!RowMap().GlobalIndicesTypeMatch(domain_map))
00328     throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot be called with different indices types for row map and incoming rangeMap", -1);
00329 
00330   if(RowMap().GlobalIndicesInt())
00331 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00332     return GlobalAssemble<int>(domain_map, range_map, callFillComplete);
00333 #else
00334     throw ReportError("Epetra_FECrsGraph::GlobalAssemble: ERROR, GlobalIndicesInt but no API for it.",-1);
00335 #endif
00336 
00337   if(RowMap().GlobalIndicesLongLong())
00338 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00339     return GlobalAssemble<long long>(domain_map, range_map, callFillComplete);
00340 #else
00341     throw ReportError("Epetra_FECrsGraph::GlobalAssemble: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00342 #endif
00343 
00344   throw ReportError("Epetra_FECrsGraph::GlobalAssemble: cannot determine global index type", -1);
00345 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines