Zoltan2
Zoltan2_XpetraCrsMatrixAdapter.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //   Zoltan2: A package of combinatorial algorithms for scientific computing
00006 //                  Copyright 2012 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 Karen Devine      (kddevin@sandia.gov)
00039 //                    Erik Boman        (egboman@sandia.gov)
00040 //                    Siva Rajamanickam (srajama@sandia.gov)
00041 //
00042 // ***********************************************************************
00043 //
00044 // @HEADER
00045 
00050 #ifndef _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
00051 #define _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
00052 
00053 #include <Zoltan2_MatrixAdapter.hpp>
00054 #include <Zoltan2_StridedData.hpp>
00055 #include <Zoltan2_XpetraTraits.hpp>
00056 
00057 #include <Xpetra_CrsMatrix.hpp>
00058 
00059 namespace Zoltan2 {
00060 
00062 
00084 template <typename User, typename UserCoord=User>
00085   class XpetraCrsMatrixAdapter : public MatrixAdapter<User,UserCoord> {
00086 public:
00087 
00088 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00089   typedef typename InputTraits<User>::scalar_t    scalar_t;
00090   typedef typename InputTraits<User>::lno_t    lno_t;
00091   typedef typename InputTraits<User>::gno_t    gno_t;
00092   typedef typename InputTraits<User>::zgid_t    zgid_t;
00093   typedef typename InputTraits<User>::part_t   part_t;
00094   typedef typename InputTraits<User>::node_t   node_t;
00095   typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> xmatrix_t;
00096   typedef MatrixAdapter<User,UserCoord> base_adapter_t;
00097   typedef User user_t;
00098   typedef UserCoord userCoord_t;
00099 #endif
00100 
00103   ~XpetraCrsMatrixAdapter() { }
00104 
00110   XpetraCrsMatrixAdapter(const RCP<const User> &inmatrix,
00111                          int numWeightsPerRow=0);
00112 
00125   void setWeights(const scalar_t *weightVal, int stride, int idx = 0);
00126 
00142   void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0);
00143 
00149   void setWeightIsDegree(int idx);
00150 
00156   void setRowWeightIsNumberOfNonZeros(int idx);
00157 
00159   // The MatrixAdapter interface.
00161 
00162   size_t getLocalNumRows() const { 
00163     return matrix_->getNodeNumRows();
00164   }
00165 
00166   size_t getLocalNumColumns() const { 
00167     return matrix_->getNodeNumCols();
00168   }
00169 
00170   size_t getLocalNumEntries() const {
00171     return matrix_->getNodeNumEntries();
00172   }
00173 
00174   bool CRSViewAvailable() const { return true; }
00175 
00176   void getRowIDsView(const zgid_t *&rowIds) const 
00177   {
00178     ArrayView<const zgid_t> rowView = rowMap_->getNodeElementList();
00179     rowIds = rowView.getRawPtr();
00180   }
00181 
00182   void getCRSView(const lno_t *&offsets, const zgid_t *&colIds) const
00183   {
00184     offsets = offset_.getRawPtr();
00185     colIds = columnIds_.getRawPtr();
00186   }
00187 
00188   void getCRSView(const lno_t *&offsets, const zgid_t *&colIds,
00189                     const scalar_t *&values) const
00190   {
00191     offsets = offset_.getRawPtr();
00192     colIds = columnIds_.getRawPtr();
00193     values = values_.getRawPtr();
00194   }
00195 
00196 
00197   int getNumWeightsPerRow() const { return numWeightsPerRow_; }
00198 
00199   void getRowWeightsView(const scalar_t *&weights, int &stride,
00200                            int idx = 0) const
00201   {
00202     env_->localInputAssertion(__FILE__, __LINE__,
00203       "invalid weight index",
00204       idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
00205     size_t length;
00206     rowWeights_[idx].getStridedList(length, weights, stride);
00207   }
00208 
00209   bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
00210 
00211   template <typename Adapter>
00212     void applyPartitioningSolution(const User &in, User *&out,
00213          const PartitioningSolution<Adapter> &solution) const;
00214 
00215 private:
00216 
00217   RCP<Environment> env_;    // for error messages, etc.
00218 
00219   RCP<const User> inmatrix_;
00220   RCP<const xmatrix_t> matrix_;
00221   RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
00222   RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
00223   lno_t base_;
00224   ArrayRCP<lno_t> offset_;
00225   ArrayRCP<gno_t> columnIds_;  // TODO:  KDD Is it necessary to copy and store
00226   ArrayRCP<scalar_t> values_;  // TODO:  the matrix here?  Would prefer views.
00227 
00228   int numWeightsPerRow_;
00229   ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
00230   ArrayRCP<bool> numNzWeight_;
00231 
00232   bool mayHaveDiagonalEntries;
00233 };
00234 
00236 // Definitions
00238 
00239 template <typename User, typename UserCoord>
00240   XpetraCrsMatrixAdapter<User,UserCoord>::XpetraCrsMatrixAdapter(
00241     const RCP<const User> &inmatrix, int numWeightsPerRow):
00242       env_(rcp(new Environment)),
00243       inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(), base_(),
00244       offset_(), columnIds_(),
00245       numWeightsPerRow_(numWeightsPerRow), rowWeights_(), numNzWeight_(),
00246       mayHaveDiagonalEntries(true)
00247 {
00248   typedef StridedData<lno_t,scalar_t> input_t;
00249   matrix_ = XpetraTraits<User>::convertToXpetra(inmatrix);
00250   rowMap_ = matrix_->getRowMap();
00251   colMap_ = matrix_->getColMap();
00252   base_ = rowMap_->getIndexBase();
00253 
00254   size_t nrows = matrix_->getNodeNumRows();
00255   size_t nnz = matrix_->getNodeNumEntries();
00256  
00257   offset_.resize(nrows+1, 0);
00258   columnIds_.resize(nnz);
00259   values_.resize(nnz);
00260   ArrayView<const lno_t> indices;
00261   ArrayView<const scalar_t> nzs;
00262   lno_t next = 0;
00263 //TODO WE ARE COPYING THE MATRIX HERE.  IS THERE A WAY TO USE VIEWS?
00264 //TODO THEY ARE AVAILABLE IN EPETRA; ARE THEY AVAIL IN TPETRA AND XPETRA?
00265   for (size_t i=0; i < nrows; i++){
00266     lno_t row = i + base_;
00267     nnz = matrix_->getNumEntriesInLocalRow(row);
00268     matrix_->getLocalRowView(row, indices, nzs);
00269     for (size_t j=0; j < nnz; j++){
00270       values_[next] = nzs[j];
00271       // TODO - this will be slow
00272       //   Is it possible that global columns ids might be stored in order?
00273       columnIds_[next++] = colMap_->getGlobalElement(indices[j]);
00274     }
00275     offset_[i+1] = offset_[i] + nnz;
00276   } 
00277 
00278   if (numWeightsPerRow_ > 0){
00279     rowWeights_ = arcp(new input_t [numWeightsPerRow_], 0, numWeightsPerRow_, true);
00280     numNzWeight_ = arcp(new bool [numWeightsPerRow_], 0, numWeightsPerRow_, true);
00281     for (int i=0; i < numWeightsPerRow_; i++)
00282       numNzWeight_[i] = false;
00283   }
00284 }
00285 
00287 template <typename User, typename UserCoord>
00288   void XpetraCrsMatrixAdapter<User,UserCoord>::setWeights(
00289     const scalar_t *weightVal, int stride, int idx)
00290 {
00291   if (this->getPrimaryEntityType() == MATRIX_ROW)
00292     setRowWeights(weightVal, stride, idx);
00293   else {
00294     // TODO:  Need to allow weights for columns and/or nonzeros
00295     std::ostringstream emsg;
00296     emsg << __FILE__ << "," << __LINE__
00297          << " error:  setWeights not yet supported for"
00298          << " columns or nonzeros."
00299          << std::endl;
00300     throw std::runtime_error(emsg.str());
00301   }
00302 }
00303 
00305 template <typename User, typename UserCoord>
00306   void XpetraCrsMatrixAdapter<User,UserCoord>::setRowWeights(
00307     const scalar_t *weightVal, int stride, int idx)
00308 {
00309   typedef StridedData<lno_t,scalar_t> input_t;
00310   env_->localInputAssertion(__FILE__, __LINE__,
00311     "invalid row weight index",
00312     idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
00313   size_t nvtx = getLocalNumRows();
00314   ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
00315   rowWeights_[idx] = input_t(weightV, stride);
00316 }
00317 
00319 template <typename User, typename UserCoord>
00320   void XpetraCrsMatrixAdapter<User,UserCoord>::setWeightIsDegree(
00321     int idx)
00322 {
00323   if (this->getPrimaryEntityType() == MATRIX_ROW)
00324     setRowWeightIsNumberOfNonZeros(idx);
00325   else {
00326     // TODO:  Need to allow weights for columns and/or nonzeros
00327     std::ostringstream emsg;
00328     emsg << __FILE__ << "," << __LINE__
00329          << " error:  setWeightIsNumberOfNonZeros not yet supported for"
00330          << " columns" << std::endl;
00331     throw std::runtime_error(emsg.str());
00332   }
00333 }
00334 
00336 template <typename User, typename UserCoord>
00337   void XpetraCrsMatrixAdapter<User,UserCoord>::setRowWeightIsNumberOfNonZeros(
00338     int idx)
00339 {
00340   env_->localInputAssertion(__FILE__, __LINE__,
00341     "invalid row weight index",
00342     idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
00343 
00344   numNzWeight_[idx] = true;
00345 }
00346 
00348 template <typename User, typename UserCoord>
00349   template <typename Adapter>
00350     void XpetraCrsMatrixAdapter<User,UserCoord>::applyPartitioningSolution(
00351       const User &in, User *&out, 
00352       const PartitioningSolution<Adapter> &solution) const
00353 { 
00354   // Get an import list
00355 
00356   size_t len = solution.getLocalNumberOfIds();
00357   const zgid_t *gids = solution.getIdList();
00358   const part_t *parts = solution.getPartList();
00359   ArrayRCP<zgid_t> gidList = arcp(const_cast<zgid_t *>(gids), 0, len, false); 
00360   ArrayRCP<part_t> partList = arcp(const_cast<part_t *>(parts), 0, len, 
00361     false); 
00362   ArrayRCP<lno_t> dummyIn;
00363   ArrayRCP<zgid_t> importList;
00364   ArrayRCP<lno_t> dummyOut;
00365   size_t numNewRows;
00366   const RCP<const Comm<int> > comm = matrix_->getRowMap()->getComm();
00367 
00368   try{
00369     numNewRows = solution.convertSolutionToImportList(
00370       0, dummyIn, importList, dummyOut);
00371   }
00372   Z2_FORWARD_EXCEPTIONS;
00373 
00374   RCP<const User> inPtr = rcp(&in, false);
00375 
00376   RCP<const User> outPtr = XpetraTraits<User>::doMigration(
00377    inPtr, numNewRows, importList.getRawPtr());
00378 
00379   out = const_cast<User *>(outPtr.get());
00380   outPtr.release();
00381 }
00382 
00383 }  //namespace Zoltan2
00384   
00385 #endif