Epetra Package Browser (Single Doxygen Collection) Development
Epetra_OffsetIndex.cpp
Go to the documentation of this file.
00001 //@HEADER
00002 // ************************************************************************
00003 //
00004 //               Epetra: Linear Algebra Services Package
00005 //                 Copyright 2011 Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
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 #include "Epetra_ConfigDefs.h"
00043 #include "Epetra_OffsetIndex.h"
00044 #include "Epetra_CrsGraph.h"
00045 #include "Epetra_Import.h"
00046 #include "Epetra_Export.h"
00047 #include "Epetra_Distributor.h"
00048 #include "Epetra_Comm.h"
00049 
00050 //==============================================================================
00051 // Epetra_OffsetIndex constructor from Importer
00052 Epetra_OffsetIndex::Epetra_OffsetIndex( const Epetra_CrsGraph & SourceGraph,
00053                                         const Epetra_CrsGraph & TargetGraph,
00054                                         Epetra_Import & Importer )
00055   : Epetra_Object("Epetra::OffsetIndex"),
00056     NumSame_(0),
00057     SameOffsets_(0),
00058     NumPermute_(0),
00059     PermuteOffsets_(0),
00060     NumExport_(0),
00061     NumRemote_(0),
00062     RemoteOffsets_(0),
00063     DataOwned_(true)
00064 {
00065   NumSame_ = Importer.NumSameIDs();
00066 
00067   NumPermute_ = Importer.NumPermuteIDs();
00068   int * PermuteLIDs = Importer.PermuteToLIDs();
00069 
00070   NumExport_ = Importer.NumExportIDs();
00071   int * ExportLIDs = Importer.ExportLIDs();
00072 
00073   NumRemote_ = Importer.NumRemoteIDs();
00074   int * RemoteLIDs = Importer.RemoteLIDs();
00075 
00076   if(!SourceGraph.RowMap().GlobalIndicesTypeMatch(TargetGraph.RowMap()))
00077      throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: SourceGraph and TargetGraph global indices type mismatch", -1);
00078   if(SourceGraph.RowMap().GlobalIndicesInt()) {
00079 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00080      GenerateLocalOffsets_<int>( SourceGraph, TargetGraph,
00081                             PermuteLIDs );
00082 
00083      GenerateRemoteOffsets_<int>( SourceGraph, TargetGraph,
00084                              ExportLIDs, RemoteLIDs,
00085                              Importer.Distributor() );
00086 #else
00087     throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: ERROR, GlobalIndicesInt but no API for it.",-1);
00088 #endif
00089   }
00090   else if(SourceGraph.RowMap().GlobalIndicesLongLong()) {
00091 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00092      GenerateLocalOffsets_<long long>( SourceGraph, TargetGraph,
00093                             PermuteLIDs );
00094 
00095      GenerateRemoteOffsets_<long long>( SourceGraph, TargetGraph,
00096                              ExportLIDs, RemoteLIDs,
00097                              Importer.Distributor() );
00098 #else
00099     throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00100 #endif
00101   }
00102   else
00103      throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: SourceGraph global indices type unknown", -1);
00104 }
00105 
00106 //==============================================================================
00107 // Epetra_OffsetIndex constructor from Exporter
00108 Epetra_OffsetIndex::Epetra_OffsetIndex( const Epetra_CrsGraph & SourceGraph,
00109                                         const Epetra_CrsGraph & TargetGraph,
00110                                         Epetra_Export & Exporter )
00111   : Epetra_Object("Epetra::OffsetIndex"),
00112     NumSame_(0),
00113     SameOffsets_(0),
00114     NumPermute_(0),
00115     PermuteOffsets_(0),
00116     NumExport_(0),
00117     NumRemote_(0),
00118     RemoteOffsets_(0),
00119     DataOwned_(true)
00120 {
00121   NumSame_ = Exporter.NumSameIDs();
00122 
00123   NumPermute_ = Exporter.NumPermuteIDs();
00124   int * PermuteLIDs = Exporter.PermuteToLIDs();
00125 
00126   NumExport_ = Exporter.NumExportIDs();
00127   int * ExportLIDs = Exporter.ExportLIDs();
00128 
00129   NumRemote_ = Exporter.NumRemoteIDs();
00130   int * RemoteLIDs = Exporter.RemoteLIDs();
00131 
00132   if(!SourceGraph.RowMap().GlobalIndicesTypeMatch(TargetGraph.RowMap()))
00133      throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: SourceGraph and TargetGraph global indices type mismatch", -1);
00134   if(SourceGraph.RowMap().GlobalIndicesInt()) {
00135 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00136      GenerateLocalOffsets_<int>( SourceGraph, TargetGraph,
00137                             PermuteLIDs );
00138 
00139      GenerateRemoteOffsets_<int>( SourceGraph, TargetGraph,
00140                              ExportLIDs, RemoteLIDs,
00141                              Exporter.Distributor() );
00142 #else
00143     throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: ERROR, GlobalIndicesInt but no API for it.",-1);
00144 #endif
00145   }
00146   else if(SourceGraph.RowMap().GlobalIndicesLongLong()) {
00147 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
00148      GenerateLocalOffsets_<long long>( SourceGraph, TargetGraph,
00149                             PermuteLIDs );
00150 
00151      GenerateRemoteOffsets_<long long>( SourceGraph, TargetGraph,
00152                              ExportLIDs, RemoteLIDs,
00153                              Exporter.Distributor() );
00154 #else
00155     throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: ERROR, GlobalIndicesLongLong but no API for it.",-1);
00156 #endif
00157   }
00158   else
00159      throw ReportError("Epetra_OffsetIndex::Epetra_OffsetIndex: SourceGraph global indices type unknown", -1);
00160 }
00161 
00162 //==============================================================================
00163 // Epetra_OffsetIndex copy constructor
00164 Epetra_OffsetIndex::Epetra_OffsetIndex(const Epetra_OffsetIndex& Indexor)
00165   : Epetra_Object(Indexor),
00166     NumSame_(Indexor.NumSame_),
00167     SameOffsets_(Indexor.SameOffsets_),
00168     NumPermute_(Indexor.NumPermute_),
00169     PermuteOffsets_(Indexor.PermuteOffsets_),
00170     NumExport_(0),
00171     NumRemote_(Indexor.NumRemote_),
00172     RemoteOffsets_(Indexor.RemoteOffsets_),
00173     DataOwned_(false)
00174 {
00175 }
00176 
00177 //==============================================================================
00178 // Epetra_OffsetIndex destructor
00179 Epetra_OffsetIndex::~Epetra_OffsetIndex()
00180 {
00181   if( DataOwned_ )
00182   {
00183     for( int i = 0; i < NumSame_; ++i )
00184       if( SameOffsets_[i] ) delete [] SameOffsets_[i];
00185     delete [] SameOffsets_;
00186     for( int i = 0; i < NumPermute_; ++i )
00187       if( PermuteOffsets_[i] ) delete [] PermuteOffsets_[i];
00188     delete [] PermuteOffsets_;
00189     for( int i = 0; i < NumRemote_; ++i )
00190       if( RemoteOffsets_[i] ) delete [] RemoteOffsets_[i];
00191     delete [] RemoteOffsets_;
00192   }
00193 }
00194 
00195 //==============================================================================
00196 template<typename int_type>
00197 void Epetra_OffsetIndex::GenerateLocalOffsets_( const Epetra_CrsGraph & SourceGraph,
00198                                                 const Epetra_CrsGraph & TargetGraph,
00199                                                 const int * PermuteLIDs )
00200 {
00201   const int GlobalMaxNumSourceIndices = SourceGraph.GlobalMaxNumIndices();
00202 
00203   int NumSourceIndices;
00204   int_type * SourceIndices = 0;
00205   if( GlobalMaxNumSourceIndices>0 ) SourceIndices = new int_type[GlobalMaxNumSourceIndices];
00206 
00207   //setup Same Offsets
00208   SameOffsets_ = new int*[NumSame_];
00209   for( int i = 0; i < NumSame_; ++i ) SameOffsets_[i] = 0;
00210 
00211   for( int i = 0; i < NumSame_; ++i ) {
00212     int_type GID = (int_type) SourceGraph.GRID64(i);
00213     SourceGraph.ExtractGlobalRowCopy( GID,
00214                                       GlobalMaxNumSourceIndices,
00215                                       NumSourceIndices,
00216                                       SourceIndices );
00217 
00218     if( NumSourceIndices > 0 ) SameOffsets_[i] = new int[NumSourceIndices];
00219 
00220     int Loc = 0;
00221     int Start = 0;
00222     for( int j = 0; j < NumSourceIndices; ++j ) {
00223       Start = Loc;
00224       if( TargetGraph.FindGlobalIndexLoc(i,SourceIndices[j],Start,Loc) )
00225         SameOffsets_[i][j] = Loc;
00226       else
00227         SameOffsets_[i][j] = -1;
00228     }
00229   }
00230 
00231   //do also for permuted ids
00232   PermuteOffsets_ = new int*[NumPermute_];
00233   for( int i = 0; i < NumPermute_; ++i ) PermuteOffsets_[i] = 0;
00234 
00235   for( int i = 0; i < NumPermute_; ++i ) {
00236     int_type GID = (int_type) SourceGraph.GRID64(PermuteLIDs[i]);
00237     SourceGraph.ExtractGlobalRowCopy( GID,
00238                                       GlobalMaxNumSourceIndices,
00239                                       NumSourceIndices,
00240                                       SourceIndices );
00241 
00242     if( NumSourceIndices > 0 ) PermuteOffsets_[i] = new int[NumSourceIndices];
00243 
00244     int Loc = 0;
00245     int Start = 0;
00246     for( int j = 0; j < NumSourceIndices; ++j ) {
00247       Start = Loc;
00248       if( TargetGraph.FindGlobalIndexLoc(PermuteLIDs[i],SourceIndices[j],Start,Loc) )
00249         PermuteOffsets_[i][j] = Loc;
00250       else
00251         PermuteOffsets_[i][j] = -1;
00252     }
00253   }
00254 
00255   if( GlobalMaxNumSourceIndices>0 ) delete [] SourceIndices;
00256 }
00257 
00258 //==============================================================================
00259 template<typename int_type>
00260 void Epetra_OffsetIndex::GenerateRemoteOffsets_( const Epetra_CrsGraph & SourceGraph,
00261                                                  const Epetra_CrsGraph & TargetGraph,
00262                                                  const int * ExportLIDs,
00263                                                  const int * RemoteLIDs,
00264                                                  Epetra_Distributor & Distor )
00265 {
00266   int numProcs = SourceGraph.RowMap().Comm().NumProc();
00267   if (numProcs < 2) {
00268     return;
00269   }
00270 
00271   const int GlobalMaxNumIndices = SourceGraph.GlobalMaxNumIndices();
00272 
00273   int NumIndices;
00274   /* "Indices" appears to be unused -- jhurani@txcorp.com
00275   int * Indices = 0;
00276   if( GlobalMaxNumIndices>0 ) Indices = new int[GlobalMaxNumIndices];
00277   */
00278 
00279   //Pack Source Rows
00280   int * Sizes = 0;
00281   if( NumExport_ > 0 ) Sizes = new int[NumExport_];
00282   int TotalSize = 0;
00283   for( int i = 0; i < NumExport_; ++i ) {
00284     Sizes[i] = SourceGraph.NumMyIndices(ExportLIDs[i]) + 1;
00285     TotalSize += Sizes[i];
00286   }
00287 
00288   int_type * SourceArray = new int_type[TotalSize+1];
00289   int Loc = 0;
00290   for( int i = 0; i < NumExport_; ++i ) {
00291     int_type GID = (int_type) SourceGraph.GRID64(ExportLIDs[i]);
00292     SourceArray[Loc] = Sizes[i]-1;
00293     SourceGraph.ExtractGlobalRowCopy( GID,
00294                                       GlobalMaxNumIndices,
00295                                       NumIndices,
00296                                       &(SourceArray[Loc+1]) );
00297     Loc += Sizes[i];
00298   }
00299 
00300   //Push to Target
00301   char * cRecvArray = 0;
00302   int_type * RecvArray = 0;
00303   int RecvArraySize = 0;
00304 
00305   Distor.Do( reinterpret_cast<char *>(SourceArray),
00306              (int)sizeof(int_type),
00307              Sizes,
00308              RecvArraySize,
00309              cRecvArray );
00310   RecvArray = reinterpret_cast<int_type*>(cRecvArray);
00311 
00312   //Construct RemoteOffsets
00313   if( NumRemote_ > 0 ) RemoteOffsets_ = new int*[NumRemote_];
00314   for( int i = 0; i < NumRemote_; ++i ) RemoteOffsets_[i] = 0;
00315 
00316   Loc = 0;
00317   for( int i = 0; i < NumRemote_; ++i ) {
00318     NumIndices = (int) RecvArray[Loc];
00319     RemoteOffsets_[i] = new int[NumIndices];
00320     ++Loc;
00321     int FLoc = 0;
00322     int Start = 0;
00323     for( int j = 0; j < NumIndices; ++j ) {
00324       Start = FLoc;
00325       if( TargetGraph.FindGlobalIndexLoc(RemoteLIDs[i],RecvArray[Loc],Start,FLoc) )
00326         RemoteOffsets_[i][j] = FLoc;
00327       else
00328         RemoteOffsets_[i][j] = -1;
00329       ++Loc;
00330     }
00331   }
00332 
00333   /* "Indices" appears to be unused -- jhurani@txcorp.com
00334   if( GlobalMaxNumIndices>0 ) delete [] Indices;
00335   */
00336 
00337   if( Sizes ) delete [] Sizes;
00338   if( SourceArray ) delete [] SourceArray;
00339   if( RecvArraySize ) delete [] cRecvArray;
00340 }
00341 
00342 //=============================================================================
00343 void Epetra_OffsetIndex::Print(std::ostream & os) const
00344 {
00345   os << "Number of Same IDs = " << NumSame_ << std::endl;
00346   os << "Number of Permute IDs = " << NumPermute_ << std::endl;
00347   os << "Number of Remote IDs = " << NumRemote_ << std::endl;
00348 
00349   return;
00350 }
00351 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines