Zoltan2
Zoltan2_XpetraCrsMatrixAdapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #ifndef _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
51 #define _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
52 
54 #include <Zoltan2_StridedData.hpp>
55 #include <Zoltan2_XpetraTraits.hpp>
57 
58 #include <Xpetra_CrsMatrix.hpp>
59 
60 namespace Zoltan2 {
61 
63 
85 template <typename User, typename UserCoord=User>
86  class XpetraCrsMatrixAdapter : public MatrixAdapter<User,UserCoord> {
87 public:
88 
89 #ifndef DOXYGEN_SHOULD_SKIP_THIS
90  typedef typename InputTraits<User>::scalar_t scalar_t;
91  typedef typename InputTraits<User>::lno_t lno_t;
92  typedef typename InputTraits<User>::gno_t gno_t;
93  typedef typename InputTraits<User>::part_t part_t;
94  typedef typename InputTraits<User>::node_t node_t;
95  typedef Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t> xmatrix_t;
96  typedef User user_t;
97  typedef UserCoord userCoord_t;
98 #endif
99 
103 
109  XpetraCrsMatrixAdapter(const RCP<const User> &inmatrix,
110  int nWeightsPerRow=0);
111 
124  void setWeights(const scalar_t *weightVal, int stride, int idx = 0);
125 
141  void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0);
142 
148  void setWeightIsDegree(int idx);
149 
155  void setRowWeightIsNumberOfNonZeros(int idx);
156 
158  // The MatrixAdapter interface.
160 
161  size_t getLocalNumRows() const {
162  return matrix_->getNodeNumRows();
163  }
164 
165  size_t getLocalNumColumns() const {
166  return matrix_->getNodeNumCols();
167  }
168 
169  size_t getLocalNumEntries() const {
170  return matrix_->getNodeNumEntries();
171  }
172 
173  bool CRSViewAvailable() const { return true; }
174 
175  void getRowIDsView(const gno_t *&rowIds) const
176  {
177  ArrayView<const gno_t> rowView = rowMap_->getNodeElementList();
178  rowIds = rowView.getRawPtr();
179  }
180 
181  void getCRSView(const lno_t *&offsets, const gno_t *&colIds) const
182  {
183  offsets = offset_.getRawPtr();
184  colIds = columnIds_.getRawPtr();
185  }
186 
187  void getCRSView(const lno_t *&offsets, const gno_t *&colIds,
188  const scalar_t *&values) const
189  {
190  offsets = offset_.getRawPtr();
191  colIds = columnIds_.getRawPtr();
192  values = values_.getRawPtr();
193  }
194 
195 
196  int getNumWeightsPerRow() const { return nWeightsPerRow_; }
197 
198  void getRowWeightsView(const scalar_t *&weights, int &stride,
199  int idx = 0) const
200  {
201  if(idx<0 || idx >= nWeightsPerRow_)
202  {
203  std::ostringstream emsg;
204  emsg << __FILE__ << ":" << __LINE__
205  << " Invalid row weight index " << idx << std::endl;
206  throw std::runtime_error(emsg.str());
207  }
208 
209  size_t length;
210  rowWeights_[idx].getStridedList(length, weights, stride);
211  }
212 
213  bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
214 
215  template <typename Adapter>
216  void applyPartitioningSolution(const User &in, User *&out,
217  const PartitioningSolution<Adapter> &solution) const;
218 
219  template <typename Adapter>
220  void applyPartitioningSolution(const User &in, RCP<User> &out,
221  const PartitioningSolution<Adapter> &solution) const;
222 
223 private:
224 
225  RCP<const User> inmatrix_;
226  RCP<const xmatrix_t> matrix_;
227  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
228  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
229  ArrayRCP<lno_t> offset_;
230  ArrayRCP<gno_t> columnIds_; // TODO: KDD Is it necessary to copy and store
231  ArrayRCP<scalar_t> values_; // TODO: the matrix here? Would prefer views.
232 
233  int nWeightsPerRow_;
234  ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
235  ArrayRCP<bool> numNzWeight_;
236 
237  bool mayHaveDiagonalEntries;
238 };
239 
241 // Definitions
243 
244 template <typename User, typename UserCoord>
246  const RCP<const User> &inmatrix, int nWeightsPerRow):
247  inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(),
248  offset_(), columnIds_(),
249  nWeightsPerRow_(nWeightsPerRow), rowWeights_(), numNzWeight_(),
250  mayHaveDiagonalEntries(true)
251 {
252  typedef StridedData<lno_t,scalar_t> input_t;
253  try {
254  matrix_ = rcp_const_cast<const xmatrix_t>(
255  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(inmatrix)));
256  }
258 
259  rowMap_ = matrix_->getRowMap();
260  colMap_ = matrix_->getColMap();
261 
262  size_t nrows = matrix_->getNodeNumRows();
263  size_t nnz = matrix_->getNodeNumEntries();
264 
265  offset_.resize(nrows+1, 0);
266  columnIds_.resize(nnz);
267  values_.resize(nnz);
268  ArrayView<const lno_t> indices;
269  ArrayView<const scalar_t> nzs;
270  lno_t next = 0;
271 //TODO WE ARE COPYING THE MATRIX HERE. IS THERE A WAY TO USE VIEWS?
272 //TODO THEY ARE AVAILABLE IN EPETRA; ARE THEY AVAIL IN TPETRA AND XPETRA?
273  for (size_t i=0; i < nrows; i++){
274  lno_t row = i;
275  nnz = matrix_->getNumEntriesInLocalRow(row);
276  matrix_->getLocalRowView(row, indices, nzs);
277  for (size_t j=0; j < nnz; j++){
278  values_[next] = nzs[j];
279  // TODO - this will be slow
280  // Is it possible that global columns ids might be stored in order?
281  columnIds_[next++] = colMap_->getGlobalElement(indices[j]);
282  }
283  offset_[i+1] = offset_[i] + nnz;
284  }
285 
286  if (nWeightsPerRow_ > 0){
287  rowWeights_ = arcp(new input_t [nWeightsPerRow_], 0, nWeightsPerRow_, true);
288  numNzWeight_ = arcp(new bool [nWeightsPerRow_], 0, nWeightsPerRow_, true);
289  for (int i=0; i < nWeightsPerRow_; i++)
290  numNzWeight_[i] = false;
291  }
292 }
293 
295 template <typename User, typename UserCoord>
297  const scalar_t *weightVal, int stride, int idx)
298 {
299  if (this->getPrimaryEntityType() == MATRIX_ROW)
300  setRowWeights(weightVal, stride, idx);
301  else {
302  // TODO: Need to allow weights for columns and/or nonzeros
303  std::ostringstream emsg;
304  emsg << __FILE__ << "," << __LINE__
305  << " error: setWeights not yet supported for"
306  << " columns or nonzeros."
307  << std::endl;
308  throw std::runtime_error(emsg.str());
309  }
310 }
311 
313 template <typename User, typename UserCoord>
315  const scalar_t *weightVal, int stride, int idx)
316 {
317  typedef StridedData<lno_t,scalar_t> input_t;
318  if(idx<0 || idx >= nWeightsPerRow_)
319  {
320  std::ostringstream emsg;
321  emsg << __FILE__ << ":" << __LINE__
322  << " Invalid row weight index " << idx << std::endl;
323  throw std::runtime_error(emsg.str());
324  }
325 
326  size_t nvtx = getLocalNumRows();
327  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
328  rowWeights_[idx] = input_t(weightV, stride);
329 }
330 
332 template <typename User, typename UserCoord>
334  int idx)
335 {
336  if (this->getPrimaryEntityType() == MATRIX_ROW)
338  else {
339  // TODO: Need to allow weights for columns and/or nonzeros
340  std::ostringstream emsg;
341  emsg << __FILE__ << "," << __LINE__
342  << " error: setWeightIsNumberOfNonZeros not yet supported for"
343  << " columns" << std::endl;
344  throw std::runtime_error(emsg.str());
345  }
346 }
347 
349 template <typename User, typename UserCoord>
351  int idx)
352 {
353  if(idx<0 || idx >= nWeightsPerRow_)
354  {
355  std::ostringstream emsg;
356  emsg << __FILE__ << ":" << __LINE__
357  << " Invalid row weight index " << idx << std::endl;
358  throw std::runtime_error(emsg.str());
359  }
360 
361 
362  numNzWeight_[idx] = true;
363 }
364 
366 template <typename User, typename UserCoord>
367  template <typename Adapter>
369  const User &in, User *&out,
370  const PartitioningSolution<Adapter> &solution) const
371 {
372  // Get an import list (rows to be received)
373  size_t numNewRows;
374  ArrayRCP<gno_t> importList;
375  try{
376  numNewRows = Zoltan2::getImportList<Adapter,
378  (solution, this, importList);
379  }
381 
382  // Move the rows, creating a new matrix.
383  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
384  importList.getRawPtr());
385  out = const_cast<User *>(outPtr.get());
386  outPtr.release();
387 }
388 
390 template <typename User, typename UserCoord>
391  template <typename Adapter>
393  const User &in, RCP<User> &out,
394  const PartitioningSolution<Adapter> &solution) const
395 {
396  // Get an import list (rows to be received)
397  size_t numNewRows;
398  ArrayRCP<gno_t> importList;
399  try{
400  numNewRows = Zoltan2::getImportList<Adapter,
402  (solution, this, importList);
403  }
405 
406  // Move the rows, creating a new matrix.
407  out = XpetraTraits<User>::doMigration(in, numNewRows,
408  importList.getRawPtr());
409 }
410 
411 } //namespace Zoltan2
412 
413 #endif
InputTraits< User >::scalar_t scalar_t
Helper functions for Partitioning Problems.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
void setRowWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each row.
void getRowWeightsView(const scalar_t *&weights, int &stride, int idx=0) const
MatrixAdapter defines the adapter interface for matrices.
InputTraits< User >::gno_t gno_t
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
size_t getLocalNumColumns() const
Returns the number of columns on this process.
default_part_t part_t
The data type to represent part numbers.
bool useNumNonzerosAsRowWeight(int idx) const
Indicate whether row weight with index idx should be the global number of nonzeros in the row...
Xpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > xmatrix_t
size_t getLocalNumRows() const
Returns the number of rows on this process.
InputTraits< User >::lno_t lno_t
static RCP< User > doMigration(const User &from, size_t numLocalRows, const gno_t *myNewRows)
Migrate the object Given a user object and a new row distribution, create and return a new user objec...
int getNumWeightsPerRow() const
Returns the number of weights per row (0 or greater). Row weights may be used when partitioning matri...
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Traits of Xpetra classes, including migration method.
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
size_t getImportList(const PartitioningSolution< SolutionAdapter > &solution, const DataAdapter *const data, ArrayRCP< typename DataAdapter::gno_t > &imports)
From a PartitioningSolution, get a list of IDs to be imported. Assumes part numbers in PartitioningSo...
bool CRSViewAvailable() const
Indicates whether the MatrixAdapter implements a view of the matrix in compressed sparse row (CRS) fo...
void getCRSView(const lno_t *&offsets, const gno_t *&colIds, const scalar_t *&values) const
A PartitioningSolution is a solution to a partitioning problem.
XpetraCrsMatrixAdapter(const RCP< const User > &inmatrix, int nWeightsPerRow=0)
Constructor.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
size_t getLocalNumEntries() const
Returns the number of nonzeros on this process.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices...
The StridedData class manages lists of weights or coordinates.
void getCRSView(const lno_t *&offsets, const gno_t *&colIds) const
Sets pointers to this process&#39; matrix entries using compressed sparse row (CRS) format. All matrix adapters must implement either getCRSView or getCCSView, but implementation of both is not required.
InputTraits< User >::part_t part_t
default_gno_t gno_t
The ordinal type (e.g., int, long, int64_t) that can represent global counts and identifiers.
void getRowIDsView(const gno_t *&rowIds) const
Sets pointer to this process&#39; rows&#39; global IDs.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
Defines the MatrixAdapter interface.
void setWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each entity of the primaryEntityType.
void setRowWeightIsNumberOfNonZeros(int idx)
Specify an index for which the row weight should be the global number of nonzeros in the row...
enum MatrixEntityType getPrimaryEntityType() const
Returns the entity to be partitioned, ordered, colored, etc. Valid values are MATRIX_ROW, MATRIX_COLUMN, MATRIX_NONZERO.
default_scalar_t scalar_t
The data type for weights and coordinates.
This file defines the StridedData class.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const