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  env_->localInputAssertion(__FILE__, __LINE__,
202  "invalid weight index",
203  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
204  size_t length;
205  rowWeights_[idx].getStridedList(length, weights, stride);
206  }
207 
208  bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
209 
210  template <typename Adapter>
211  void applyPartitioningSolution(const User &in, User *&out,
212  const PartitioningSolution<Adapter> &solution) const;
213 
214  template <typename Adapter>
215  void applyPartitioningSolution(const User &in, RCP<User> &out,
216  const PartitioningSolution<Adapter> &solution) const;
217 
218 private:
219 
220  RCP<Environment> env_; // for error messages, etc.
221 
222  RCP<const User> inmatrix_;
223  RCP<const xmatrix_t> matrix_;
224  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
225  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
226  lno_t base_;
227  ArrayRCP<lno_t> offset_;
228  ArrayRCP<gno_t> columnIds_; // TODO: KDD Is it necessary to copy and store
229  ArrayRCP<scalar_t> values_; // TODO: the matrix here? Would prefer views.
230 
231  int nWeightsPerRow_;
232  ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
233  ArrayRCP<bool> numNzWeight_;
234 
235  bool mayHaveDiagonalEntries;
236 };
237 
239 // Definitions
241 
242 template <typename User, typename UserCoord>
244  const RCP<const User> &inmatrix, int nWeightsPerRow):
245  env_(rcp(new Environment)),
246  inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(), base_(),
247  offset_(), columnIds_(),
248  nWeightsPerRow_(nWeightsPerRow), rowWeights_(), numNzWeight_(),
249  mayHaveDiagonalEntries(true)
250 {
251  typedef StridedData<lno_t,scalar_t> input_t;
252  try {
253  matrix_ = rcp_const_cast<const xmatrix_t>(
254  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(inmatrix)));
255  }
257 
258  rowMap_ = matrix_->getRowMap();
259  colMap_ = matrix_->getColMap();
260  base_ = rowMap_->getIndexBase();
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 + base_;
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  env_->localInputAssertion(__FILE__, __LINE__,
319  "invalid row weight index",
320  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
321  size_t nvtx = getLocalNumRows();
322  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
323  rowWeights_[idx] = input_t(weightV, stride);
324 }
325 
327 template <typename User, typename UserCoord>
329  int idx)
330 {
331  if (this->getPrimaryEntityType() == MATRIX_ROW)
333  else {
334  // TODO: Need to allow weights for columns and/or nonzeros
335  std::ostringstream emsg;
336  emsg << __FILE__ << "," << __LINE__
337  << " error: setWeightIsNumberOfNonZeros not yet supported for"
338  << " columns" << std::endl;
339  throw std::runtime_error(emsg.str());
340  }
341 }
342 
344 template <typename User, typename UserCoord>
346  int idx)
347 {
348  env_->localInputAssertion(__FILE__, __LINE__,
349  "invalid row weight index",
350  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
351 
352  numNzWeight_[idx] = true;
353 }
354 
356 template <typename User, typename UserCoord>
357  template <typename Adapter>
359  const User &in, User *&out,
360  const PartitioningSolution<Adapter> &solution) const
361 {
362  // Get an import list (rows to be received)
363  size_t numNewRows;
364  ArrayRCP<gno_t> importList;
365  try{
366  numNewRows = Zoltan2::getImportList<Adapter,
368  (solution, this, importList);
369  }
371 
372  // Move the rows, creating a new matrix.
373  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
374  importList.getRawPtr());
375  out = const_cast<User *>(outPtr.get());
376  outPtr.release();
377 }
378 
380 template <typename User, typename UserCoord>
381  template <typename Adapter>
383  const User &in, RCP<User> &out,
384  const PartitioningSolution<Adapter> &solution) const
385 {
386  // Get an import list (rows to be received)
387  size_t numNewRows;
388  ArrayRCP<gno_t> importList;
389  try{
390  numNewRows = Zoltan2::getImportList<Adapter,
392  (solution, this, importList);
393  }
395 
396  // Move the rows, creating a new matrix.
397  out = XpetraTraits<User>::doMigration(in, numNewRows,
398  importList.getRawPtr());
399 }
400 
401 } //namespace Zoltan2
402 
403 #endif
InputTraits< User >::scalar_t scalar_t
Helper functions for Partitioning Problems.
fast typical checks for valid arguments
#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
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
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