Zoltan2
Zoltan2_XpetraRowMatrixAdapter.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_XPETRAROWMATRIXADAPTER_HPP_
51 #define _ZOLTAN2_XPETRAROWMATRIXADAPTER_HPP_
52 
54 #include <Zoltan2_StridedData.hpp>
55 #include <Zoltan2_XpetraTraits.hpp>
57 
58 #include <Xpetra_RowMatrix.hpp>
59 
60 namespace Zoltan2 {
61 
63 
80 template <typename User, typename UserCoord=User>
81  class XpetraRowMatrixAdapter : public MatrixAdapter<User,UserCoord> {
82 public:
83 
84 #ifndef DOXYGEN_SHOULD_SKIP_THIS
85  typedef typename InputTraits<User>::scalar_t scalar_t;
86  typedef typename InputTraits<User>::lno_t lno_t;
87  typedef typename InputTraits<User>::gno_t gno_t;
88  typedef typename InputTraits<User>::part_t part_t;
89  typedef typename InputTraits<User>::node_t node_t;
90  typedef Xpetra::RowMatrix<scalar_t, lno_t, gno_t, node_t> xmatrix_t;
91  typedef MatrixAdapter<User,UserCoord> base_adapter_t;
92  typedef User user_t;
93  typedef UserCoord userCoord_t;
94 #endif
95 
99 
105  XpetraRowMatrixAdapter(const RCP<const User> &inmatrix,
106  int numWeightsPerRow=0);
107 
120  void setWeights(const scalar_t *weightVal, int stride, int idx = 0);
121 
137  void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0);
138 
144  void setWeightIsDegree(int idx);
145 
151  void setRowWeightIsNumberOfNonZeros(int idx);
152 
154  // The MatrixAdapter interface.
156 
157  size_t getLocalNumRows() const {
158  return matrix_->getNodeNumRows();
159  }
160 
161  size_t getLocalNumColumns() const {
162  return matrix_->getNodeNumCols();
163  }
164 
165  size_t getLocalNumEntries() const {
166  return matrix_->getNodeNumEntries();
167  }
168 
169  bool CRSViewAvailable() const { return true; }
170 
171  void getRowIDsView(const gno_t *&rowIds) const
172  {
173  ArrayView<const gno_t> rowView = rowMap_->getNodeElementList();
174  rowIds = rowView.getRawPtr();
175  }
176 
177  void getCRSView(const lno_t *&offsets, const gno_t *&colIds) const
178  {
179  offsets = offset_.getRawPtr();
180  colIds = columnIds_.getRawPtr();
181  }
182 
183  void getCRSView(const lno_t *&offsets, const gno_t *&colIds,
184  const scalar_t *&values) const
185  {
186  offsets = offset_.getRawPtr();
187  colIds = columnIds_.getRawPtr();
188  values = values_.getRawPtr();
189  }
190 
191 
192  int getNumWeightsPerRow() const { return nWeightsPerRow_; }
193 
194  void getRowWeightsView(const scalar_t *&weights, int &stride,
195  int idx = 0) const
196  {
197  env_->localInputAssertion(__FILE__, __LINE__,
198  "invalid weight index",
199  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
200  size_t length;
201  rowWeights_[idx].getStridedList(length, weights, stride);
202  }
203 
204  bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
205 
206  template <typename Adapter>
207  void applyPartitioningSolution(const User &in, User *&out,
208  const PartitioningSolution<Adapter> &solution) const;
209 
210  template <typename Adapter>
211  void applyPartitioningSolution(const User &in, RCP<User> &out,
212  const PartitioningSolution<Adapter> &solution) const;
213 
214 private:
215 
216  RCP<Environment> env_; // for error messages, etc.
217 
218  RCP<const User> inmatrix_;
219  RCP<const xmatrix_t> matrix_;
220  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
221  RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
222  lno_t base_;
223  ArrayRCP<lno_t> offset_;
224  ArrayRCP<gno_t> columnIds_; // TODO: KDD Is it necessary to copy and store
225  ArrayRCP<scalar_t> values_; // TODO: the matrix here? Would prefer views.
226 
227  int nWeightsPerRow_;
228  ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
229  ArrayRCP<bool> numNzWeight_;
230 
231  bool mayHaveDiagonalEntries;
232 };
233 
235 // Definitions
237 
238 template <typename User, typename UserCoord>
240  const RCP<const User> &inmatrix, int nWeightsPerRow):
241  env_(rcp(new Environment)),
242  inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(), base_(),
243  offset_(), columnIds_(),
244  nWeightsPerRow_(nWeightsPerRow), rowWeights_(), numNzWeight_(),
245  mayHaveDiagonalEntries(true)
246 {
247  typedef StridedData<lno_t,scalar_t> input_t;
248  matrix_ = rcp_const_cast<const xmatrix_t>(
249  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(inmatrix)));
250  rowMap_ = matrix_->getRowMap();
251  colMap_ = matrix_->getColMap();
252  base_ = rowMap_->getIndexBase();
253 
254  size_t nrows = matrix_->getNodeNumRows();
255  size_t nnz = matrix_->getNodeNumEntries();
256  size_t maxnumentries =
257  matrix_->getNodeMaxNumRowEntries(); // Diff from CrsMatrix
258 
259  offset_.resize(nrows+1, 0);
260  columnIds_.resize(nnz);
261  values_.resize(nnz);
262  ArrayRCP<lno_t> indices(maxnumentries); // Diff from CrsMatrix
263  ArrayRCP<scalar_t> nzs(maxnumentries); // Diff from CrsMatrix
264  lno_t next = 0;
265  for (size_t i=0; i < nrows; i++){
266  lno_t row = i + base_;
267  matrix_->getLocalRowCopy(row, indices(), nzs(), nnz); // Diff from CrsMatrix
268  for (size_t j=0; j < nnz; j++){
269  values_[next] = nzs[j];
270  // TODO - this will be slow
271  // Is it possible that global columns ids might be stored in order?
272  columnIds_[next++] = colMap_->getGlobalElement(indices[j]);
273  }
274  offset_[i+1] = offset_[i] + nnz;
275  }
276 
277  if (nWeightsPerRow_ > 0){
278  rowWeights_ = arcp(new input_t [nWeightsPerRow_], 0, nWeightsPerRow_, true);
279  numNzWeight_ = arcp(new bool [nWeightsPerRow_], 0, nWeightsPerRow_, true);
280  for (int i=0; i < nWeightsPerRow_; i++)
281  numNzWeight_[i] = false;
282  }
283 }
284 
286 template <typename User, typename UserCoord>
288  const scalar_t *weightVal, int stride, int idx)
289 {
290  if (this->getPrimaryEntityType() == MATRIX_ROW)
291  setRowWeights(weightVal, stride, idx);
292  else {
293  // TODO: Need to allow weights for columns and/or nonzeros
294  std::ostringstream emsg;
295  emsg << __FILE__ << "," << __LINE__
296  << " error: setWeights not yet supported for"
297  << " columns or nonzeros."
298  << std::endl;
299  throw std::runtime_error(emsg.str());
300  }
301 }
302 
304 template <typename User, typename UserCoord>
306  const scalar_t *weightVal, int stride, int idx)
307 {
308  typedef StridedData<lno_t,scalar_t> input_t;
309  env_->localInputAssertion(__FILE__, __LINE__,
310  "invalid row weight index",
311  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
312  size_t nvtx = getLocalNumRows();
313  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
314  rowWeights_[idx] = input_t(weightV, stride);
315 }
316 
318 template <typename User, typename UserCoord>
320  int idx)
321 {
322  if (this->getPrimaryEntityType() == MATRIX_ROW)
324  else {
325  // TODO: Need to allow weights for columns and/or nonzeros
326  std::ostringstream emsg;
327  emsg << __FILE__ << "," << __LINE__
328  << " error: setWeightIsNumberOfNonZeros not yet supported for"
329  << " columns" << std::endl;
330  throw std::runtime_error(emsg.str());
331  }
332 }
333 
335 template <typename User, typename UserCoord>
337  int idx)
338 {
339  env_->localInputAssertion(__FILE__, __LINE__,
340  "invalid row weight index",
341  idx >= 0 && idx < nWeightsPerRow_, BASIC_ASSERTION);
342 
343  numNzWeight_[idx] = true;
344 }
345 
347 template <typename User, typename UserCoord>
348  template <typename Adapter>
350  const User &in, User *&out,
351  const PartitioningSolution<Adapter> &solution) const
352 {
353  // Get an import list (rows to be received)
354  size_t numNewRows;
355  ArrayRCP<gno_t> importList;
356  try{
357  numNewRows = Zoltan2::getImportList<Adapter,
359  (solution, this, importList);
360  }
362 
363  // Move the rows, creating a new matrix.
364  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
365  importList.getRawPtr());
366  out = outPtr.get();
367  outPtr.release();
368 }
369 
371 template <typename User, typename UserCoord>
372  template <typename Adapter>
374  const User &in, RCP<User> &out,
375  const PartitioningSolution<Adapter> &solution) const
376 {
377  // Get an import list (rows to be received)
378  size_t numNewRows;
379  ArrayRCP<gno_t> importList;
380  try{
381  numNewRows = Zoltan2::getImportList<Adapter,
383  (solution, this, importList);
384  }
386 
387  // Move the rows, creating a new matrix.
388  out = XpetraTraits<User>::doMigration(in, numNewRows,
389  importList.getRawPtr());
390 }
391 
392 } //namespace Zoltan2
393 
394 #endif
InputTraits< User >::scalar_t scalar_t
size_t getLocalNumEntries() const
Returns the number of nonzeros on this process.
Helper functions for Partitioning Problems.
fast typical checks for valid arguments
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
MatrixAdapter defines the adapter interface for matrices.
InputTraits< User >::gno_t gno_t
XpetraRowMatrixAdapter(const RCP< const User > &inmatrix, int numWeightsPerRow=0)
Constructor.
void setWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each entity of the primaryEntityType.
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.
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...
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Traits of Xpetra classes, including migration method.
Provides access for Zoltan2 to Xpetra::RowMatrix data.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
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...
void getRowIDsView(const gno_t *&rowIds) const
Sets pointer to this process&#39; rows&#39; global IDs.
void getCRSView(const lno_t *&offsets, const gno_t *&colIds, const scalar_t *&values) const
A PartitioningSolution is a solution to a partitioning problem.
bool useNumNonzerosAsRowWeight(int idx) const
Indicate whether row weight with index idx 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_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.
default_node_t node_t
The Kokkos node type. This is only meaningful for users of Tpetra objects.
size_t getLocalNumRows() const
Returns the number of rows on this process.
Defines the MatrixAdapter interface.
void setRowWeightIsNumberOfNonZeros(int idx)
Specify an index for which the row weight should be the global number of nonzeros in the row...
size_t getLocalNumColumns() const
Returns the number of columns on this process.
int getNumWeightsPerRow() const
Returns the number of weights per row (0 or greater). Row weights may be used when partitioning matri...
void getRowWeightsView(const scalar_t *&weights, int &stride, int idx=0) const
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.
void setRowWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each 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