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)
332  setRowWeightIsNumberOfNonZeros(idx);
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...
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