Zoltan2
Zoltan2_XpetraCrsGraphAdapter.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_XPETRACRSGRAPHADAPTER_HPP_
51 #define _ZOLTAN2_XPETRACRSGRAPHADAPTER_HPP_
52 
53 #include <Zoltan2_GraphAdapter.hpp>
54 #include <Zoltan2_StridedData.hpp>
55 #include <Zoltan2_XpetraTraits.hpp>
57 
58 #include <Xpetra_CrsGraph.hpp>
59 
60 namespace Zoltan2 {
61 
83 template <typename User, typename UserCoord=User>
84  class XpetraCrsGraphAdapter : public GraphAdapter<User,UserCoord> {
85 
86 public:
87 
88 #ifndef DOXYGEN_SHOULD_SKIP_THIS
89  typedef typename InputTraits<User>::scalar_t scalar_t;
90  typedef typename InputTraits<User>::lno_t lno_t;
91  typedef typename InputTraits<User>::gno_t gno_t;
92  typedef typename InputTraits<User>::part_t part_t;
93  typedef typename InputTraits<User>::node_t node_t;
94  typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> xgraph_t;
95  typedef User user_t;
96  typedef UserCoord userCoord_t;
97 #endif
98 
102 
112  XpetraCrsGraphAdapter(const RCP<const User> &ingraph,
113  int nVtxWeights=0, int nEdgeWeights=0);
114 
127  void setWeights(const scalar_t *val, int stride, int idx);
128 
144  void setVertexWeights(const scalar_t *val, int stride, int idx);
145 
151  void setWeightIsDegree(int idx);
152 
158  void setVertexWeightIsDegree(int idx);
159 
182  void setEdgeWeights(const scalar_t *val, int stride, int idx);
183 
186  RCP<const xgraph_t> getXpetraGraph() const { return graph_; }
187 
190  RCP<const User> getUserGraph() const { return ingraph_; }
191 
193  // The Adapter interface.
195 
197  // The GraphAdapter interface.
199 
200  // TODO: Assuming rows == objects;
201  // TODO: Need to add option for columns or nonzeros?
202  size_t getLocalNumVertices() const { return graph_->getNodeNumRows(); }
203 
204  void getVertexIDsView(const gno_t *&ids) const
205  {
206  ids = NULL;
207  if (getLocalNumVertices())
208  ids = graph_->getRowMap()->getNodeElementList().getRawPtr();
209  }
210 
211  size_t getLocalNumEdges() const { return graph_->getNodeNumEntries(); }
212 
213  void getEdgesView(const lno_t *&offsets, const gno_t *&adjIds) const
214  {
215  offsets = offs_.getRawPtr();
216  adjIds = (getLocalNumEdges() ? adjids_.getRawPtr() : NULL);
217  }
218 
219  int getNumWeightsPerVertex() const { return nWeightsPerVertex_;}
220 
221  void getVertexWeightsView(const scalar_t *&weights, int &stride,
222  int idx) const
223  {
224  if(idx<0 || idx >= nWeightsPerVertex_)
225  {
226  std::ostringstream emsg;
227  emsg << __FILE__ << ":" << __LINE__
228  << " Invalid vertex weight index " << idx << std::endl;
229  throw std::runtime_error(emsg.str());
230  }
231 
232 
233  size_t length;
234  vertexWeights_[idx].getStridedList(length, weights, stride);
235  }
236 
237  bool useDegreeAsVertexWeight(int idx) const {return vertexDegreeWeight_[idx];}
238 
239  int getNumWeightsPerEdge() const { return nWeightsPerEdge_;}
240 
241  void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
242  {
243  if(idx<0 || idx >= nWeightsPerEdge_)
244  {
245  std::ostringstream emsg;
246  emsg << __FILE__ << ":" << __LINE__
247  << " Invalid edge weight index " << idx << std::endl;
248  throw std::runtime_error(emsg.str());
249  }
250 
251 
252  size_t length;
253  edgeWeights_[idx].getStridedList(length, weights, stride);
254  }
255 
256 
257  template <typename Adapter>
258  void applyPartitioningSolution(const User &in, User *&out,
259  const PartitioningSolution<Adapter> &solution) const;
260 
261  template <typename Adapter>
262  void applyPartitioningSolution(const User &in, RCP<User> &out,
263  const PartitioningSolution<Adapter> &solution) const;
264 
265 private:
266 
267  RCP<const User > ingraph_;
268  RCP<const xgraph_t > graph_;
269  RCP<const Comm<int> > comm_;
270 
271  ArrayRCP<const lno_t> offs_;
272  ArrayRCP<const gno_t> adjids_;
273 
274  int nWeightsPerVertex_;
275  ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_;
276  ArrayRCP<bool> vertexDegreeWeight_;
277 
278  int nWeightsPerEdge_;
279  ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_;
280 
281  int coordinateDim_;
282  ArrayRCP<StridedData<lno_t, scalar_t> > coords_;
283 
284 };
285 
287 // Definitions
289 
290 template <typename User, typename UserCoord>
292  const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts):
293  ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
294  nWeightsPerVertex_(nVtxWgts), vertexWeights_(), vertexDegreeWeight_(),
295  nWeightsPerEdge_(nEdgeWgts), edgeWeights_(),
296  coordinateDim_(0), coords_()
297 {
298  typedef StridedData<lno_t,scalar_t> input_t;
299 
300  try {
301  graph_ = rcp_const_cast<const xgraph_t>(
302  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(ingraph)));
303  }
305 
306  comm_ = graph_->getComm();
307  size_t nvtx = graph_->getNodeNumRows();
308  size_t nedges = graph_->getNodeNumEntries();
309 
310  // Unfortunately we have to copy the offsets and edge Ids
311  // because edge Ids are not usually stored in vertex id order.
312 
313  size_t n = nvtx + 1;
314  lno_t *offs = new lno_t [n];
315 
316  if (!offs)
317  {
318  std::cerr << "Error: " << __FILE__ << ", " << __LINE__<< std::endl;
319  std::cerr << n << " objects" << std::endl;
320  throw std::bad_alloc();
321  }
322 
323  gno_t *adjids = NULL;
324  if (nedges)
325  {
326  adjids = new gno_t [nedges];
327 
328  if (!adjids)
329  {
330  std::cerr << "Error: " << __FILE__ << ", " << __LINE__<< std::endl;
331  std::cerr << nedges << " objects" << std::endl;
332  throw std::bad_alloc();
333  }
334  }
335 
336  offs[0] = 0;
337  for (size_t v=0; v < nvtx; v++){
338  ArrayView<const lno_t> nbors;
339  graph_->getLocalRowView(v, nbors);
340  offs[v+1] = offs[v] + nbors.size();
341  for (lno_t e=offs[v], i=0; e < offs[v+1]; e++)
342  adjids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]);
343  }
344 
345  offs_ = arcp(offs, 0, n, true);
346  adjids_ = arcp(adjids, 0, nedges, true);
347 
348  if (nWeightsPerVertex_ > 0) {
349  vertexWeights_ =
350  arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
351  vertexDegreeWeight_ =
352  arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
353  for (int i=0; i < nWeightsPerVertex_; i++)
354  vertexDegreeWeight_[i] = false;
355  }
356 
357  if (nWeightsPerEdge_ > 0)
358  edgeWeights_ = arcp(new input_t[nWeightsPerEdge_], 0, nWeightsPerEdge_, true);
359 }
360 
362 template <typename User, typename UserCoord>
364  const scalar_t *weightVal, int stride, int idx)
365 {
366  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
367  setVertexWeights(weightVal, stride, idx);
368  else
369  setEdgeWeights(weightVal, stride, idx);
370 }
371 
373 template <typename User, typename UserCoord>
375  const scalar_t *weightVal, int stride, int idx)
376 {
377  typedef StridedData<lno_t,scalar_t> input_t;
378 
379  if(idx<0 || idx >= nWeightsPerVertex_)
380  {
381  std::ostringstream emsg;
382  emsg << __FILE__ << ":" << __LINE__
383  << " Invalid vertex weight index " << idx << std::endl;
384  throw std::runtime_error(emsg.str());
385  }
386 
387  size_t nvtx = getLocalNumVertices();
388  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
389  vertexWeights_[idx] = input_t(weightV, stride);
390 }
391 
393 template <typename User, typename UserCoord>
395  int idx)
396 {
397  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
399  else {
400  std::ostringstream emsg;
401  emsg << __FILE__ << "," << __LINE__
402  << " error: setWeightIsNumberOfNonZeros is supported only for"
403  << " vertices" << std::endl;
404  throw std::runtime_error(emsg.str());
405  }
406 }
407 
409 template <typename User, typename UserCoord>
411  int idx)
412 {
413  if(idx<0 || idx >= nWeightsPerVertex_)
414  {
415  std::ostringstream emsg;
416  emsg << __FILE__ << ":" << __LINE__
417  << " Invalid vertex weight index " << idx << std::endl;
418  throw std::runtime_error(emsg.str());
419  }
420 
421  vertexDegreeWeight_[idx] = true;
422 }
423 
425 template <typename User, typename UserCoord>
427  const scalar_t *weightVal, int stride, int idx)
428 {
429  typedef StridedData<lno_t,scalar_t> input_t;
430 
431  if(idx<0 || idx >= nWeightsPerEdge_)
432  {
433  std::ostringstream emsg;
434  emsg << __FILE__ << ":" << __LINE__
435  << " Invalid edge weight index " << idx << std::endl;
436  throw std::runtime_error(emsg.str());
437  }
438 
439  size_t nedges = getLocalNumEdges();
440  ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges*stride, false);
441  edgeWeights_[idx] = input_t(weightV, stride);
442 }
443 
445 template <typename User, typename UserCoord>
446  template<typename Adapter>
448  const User &in, User *&out,
449  const PartitioningSolution<Adapter> &solution) const
450 {
451  // Get an import list (rows to be received)
452  size_t numNewVtx;
453  ArrayRCP<gno_t> importList;
454  try{
455  numNewVtx = Zoltan2::getImportList<Adapter,
457  (solution, this, importList);
458  }
460 
461  // Move the rows, creating a new graph.
462  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewVtx,
463  importList.getRawPtr());
464  out = outPtr.get();
465  outPtr.release();
466 }
467 
469 template <typename User, typename UserCoord>
470  template<typename Adapter>
472  const User &in, RCP<User> &out,
473  const PartitioningSolution<Adapter> &solution) const
474 {
475  // Get an import list (rows to be received)
476  size_t numNewVtx;
477  ArrayRCP<gno_t> importList;
478  try{
479  numNewVtx = Zoltan2::getImportList<Adapter,
481  (solution, this, importList);
482  }
484 
485  // Move the rows, creating a new graph.
486  out = XpetraTraits<User>::doMigration(in, numNewVtx,
487  importList.getRawPtr());
488 }
489 
490 } //namespace Zoltan2
491 
492 #endif
int getNumWeightsPerEdge() const
Returns the number (0 or greater) of edge weights.
void getVertexIDsView(const gno_t *&ids) const
Sets pointers to this process&#39; graph entries.
InputTraits< User >::scalar_t scalar_t
Helper functions for Partitioning Problems.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
bool useDegreeAsVertexWeight(int idx) const
Indicate whether vertex weight with index idx should be the global degree of the vertex.
InputTraits< User >::gno_t gno_t
GraphAdapter defines the interface for graph-based user data.
void setWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to weights for the primary entity type.
RCP< const xgraph_t > getXpetraGraph() const
Access to Xpetra-wrapped user&#39;s graph.
default_part_t part_t
The data type to represent part numbers.
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...
Provides access for Zoltan2 to Xpetra::CrsGraph data.
static ArrayRCP< ArrayRCP< zscalar_t > > weights
size_t getLocalNumEdges() const
Returns the number of edges on this process.
Xpetra::CrsGraph< zlno_t, zgno_t, znode_t > xgraph_t
Traits of Xpetra classes, including migration method.
RCP< const User > getUserGraph() const
Access to user&#39;s graph.
size_t getLocalNumVertices() const
Returns the number of vertices on this process.
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
int getNumWeightsPerVertex() const
Returns the number (0 or greater) of weights per vertex.
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...
XpetraCrsGraphAdapter(const RCP< const User > &ingraph, int nVtxWeights=0, int nEdgeWeights=0)
Constructor for graph with no weights or coordinates.
A PartitioningSolution is a solution to a partitioning problem.
default_lno_t lno_t
The ordinal type (e.g., int, long, int64_t) that represents local counts and local indices...
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
The StridedData class manages lists of weights or coordinates.
InputTraits< User >::part_t part_t
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.
void setEdgeWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to edge weights.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
enum GraphEntityType getPrimaryEntityType() const
Returns the entity to be partitioned, ordered, colored, etc. Valid values are GRAPH_VERTEX or GRAPH_E...
void getVertexWeightsView(const scalar_t *&weights, int &stride, int idx) const
void getEdgesView(const lno_t *&offsets, const gno_t *&adjIds) const
Gets adjacency lists for all vertices in a compressed sparse row (CSR) format.
Defines the GraphAdapter interface.
void setVertexWeightIsDegree(int idx)
Specify an index for which the vertex weight should be the degree of the vertex.
void setVertexWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to vertex weights.
default_scalar_t scalar_t
The data type for weights and coordinates.
void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
This file defines the StridedData class.