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 MatrixAdapter<User,UserCoord> base_adapter_t;
97  typedef User user_t;
98  typedef UserCoord userCoord_t;
99 #endif
100 
104 
110  XpetraCrsMatrixAdapter(const RCP<const User> &inmatrix,
111  int numWeightsPerRow=0);
112 
125  void setWeights(const scalar_t *weightVal, int stride, int idx = 0);
126 
142  void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0);
143 
149  void setWeightIsDegree(int idx);
150 
156  void setRowWeightIsNumberOfNonZeros(int idx);
157 
159  // The MatrixAdapter interface.
161 
162  size_t getLocalNumRows() const {
163  return matrix_->getNodeNumRows();
164  }
165 
166  size_t getLocalNumColumns() const {
167  return matrix_->getNodeNumCols();
168  }
169 
170  size_t getLocalNumEntries() const {
171  return matrix_->getNodeNumEntries();
172  }
173 
174  bool CRSViewAvailable() const { return true; }
175 
176  void getRowIDsView(const gno_t *&rowIds) const
177  {
178  ArrayView<const gno_t> rowView = rowMap_->getNodeElementList();
179  rowIds = rowView.getRawPtr();
180  }
181 
182  void getCRSView(const lno_t *&offsets, const gno_t *&colIds) const
183  {
184  offsets = offset_.getRawPtr();
185  colIds = columnIds_.getRawPtr();
186  }
187 
188  void getCRSView(const lno_t *&offsets, const gno_t *&colIds,
189  const scalar_t *&values) const
190  {
191  offsets = offset_.getRawPtr();
192  colIds = columnIds_.getRawPtr();
193  values = values_.getRawPtr();
194  }
195 
196 
197  int getNumWeightsPerRow() const { return numWeightsPerRow_; }
198 
199  void getRowWeightsView(const scalar_t *&weights, int &stride,
200  int idx = 0) const
201  {
202  env_->localInputAssertion(__FILE__, __LINE__,
203  "invalid weight index",
204  idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
205  size_t length;
206  rowWeights_[idx].getStridedList(length, weights, stride);
207  }
208 
209  bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
210 
211  template <typename Adapter>
212  void applyPartitioningSolution(const User &in, User *&out,
213  const PartitioningSolution<Adapter> &solution) const;
214 
215  template <typename Adapter>
216  void applyPartitioningSolution(const User &in, RCP<User> &out,
217  const PartitioningSolution<Adapter> &solution) const;
218 
219 private:
220 
221  RCP<Environment> env_; // for error messages, etc.
222 
223  RCP<const User> inmatrix_;
224  RCP<const xmatrix_t> matrix_;
225  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
226  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
227  lno_t base_;
228  ArrayRCP<lno_t> offset_;
229  ArrayRCP<gno_t> columnIds_; // TODO: KDD Is it necessary to copy and store
230  ArrayRCP<scalar_t> values_; // TODO: the matrix here? Would prefer views.
231 
232  int numWeightsPerRow_;
233  ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
234  ArrayRCP<bool> numNzWeight_;
235 
236  bool mayHaveDiagonalEntries;
237 };
238 
240 // Definitions
242 
243 template <typename User, typename UserCoord>
245  const RCP<const User> &inmatrix, int numWeightsPerRow):
246  env_(rcp(new Environment)),
247  inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(), base_(),
248  offset_(), columnIds_(),
249  numWeightsPerRow_(numWeightsPerRow), rowWeights_(), numNzWeight_(),
250  mayHaveDiagonalEntries(true)
251 {
252  typedef StridedData<lno_t,scalar_t> input_t;
253  matrix_ = rcp_const_cast<const xmatrix_t>(
254  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(inmatrix)));
255  rowMap_ = matrix_->getRowMap();
256  colMap_ = matrix_->getColMap();
257  base_ = rowMap_->getIndexBase();
258 
259  size_t nrows = matrix_->getNodeNumRows();
260  size_t nnz = matrix_->getNodeNumEntries();
261 
262  offset_.resize(nrows+1, 0);
263  columnIds_.resize(nnz);
264  values_.resize(nnz);
265  ArrayView<const lno_t> indices;
266  ArrayView<const scalar_t> nzs;
267  lno_t next = 0;
268 //TODO WE ARE COPYING THE MATRIX HERE. IS THERE A WAY TO USE VIEWS?
269 //TODO THEY ARE AVAILABLE IN EPETRA; ARE THEY AVAIL IN TPETRA AND XPETRA?
270  for (size_t i=0; i < nrows; i++){
271  lno_t row = i + base_;
272  nnz = matrix_->getNumEntriesInLocalRow(row);
273  matrix_->getLocalRowView(row, indices, nzs);
274  for (size_t j=0; j < nnz; j++){
275  values_[next] = nzs[j];
276  // TODO - this will be slow
277  // Is it possible that global columns ids might be stored in order?
278  columnIds_[next++] = colMap_->getGlobalElement(indices[j]);
279  }
280  offset_[i+1] = offset_[i] + nnz;
281  }
282 
283  if (numWeightsPerRow_ > 0){
284  rowWeights_ = arcp(new input_t [numWeightsPerRow_], 0, numWeightsPerRow_, true);
285  numNzWeight_ = arcp(new bool [numWeightsPerRow_], 0, numWeightsPerRow_, true);
286  for (int i=0; i < numWeightsPerRow_; i++)
287  numNzWeight_[i] = false;
288  }
289 }
290 
292 template <typename User, typename UserCoord>
294  const scalar_t *weightVal, int stride, int idx)
295 {
296  if (this->getPrimaryEntityType() == MATRIX_ROW)
297  setRowWeights(weightVal, stride, idx);
298  else {
299  // TODO: Need to allow weights for columns and/or nonzeros
300  std::ostringstream emsg;
301  emsg << __FILE__ << "," << __LINE__
302  << " error: setWeights not yet supported for"
303  << " columns or nonzeros."
304  << std::endl;
305  throw std::runtime_error(emsg.str());
306  }
307 }
308 
310 template <typename User, typename UserCoord>
312  const scalar_t *weightVal, int stride, int idx)
313 {
314  typedef StridedData<lno_t,scalar_t> input_t;
315  env_->localInputAssertion(__FILE__, __LINE__,
316  "invalid row weight index",
317  idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
318  size_t nvtx = getLocalNumRows();
319  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
320  rowWeights_[idx] = input_t(weightV, stride);
321 }
322 
324 template <typename User, typename UserCoord>
326  int idx)
327 {
328  if (this->getPrimaryEntityType() == MATRIX_ROW)
330  else {
331  // TODO: Need to allow weights for columns and/or nonzeros
332  std::ostringstream emsg;
333  emsg << __FILE__ << "," << __LINE__
334  << " error: setWeightIsNumberOfNonZeros not yet supported for"
335  << " columns" << std::endl;
336  throw std::runtime_error(emsg.str());
337  }
338 }
339 
341 template <typename User, typename UserCoord>
343  int idx)
344 {
345  env_->localInputAssertion(__FILE__, __LINE__,
346  "invalid row weight index",
347  idx >= 0 && idx < numWeightsPerRow_, BASIC_ASSERTION);
348 
349  numNzWeight_[idx] = true;
350 }
351 
353 template <typename User, typename UserCoord>
354  template <typename Adapter>
356  const User &in, User *&out,
357  const PartitioningSolution<Adapter> &solution) const
358 {
359  // Get an import list (rows to be received)
360  size_t numNewRows;
361  ArrayRCP<gno_t> importList;
362  try{
363  numNewRows = Zoltan2::getImportList<Adapter,
365  (solution, this, importList);
366  }
368 
369  // Move the rows, creating a new matrix.
370  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
371  importList.getRawPtr());
372  out = const_cast<User *>(outPtr.get());
373  outPtr.release();
374 }
375 
377 template <typename User, typename UserCoord>
378  template <typename Adapter>
380  const User &in, RCP<User> &out,
381  const PartitioningSolution<Adapter> &solution) const
382 {
383  // Get an import list (rows to be received)
384  size_t numNewRows;
385  ArrayRCP<gno_t> importList;
386  try{
387  numNewRows = Zoltan2::getImportList<Adapter,
389  (solution, this, importList);
390  }
392 
393  // Move the rows, creating a new matrix.
394  out = XpetraTraits<User>::doMigration(in, numNewRows,
395  importList.getRawPtr());
396 }
397 
398 } //namespace Zoltan2
399 
400 #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.
MatrixAdapter defines the adapter interface for matrices.
InputTraits< User >::gno_t gno_t
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
void getRowWeightsView(const scalar_t *&weights, int &stride, int idx=0) const
default_part_t part_t
The data type to represent part numbers.
Xpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > xmatrix_t
enum MatrixEntityType getPrimaryEntityType() const
Returns the entity to be partitioned, ordered, colored, etc. Valid values are MATRIX_ROW, MATRIX_COLUMN, MATRIX_NONZERO.
void getCRSView(const lno_t *&offsets, const gno_t *&colIds) const
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...
size_t getLocalNumColumns() const
Returns the number of columns on this process.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Traits of Xpetra classes, including migration method.
XpetraCrsMatrixAdapter(const RCP< const User > &inmatrix, int numWeightsPerRow=0)
Constructor.
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...
A PartitioningSolution is a solution to a partitioning problem.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
size_t getLocalNumRows() const
Returns the number of rows 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.
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.
size_t getLocalNumEntries() const
Returns the number of nonzeros on this process.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
void getCRSView(const lno_t *&offsets, const gno_t *&colIds, const scalar_t *&values) const
Defines the MatrixAdapter interface.
void setWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each entity of the primaryEntityType.
bool useNumNonzerosAsRowWeight(int idx) const
Indicate whether row weight with index idx should be the global number of nonzeros in the row...
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
void setRowWeightIsNumberOfNonZeros(int idx)
Specify an index for which the row weight should be the global number of nonzeros in the row...
bool CRSViewAvailable() const
Indicates whether the MatrixAdapter implements a view of the matrix in compressed sparse row (CRS) fo...
default_scalar_t scalar_t
The data type for weights and coordinates.
void getRowIDsView(const gno_t *&rowIds) const
This file defines the StridedData class.