|
Zoltan2
|
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
1.7.6.1