Tpetra Matrix/Vector Services  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Tpetra_RowMatrixTransposer_def.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) 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 #ifndef TPETRA_ROWMATRIXTRANSPOSER_DEF_HPP
00043 #define TPETRA_ROWMATRIXTRANSPOSER_DEF_HPP
00044 
00045 #include "Tpetra_Export.hpp"
00046 #include "Tpetra_Import.hpp"
00047 #include "Tpetra_Map.hpp"
00048 #include "Teuchos_DefaultSerialComm.hpp"
00049 #ifdef DOXYGEN_USE_ONLY
00050   // #include "Tpetra_RowMatrixtransposer_decl.hpp"
00051 #endif
00052 
00053 namespace Tpetra {
00054 
00055 template<class Scalar,
00056      class LocalOrdinal,
00057      class GlobalOrdinal,
00058      class Node>
00059 RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
00060 RowMatrixTransposer (const Teuchos::RCP<const crs_matrix_type>& origMatrix)
00061   : origMatrix_ (origMatrix) {}
00062 
00063 template<class Scalar,
00064      class LocalOrdinal,
00065      class GlobalOrdinal,
00066      class Node>
00067 TEUCHOS_DEPRECATED
00068 RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
00069 RowMatrixTransposer (const crs_matrix_type& origMatrix)
00070   : origMatrix_ (Teuchos::rcpFromRef (origMatrix)) {}
00071 
00072 template<class Scalar,
00073      class LocalOrdinal,
00074      class GlobalOrdinal,
00075      class Node>
00076 Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
00077 RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
00078 createTranspose()
00079 {
00080   using Teuchos::RCP;
00081 
00082   // Do the local transpose
00083   RCP<crs_matrix_type> transMatrixWithSharedRows = createTransposeLocal ();
00084 
00085   // If transMatrixWithSharedRows has an exporter, that's what we
00086   // want.  If it doesn't, the rows aren't actually shared, and we're
00087   // done!
00088   RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > exporter =
00089     transMatrixWithSharedRows->getGraph ()->getExporter ();
00090   if (exporter.is_null ()) {
00091     return transMatrixWithSharedRows;
00092   }
00093   else {
00094     // Use the Export object to do a fused Export and fillComplete.
00095     return exportAndFillCompleteCrsMatrix<crs_matrix_type> (transMatrixWithSharedRows, *exporter);
00096   }
00097 }
00098 
00099 
00100 // mfh 03 Feb 2013: In a definition outside the class like this, the
00101 // return value is considered outside the class scope (for things like
00102 // resolving typedefs), but the arguments are considered inside the
00103 // class scope.
00104 template<class Scalar,
00105          class LocalOrdinal,
00106          class GlobalOrdinal,
00107          class Node>
00108 Teuchos::RCP<CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
00109 RowMatrixTransposer<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
00110 createTransposeLocal ()
00111 {
00112   using Teuchos::Array;
00113   using Teuchos::ArrayRCP;
00114   using Teuchos::ArrayView;
00115   using Teuchos::RCP;
00116   using Teuchos::rcp;
00117   using Teuchos::rcp_dynamic_cast;
00118   typedef LocalOrdinal LO;
00119   typedef GlobalOrdinal GO;
00120   typedef Tpetra::Import<LO, GO, Node> import_type;
00121   typedef Tpetra::Export<LO, GO, Node> export_type;
00122 
00123   //
00124   // This transpose is based upon the approach in EpetraExt.
00125   //
00126   size_t numLocalCols = origMatrix_->getNodeNumCols();
00127   size_t numLocalRows = origMatrix_->getNodeNumRows();
00128   size_t numLocalNnz  = origMatrix_->getNodeNumEntries();
00129 
00130   // Determine how many nonzeros there are per row in the transpose.
00131   Array<size_t> CurrentStart(numLocalCols,0);
00132   ArrayView<const LO> localIndices;
00133   ArrayView<const Scalar> localValues;
00134   RCP<const crs_matrix_type> crsMatrix =
00135     rcp_dynamic_cast<const crs_matrix_type> (origMatrix_);
00136   if (crsMatrix == Teuchos::null) {
00137     for (size_t i=0; i<numLocalRows; ++i) {
00138       const size_t numEntriesInRow = origMatrix_->getNumEntriesInLocalRow(i);
00139       origMatrix_->getLocalRowView(i, localIndices, localValues);
00140       for (size_t j=0; j<numEntriesInRow; ++j) {
00141         ++CurrentStart[ localIndices[j] ];
00142       }
00143     }
00144   } else {
00145     ArrayRCP<const size_t> origRowPtr_rcp;
00146     ArrayRCP<const LO>     origColInd_rcp;
00147     ArrayRCP<const Scalar> origValues_rcp;
00148     crsMatrix->getAllValues(origRowPtr_rcp, origColInd_rcp, origValues_rcp);
00149     ArrayView<const LO> origColInd = origColInd_rcp();
00150     for (LO j=0; j<origColInd.size(); ++j) {
00151       ++CurrentStart[ origColInd[j] ];
00152     }
00153   }
00154 
00155   // create temporary row-major storage for the transposed matrix
00156 
00157   ArrayRCP<size_t> rowptr_rcp(numLocalCols+1);
00158   ArrayRCP<LO>     colind_rcp(numLocalNnz);
00159   ArrayRCP<Scalar> values_rcp(numLocalNnz);
00160 
00161   // Since ArrayRCP's are slow...
00162   ArrayView<size_t> TransRowptr = rowptr_rcp();
00163   ArrayView<LO>     TransColind = colind_rcp();
00164   ArrayView<Scalar> TransValues = values_rcp();
00165 
00166   // Scansum the TransRowptr; reset CurrentStart
00167   TransRowptr[0]=0;
00168   for (size_t i=1; i<numLocalCols+1; ++i) TransRowptr[i]  = CurrentStart[i-1] + TransRowptr[i-1];
00169   for (size_t i=0; i<numLocalCols;   ++i) CurrentStart[i] = TransRowptr[i];
00170 
00171   // populate the row-major storage so that the data for the transposed
00172   // matrix is easy to access
00173   if (crsMatrix == Teuchos::null) {
00174     for (size_t i=0; i<numLocalRows; ++i) {
00175       const size_t numEntriesInRow = origMatrix_->getNumEntriesInLocalRow (i);
00176       origMatrix_->getLocalRowView(i, localIndices, localValues);
00177 
00178       for (size_t j=0; j<numEntriesInRow; ++j) {
00179         size_t idx = CurrentStart[localIndices[j]];
00180         TransColind[idx] = Teuchos::as<LO>(i);
00181         TransValues[idx] = localValues[j];
00182         ++CurrentStart[localIndices[j]];
00183       }
00184     } //for (size_t i=0; i<numLocalRows; ++i)
00185   } else {
00186     ArrayRCP<const size_t> origRowPtr_rcp;
00187     ArrayRCP<const LO>     origColInd_rcp;
00188     ArrayRCP<const Scalar> origValues_rcp;
00189     crsMatrix->getAllValues(origRowPtr_rcp, origColInd_rcp, origValues_rcp);
00190     ArrayView<const size_t>   origRowPtr = origRowPtr_rcp();
00191     ArrayView<const LO> origColInd = origColInd_rcp();
00192     ArrayView<const Scalar>   origValues = origValues_rcp();
00193     size_t k=0;
00194     for (LO i=0; i<origRowPtr.size()-1; ++i) {
00195       const LO rowIndex = Teuchos::as<LO>(i);
00196       for (size_t j=origRowPtr[i]; j<origRowPtr[i+1]; ++j) {
00197         size_t idx = CurrentStart[origColInd[k]];
00198         TransColind[idx] = rowIndex;
00199         TransValues[idx] = origValues[k];
00200         ++CurrentStart[origColInd[k++]];
00201       }
00202     }
00203   }
00204 
00205   //Allocate and populate temporary matrix with rows not uniquely owned
00206   RCP<crs_matrix_type> transMatrixWithSharedRows =
00207     rcp (new crs_matrix_type (origMatrix_->getColMap (),
00208                               origMatrix_->getRowMap (), 0));
00209   transMatrixWithSharedRows->setAllValues (rowptr_rcp, colind_rcp, values_rcp);
00210 
00211   // Prebuild the importers and exporters the no-communication way,
00212   // flipping the importers and exporters around.
00213   RCP<const import_type> myImport;
00214   RCP<const export_type> myExport;
00215   if (! origMatrix_->getGraph ()->getImporter ().is_null ()) {
00216     myExport = rcp (new export_type (*origMatrix_->getGraph ()->getImporter ()));
00217   }
00218   if (! origMatrix_->getGraph ()->getExporter ().is_null ()) {
00219     myImport = rcp (new import_type (*origMatrix_->getGraph ()->getExporter ()));
00220   }
00221 
00222   // Call ESFC & return
00223   transMatrixWithSharedRows->expertStaticFillComplete (origMatrix_->getRangeMap (),
00224                                                        origMatrix_->getDomainMap (),
00225                                                        myImport, myExport);
00226   return transMatrixWithSharedRows;
00227 }
00228 //
00229 // Explicit instantiation macro
00230 //
00231 // Must be expanded from within the Tpetra namespace!
00232 //
00233 
00234 #define TPETRA_ROWMATRIXTRANSPOSER_INSTANT(SCALAR,LO,GO,NODE) \
00235   \
00236   template class RowMatrixTransposer< SCALAR, LO , GO , NODE >;
00237 
00238 
00239 }
00240 
00241 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines