Zoltan2
Loading...
Searching...
No Matches
Zoltan2_XpetraCrsMatrixAdapter.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
14#ifndef _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
15#define _ZOLTAN2_XPETRACRSMATRIXADAPTER_HPP_
16
21
22#include <Xpetra_CrsMatrix.hpp>
23
24#include <iostream>
25#include <cassert>
26
27namespace Zoltan2 {
28
30
52template <typename User, typename UserCoord=User>
53 class XpetraCrsMatrixAdapter : public MatrixAdapter<User, UserCoord> {
54public:
55
56#ifndef DOXYGEN_SHOULD_SKIP_THIS
58 using lno_t = typename InputTraits<User>::lno_t;
59 using gno_t = typename InputTraits<User>::gno_t;
60 using part_t = typename InputTraits<User>::part_t;
61 using node_t = typename InputTraits<User>::node_t;
63 using xmatrix_t = Xpetra::CrsMatrix<scalar_t, lno_t, gno_t, node_t>;
64
65 using userCoord_t = UserCoord;
66 using user_t = User;
67#endif
68
72
78 XpetraCrsMatrixAdapter(const RCP<const User> &inmatrix,
79 int nWeightsPerRow=0);
80
93 void setWeights(const scalar_t *weightVal, int stride, int idx = 0);
94
110 void setRowWeights(const scalar_t *weightVal, int stride, int idx = 0);
111
117 void setWeightIsDegree(int idx);
118
124 void setRowWeightIsNumberOfNonZeros(int idx);
125
127 // The MatrixAdapter interface.
129
130 size_t getLocalNumRows() const {
131 return matrix_->getLocalNumRows();
132 }
133
134 size_t getLocalNumColumns() const {
135 return matrix_->getLocalNumCols();
136 }
137
138 size_t getLocalNumEntries() const {
139 return matrix_->getLocalNumEntries();
140 }
141
142 void getRowIDsView(const gno_t *&rowIds) const
143 {
144 ArrayView<const gno_t> rowView = rowMap_->getLocalElementList();
145 rowIds = rowView.getRawPtr();
146 }
147
148 void getColumnIDsView(const gno_t *&colIds) const
149 {
150 ArrayView<const gno_t> colView = colMap_->getLocalElementList();
151 colIds = colView.getRawPtr();
152 }
153
154 void getCRSView(ArrayRCP<const offset_t> &offsets, ArrayRCP<const gno_t> &colIds) const
155 {
156 ArrayRCP< const lno_t > localColumnIds;
157 ArrayRCP<const scalar_t> values;
158 matrix_->getAllValues(offsets,localColumnIds,values);
159 colIds = columnIds_;
160 }
161
162 bool CRSViewAvailable() const { return true; }
163
164 void getCRSView(ArrayRCP<const offset_t> &offsets,
165 ArrayRCP<const gno_t> &colIds,
166 ArrayRCP<const scalar_t> &values) const {
167 ArrayRCP< const lno_t > localColumnIds;
168 matrix_->getAllValues(offsets,localColumnIds,values);
169 colIds = columnIds_;
170 }
171
172 void getCCSView(ArrayRCP<const offset_t> &offsets,
173 ArrayRCP<const gno_t> &rowIds) const override {
174 ArrayRCP<const offset_t> crsOffsets;
175 ArrayRCP<const lno_t> crsLocalColumnIds;
176 ArrayRCP<const scalar_t> values;
177 matrix_->getAllValues(crsOffsets, crsLocalColumnIds, values);
178
179 const auto localRowIds = rowMap_->getLocalElementList();
180 const auto numLocalCols = colMap_->getLocalNumElements();
181
182 // Lambda used to compute local row based on column index from CRS view
183 auto determineRow = [&crsOffsets, &localRowIds](const int columnIdx) {
184 int curLocalRow = 0;
185 for (int rowIdx = 0; rowIdx < localRowIds.size(); ++rowIdx) {
186 if (rowIdx < (localRowIds.size() - 1)) {
187 if (static_cast<offset_t>(columnIdx) < crsOffsets[rowIdx + 1]) {
188 return curLocalRow;
189 }
190 ++curLocalRow;
191 } else {
192 return curLocalRow;
193 }
194 }
195
196 return -1;
197 };
198
199 // Vector of global rows per each local column
200 std::vector<std::vector<gno_t>> rowIDsPerCol(numLocalCols);
201
202 for (int colIdx = 0; colIdx < crsLocalColumnIds.size(); ++colIdx) {
203 const auto colID = crsLocalColumnIds[colIdx];
204 const auto globalRow = rowMap_->getGlobalElement(determineRow(colIdx));
205
206 rowIDsPerCol[colID].push_back(globalRow);
207 }
208
209 size_t offsetWrite = 0;
210 ArrayRCP<gno_t> ccsRowIds(values.size());
211 ArrayRCP<offset_t> ccsOffsets(colMap_->getLocalNumElements() + 1);
212
213 ccsOffsets[0] = 0;
214 for (int64_t colID = 1; colID < ccsOffsets.size(); ++colID) {
215 const auto &rowIDs = rowIDsPerCol[colID - 1];
216
217 if (not rowIDs.empty()) {
218 std::copy(rowIDs.begin(), rowIDs.end(),
219 ccsRowIds.begin() + offsetWrite);
220 offsetWrite += rowIDs.size();
221 }
222
223 ccsOffsets[colID] = offsetWrite;
224 }
225
226 ccsOffsets[numLocalCols] = crsLocalColumnIds.size();
227
228 rowIds = ccsRowIds;
229 offsets = ccsOffsets;
230 }
231
232 int getNumWeightsPerRow() const { return nWeightsPerRow_; }
233
234 void getRowWeightsView(const scalar_t *&weights, int &stride,
235 int idx = 0) const
236 {
237 if(idx<0 || idx >= nWeightsPerRow_)
238 {
239 std::ostringstream emsg;
240 emsg << __FILE__ << ":" << __LINE__
241 << " Invalid row weight index " << idx << std::endl;
242 throw std::runtime_error(emsg.str());
243 }
244
245 size_t length;
246 rowWeights_[idx].getStridedList(length, weights, stride);
247 }
248
249 bool useNumNonzerosAsRowWeight(int idx) const { return numNzWeight_[idx];}
250
251 template <typename Adapter>
252 void applyPartitioningSolution(const User &in, User *&out,
253 const PartitioningSolution<Adapter> &solution) const;
254
255 template <typename Adapter>
256 void applyPartitioningSolution(const User &in, RCP<User> &out,
257 const PartitioningSolution<Adapter> &solution) const;
258
259private:
260
261 RCP<const User> inmatrix_;
262 RCP<const xmatrix_t> matrix_;
263 RCP<const Xpetra::Map<lno_t, gno_t, node_t> > rowMap_;
264 RCP<const Xpetra::Map<lno_t, gno_t, node_t> > colMap_;
265 lno_t base_;
266 ArrayRCP<gno_t> columnIds_; // TODO: Refactor adapter to localColumnIds_
267
268 int nWeightsPerRow_;
269 ArrayRCP<StridedData<lno_t, scalar_t> > rowWeights_;
270 ArrayRCP<bool> numNzWeight_;
271
272 bool mayHaveDiagonalEntries;
273};
274
276// Definitions
278
279template <typename User, typename UserCoord>
281 const RCP<const User> &inmatrix, int nWeightsPerRow):
282 inmatrix_(inmatrix), matrix_(), rowMap_(), colMap_(),
283 columnIds_(),
284 nWeightsPerRow_(nWeightsPerRow), rowWeights_(), numNzWeight_(),
285 mayHaveDiagonalEntries(true)
286{
287 typedef StridedData<lno_t,scalar_t> input_t;
288 try {
289 matrix_ = rcp_const_cast<const xmatrix_t>(
290 XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(inmatrix)));
291 }
293
294 rowMap_ = matrix_->getRowMap();
295 colMap_ = matrix_->getColMap();
296
297 size_t nrows = matrix_->getLocalNumRows();
298 size_t nnz = matrix_->getLocalNumEntries();
299
300 // Get ArrayRCP pointers to the structures in the underlying matrix
301 ArrayRCP< const offset_t > offset;
302 ArrayRCP< const lno_t > localColumnIds;
303 ArrayRCP< const scalar_t > values;
304 matrix_->getAllValues(offset,localColumnIds,values);
305 columnIds_.resize(nnz, 0);
306
307 for (offset_t i = 0; i < offset[nrows]; i++) {
308 columnIds_[i] = colMap_->getGlobalElement(localColumnIds[i]);
309 }
310
311 if (nWeightsPerRow_ > 0){
312 rowWeights_ = arcp(new input_t [nWeightsPerRow_], 0, nWeightsPerRow_, true);
313 numNzWeight_ = arcp(new bool [nWeightsPerRow_], 0, nWeightsPerRow_, true);
314 for (int i=0; i < nWeightsPerRow_; i++)
315 numNzWeight_[i] = false;
316 }
317}
318
320template <typename User, typename UserCoord>
322 const scalar_t *weightVal, int stride, int idx)
323{
324 if (this->getPrimaryEntityType() == MATRIX_ROW)
325 setRowWeights(weightVal, stride, idx);
326 else {
327 // TODO: Need to allow weights for columns and/or nonzeros
328 std::ostringstream emsg;
329 emsg << __FILE__ << "," << __LINE__
330 << " error: setWeights not yet supported for"
331 << " columns or nonzeros."
332 << std::endl;
333 throw std::runtime_error(emsg.str());
334 }
335}
336
338template <typename User, typename UserCoord>
340 const scalar_t *weightVal, int stride, int idx)
341{
342 typedef StridedData<lno_t,scalar_t> input_t;
343 if(idx<0 || idx >= nWeightsPerRow_)
344 {
345 std::ostringstream emsg;
346 emsg << __FILE__ << ":" << __LINE__
347 << " Invalid row weight index " << idx << std::endl;
348 throw std::runtime_error(emsg.str());
349 }
350
351 size_t nvtx = getLocalNumRows();
352 ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
353 rowWeights_[idx] = input_t(weightV, stride);
354}
355
357template <typename User, typename UserCoord>
359 int idx)
360{
361 if (this->getPrimaryEntityType() == MATRIX_ROW)
362 setRowWeightIsNumberOfNonZeros(idx);
363 else {
364 // TODO: Need to allow weights for columns and/or nonzeros
365 std::ostringstream emsg;
366 emsg << __FILE__ << "," << __LINE__
367 << " error: setWeightIsNumberOfNonZeros not yet supported for"
368 << " columns" << std::endl;
369 throw std::runtime_error(emsg.str());
370 }
371}
372
374template <typename User, typename UserCoord>
376 int idx)
377{
378 if(idx<0 || idx >= nWeightsPerRow_)
379 {
380 std::ostringstream emsg;
381 emsg << __FILE__ << ":" << __LINE__
382 << " Invalid row weight index " << idx << std::endl;
383 throw std::runtime_error(emsg.str());
384 }
385
386
387 numNzWeight_[idx] = true;
388}
389
391template <typename User, typename UserCoord>
392 template <typename Adapter>
394 const User &in, User *&out,
395 const PartitioningSolution<Adapter> &solution) const
396{
397 // Get an import list (rows to be received)
398 size_t numNewRows;
399 ArrayRCP<gno_t> importList;
400 try{
401 numNewRows = Zoltan2::getImportList<Adapter,
403 (solution, this, importList);
404 }
406
407 // Move the rows, creating a new matrix.
408 RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewRows,
409 importList.getRawPtr());
410 out = const_cast<User *>(outPtr.get());
411 outPtr.release();
412}
413
415template <typename User, typename UserCoord>
416 template <typename Adapter>
418 const User &in, RCP<User> &out,
419 const PartitioningSolution<Adapter> &solution) const
420{
421 // Get an import list (rows to be received)
422 size_t numNewRows;
423 ArrayRCP<gno_t> importList;
424 try{
425 numNewRows = Zoltan2::getImportList<Adapter,
427 (solution, this, importList);
428 }
430
431 // Move the rows, creating a new matrix.
432 out = XpetraTraits<User>::doMigration(in, numNewRows,
433 importList.getRawPtr());
434}
435
436} //namespace Zoltan2
437
438#endif
typename Zoltan2::InputTraits< ztcrsmatrix_t >::node_t node_t
Xpetra::CrsMatrix< zscalar_t, zlno_t, zgno_t, znode_t > xmatrix_t
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
Defines the MatrixAdapter interface.
Helper functions for Partitioning Problems.
This file defines the StridedData class.
Traits of Xpetra classes, including migration method.
typename InputTraits< User >::scalar_t scalar_t
typename InputTraits< User >::offset_t offset_t
typename InputTraits< User >::part_t part_t
MatrixAdapter defines the adapter interface for matrices.
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
bool CRSViewAvailable() const
Indicates whether the MatrixAdapter implements a view of the matrix in compressed sparse row (CRS) fo...
bool useNumNonzerosAsRowWeight(int idx) const
Indicate whether row weight with index idx should be the global number of nonzeros in the row.
void getCRSView(ArrayRCP< const offset_t > &offsets, ArrayRCP< const gno_t > &colIds) const
void getRowIDsView(const gno_t *&rowIds) const
size_t getLocalNumColumns() const
Returns the number of columns on this process.
void getCCSView(ArrayRCP< const offset_t > &offsets, ArrayRCP< const gno_t > &rowIds) const override
void getColumnIDsView(const gno_t *&colIds) const
size_t getLocalNumEntries() const
Returns the number of nonzeros on this process.
void setRowWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each row.
size_t getLocalNumRows() const
Returns the number of rows 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 setWeights(const scalar_t *weightVal, int stride, int idx=0)
Specify a weight for each entity of the primaryEntityType.
void getRowWeightsView(const scalar_t *&weights, int &stride, int idx=0) const
Provide a pointer to the row weights, if any.
void getCRSView(ArrayRCP< const offset_t > &offsets, ArrayRCP< const gno_t > &colIds, ArrayRCP< const scalar_t > &values) const
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
void setRowWeightIsNumberOfNonZeros(int idx)
Specify an index for which the row weight should be the global number of nonzeros in the row.
XpetraCrsMatrixAdapter(const RCP< const User > &inmatrix, int nWeightsPerRow=0)
Constructor.
map_t::local_ordinal_type lno_t
map_t::global_ordinal_type gno_t
Created by mbenlioglu on Aug 31, 2020.
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...
static ArrayRCP< ArrayRCP< zscalar_t > > weights
default_offset_t offset_t
The data type to represent offsets.
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.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices.
default_part_t part_t
The data type to represent part numbers.
default_scalar_t scalar_t
The data type for weights and coordinates.
Defines the traits required for Tpetra, Eptra and Xpetra objects.
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...