|
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_XPETRAROWMATRIXADAPTER_HPP_ 00051 #define _ZOLTAN2_XPETRAROWMATRIXADAPTER_HPP_ 00052 00053 #include <Zoltan2_MatrixAdapter.hpp> 00054 #include <Zoltan2_StridedData.hpp> 00055 #include <Zoltan2_XpetraTraits.hpp> 00056 00057 #include <Xpetra_RowMatrix.hpp> 00058 00059 namespace Zoltan2 { 00060 00062 00079 template <typename User, typename UserCoord=User> 00080 class XpetraRowMatrixAdapter : public MatrixAdapter<User,UserCoord> { 00081 public: 00082 00083 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00084 typedef typename InputTraits<User>::scalar_t scalar_t; 00085 typedef typename InputTraits<User>::lno_t lno_t; 00086 typedef typename InputTraits<User>::gno_t gno_t; 00087 typedef typename InputTraits<User>::zgid_t zgid_t; 00088 typedef typename InputTraits<User>::part_t part_t; 00089 typedef typename InputTraits<User>::node_t node_t; 00090 typedef Xpetra::RowMatrix<scalar_t, lno_t, gno_t, node_t> xmatrix_t; 00091 typedef MatrixAdapter<User,UserCoord> base_adapter_t; 00092 typedef User user_t; 00093 typedef UserCoord userCoord_t; 00094 #endif 00095 00098 ~XpetraRowMatrixAdapter() { } 00099 00105 XpetraRowMatrixAdapter(const RCP<const User> &inmatrix, 00106 int numWeightsPerRow=0); 00107 00120 void setWeights(const scalar_t *weightVal, int stride, int idx = 0); 00121 00137 void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0); 00138 00144 void setWeightIsDegree(int idx); 00145 00151 void setRowWeightIsNumberOfNonZeros(int idx); 00152 00154 // The MatrixAdapter interface. 00156 00157 size_t getLocalNumRows() const { 00158 return matrix_->getNodeNumRows(); 00159 } 00160 00161 size_t getLocalNumColumns() const { 00162 return matrix_->getNodeNumCols(); 00163 } 00164 00165 size_t getLocalNumEntries() const { 00166 return matrix_->getNodeNumEntries(); 00167 } 00168 00169 bool CRSViewAvailable() const { return true; } 00170 00171 void getRowIDsView(const zgid_t *&rowIds) const 00172 { 00173 ArrayView<const zgid_t> rowView = rowMap_->getNodeElementList(); 00174 rowIds = rowView.getRawPtr(); 00175 } 00176 00177 void getCRSView(const lno_t *&offsets, const zgid_t *&colIds) const 00178 { 00179 offsets = offset_.getRawPtr(); 00180 colIds = columnIds_.getRawPtr(); 00181 } 00182 00183 void getCRSView(const lno_t *&offsets, const zgid_t *&colIds, 00184 const scalar_t *&values) const 00185 { 00186 offsets = offset_.getRawPtr(); 00187 colIds = columnIds_.getRawPtr(); 00188 values = values_.getRawPtr(); 00189 } 00190 00191 00192 int getNumWeightsPerRow() const { return nWeightsPerRow_; } 00193 00194 void getRowWeightsView(const scalar_t *&weights, int &stride, 00195 int idx = 0) const 00196 { 00197 env_->localInputAssertion(__FILE__, __LINE__, 00198 "invalid weight index", 00199 idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION); 00200 size_t length; 00201 rowWeights_[idx].getStridedList(length, weights, stride); 00202 } 00203 00204 bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];} 00205 00206 template <typename Adapter> 00207 void applyPartitioningSolution(const User &in, User *&out, 00208 const PartitioningSolution<Adapter> &solution) const; 00209 00210 private: 00211 00212 RCP<Environment> env_; // for error messages, etc. 00213 00214 RCP<const User> inmatrix_; 00215 RCP<const xmatrix_t> matrix_; 00216 RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_; 00217 RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_; 00218 lno_t base_; 00219 ArrayRCP<lno_t> offset_; 00220 ArrayRCP<gno_t> columnIds_; // TODO: KDD Is it necessary to copy and store 00221 ArrayRCP<scalar_t> values_; // TODO: the matrix here? Would prefer views. 00222 00223 int nWeightsPerRow_; 00224 ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_; 00225 ArrayRCP<bool> numNzWeight_; 00226 00227 bool mayHaveDiagonalEntries; 00228 }; 00229 00231 // Definitions 00233 00234 template <typename User, typename UserCoord> 00235 XpetraRowMatrixAdapter<User,UserCoord>::XpetraRowMatrixAdapter( 00236 const RCP<const User> &inmatrix, int nWeightsPerRow): 00237 env_(rcp(new Environment)), 00238 inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(), base_(), 00239 offset_(), columnIds_(), 00240 nWeightsPerRow_(nWeightsPerRow), rowWeights_(), numNzWeight_(), 00241 mayHaveDiagonalEntries(true) 00242 { 00243 typedef StridedData<lno_t,scalar_t> input_t; 00244 matrix_ = XpetraTraits<User>::convertToXpetra(inmatrix); 00245 rowMap_ = matrix_->getRowMap(); 00246 colMap_ = matrix_->getColMap(); 00247 base_ = rowMap_->getIndexBase(); 00248 00249 size_t nrows = matrix_->getNodeNumRows(); 00250 size_t nnz = matrix_->getNodeNumEntries(); 00251 size_t maxnumentries = 00252 matrix_->getNodeMaxNumRowEntries(); // Diff from CrsMatrix 00253 00254 offset_.resize(nrows+1, 0); 00255 columnIds_.resize(nnz); 00256 values_.resize(nnz); 00257 ArrayRCP<lno_t> indices(maxnumentries); // Diff from CrsMatrix 00258 ArrayRCP<scalar_t> nzs(maxnumentries); // Diff from CrsMatrix 00259 lno_t next = 0; 00260 for (size_t i=0; i < nrows; i++){ 00261 lno_t row = i + base_; 00262 matrix_->getLocalRowCopy(row, indices(), nzs(), nnz); // Diff from CrsMatrix 00263 for (size_t j=0; j < nnz; j++){ 00264 values_[next] = nzs[j]; 00265 // TODO - this will be slow 00266 // Is it possible that global columns ids might be stored in order? 00267 columnIds_[next++] = colMap_->getGlobalElement(indices[j]); 00268 } 00269 offset_[i+1] = offset_[i] + nnz; 00270 } 00271 00272 if (nWeightsPerRow_ > 0){ 00273 rowWeights_ = arcp(new input_t [nWeightsPerRow_], 0, nWeightsPerRow_, true); 00274 numNzWeight_ = arcp(new bool [nWeightsPerRow_], 0, nWeightsPerRow_, true); 00275 for (int i=0; i < nWeightsPerRow_; i++) 00276 numNzWeight_[i] = false; 00277 } 00278 } 00279 00281 template <typename User, typename UserCoord> 00282 void XpetraRowMatrixAdapter<User,UserCoord>::setWeights( 00283 const scalar_t *weightVal, int stride, int idx) 00284 { 00285 if (this->getPrimaryEntityType() == MATRIX_ROW) 00286 setRowWeights(weightVal, stride, idx); 00287 else { 00288 // TODO: Need to allow weights for columns and/or nonzeros 00289 std::ostringstream emsg; 00290 emsg << __FILE__ << "," << __LINE__ 00291 << " error: setWeights not yet supported for" 00292 << " columns or nonzeros." 00293 << std::endl; 00294 throw std::runtime_error(emsg.str()); 00295 } 00296 } 00297 00299 template <typename User, typename UserCoord> 00300 void XpetraRowMatrixAdapter<User,UserCoord>::setRowWeights( 00301 const scalar_t *weightVal, int stride, int idx) 00302 { 00303 typedef StridedData<lno_t,scalar_t> input_t; 00304 env_->localInputAssertion(__FILE__, __LINE__, 00305 "invalid row weight index", 00306 idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION); 00307 size_t nvtx = getLocalNumRows(); 00308 ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false); 00309 rowWeights_[idx] = input_t(weightV, stride); 00310 } 00311 00313 template <typename User, typename UserCoord> 00314 void XpetraRowMatrixAdapter<User,UserCoord>::setWeightIsDegree( 00315 int idx) 00316 { 00317 if (this->getPrimaryEntityType() == MATRIX_ROW) 00318 setRowWeightIsNumberOfNonZeros(idx); 00319 else { 00320 // TODO: Need to allow weights for columns and/or nonzeros 00321 std::ostringstream emsg; 00322 emsg << __FILE__ << "," << __LINE__ 00323 << " error: setWeightIsNumberOfNonZeros not yet supported for" 00324 << " columns" << std::endl; 00325 throw std::runtime_error(emsg.str()); 00326 } 00327 } 00328 00330 template <typename User, typename UserCoord> 00331 void XpetraRowMatrixAdapter<User,UserCoord>::setRowWeightIsNumberOfNonZeros( 00332 int idx) 00333 { 00334 env_->localInputAssertion(__FILE__, __LINE__, 00335 "invalid row weight index", 00336 idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION); 00337 00338 numNzWeight_[idx] = true; 00339 } 00340 00342 template <typename User, typename UserCoord> 00343 template <typename Adapter> 00344 void XpetraRowMatrixAdapter<User,UserCoord>::applyPartitioningSolution( 00345 const User &in, User *&out, 00346 const PartitioningSolution<Adapter> &solution) const 00347 { 00348 // Get an import list 00349 00350 size_t len = solution.getLocalNumberOfIds(); 00351 const zgid_t *gids = solution.getIdList(); 00352 const part_t *parts = solution.getPartList(); 00353 ArrayRCP<zgid_t> gidList = arcp(const_cast<zgid_t *>(gids), 0, len, false); 00354 ArrayRCP<part_t> partList = arcp(const_cast<part_t *>(parts), 0, len, 00355 false); 00356 ArrayRCP<lno_t> dummyIn; 00357 ArrayRCP<zgid_t> importList; 00358 ArrayRCP<lno_t> dummyOut; 00359 size_t numNewRows; 00360 const RCP<const Comm<int> > comm = matrix_->getRowMap()->getComm(); 00361 00362 try{ 00363 numNewRows = solution.convertSolutionToImportList( 00364 0, dummyIn, importList, dummyOut); 00365 } 00366 Z2_FORWARD_EXCEPTIONS; 00367 00368 RCP<const User> inPtr = rcp(&in, false); 00369 00370 RCP<const User> outPtr = XpetraTraits<User>::doMigration( 00371 inPtr, numNewRows, importList.getRawPtr()); 00372 00373 out = const_cast<User *>(outPtr.get()); 00374 outPtr.release(); 00375 } 00376 00377 } //namespace Zoltan2 00378 00379 #endif
1.7.6.1