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  env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
225  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
226  size_t length;
227  vertexWeights_[idx].getStridedList(length, weights, stride);
228  }
229 
230  bool useDegreeAsVertexWeight(int idx) const {return vertexDegreeWeight_[idx];}
231 
232  int getNumWeightsPerEdge() const { return nWeightsPerEdge_;}
233 
234  void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
235  {
236  env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
237  idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION);
238  size_t length;
239  edgeWeights_[idx].getStridedList(length, weights, stride);
240  }
241 
242 
243  template <typename Adapter>
244  void applyPartitioningSolution(const User &in, User *&out,
245  const PartitioningSolution<Adapter> &solution) const;
246 
247  template <typename Adapter>
248  void applyPartitioningSolution(const User &in, RCP<User> &out,
249  const PartitioningSolution<Adapter> &solution) const;
250 
251 private:
252 
253  RCP<const User > ingraph_;
254  RCP<const xgraph_t > graph_;
255  RCP<const Comm<int> > comm_;
256 
257  ArrayRCP<const lno_t> offs_;
258  ArrayRCP<const gno_t> adjids_;
259 
260  int nWeightsPerVertex_;
261  ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_;
262  ArrayRCP<bool> vertexDegreeWeight_;
263 
264  int nWeightsPerEdge_;
265  ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_;
266 
267  int coordinateDim_;
268  ArrayRCP<StridedData<lno_t, scalar_t> > coords_;
269 
270  // A default Environment for error messages. User-written
271  // InputAdapter classes can use some other error return convention
272  // if desired.
273  RCP<const Environment> env_;
274 };
275 
277 // Definitions
279 
280 template <typename User, typename UserCoord>
282  const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts):
283  ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
284  nWeightsPerVertex_(nVtxWgts), vertexWeights_(), vertexDegreeWeight_(),
285  nWeightsPerEdge_(nEdgeWgts), edgeWeights_(),
286  coordinateDim_(0), coords_(),
287  env_(rcp(new Environment))
288 {
289  typedef StridedData<lno_t,scalar_t> input_t;
290 
291  try {
292  graph_ = rcp_const_cast<const xgraph_t>(
293  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(ingraph)));
294  }
296 
297  comm_ = graph_->getComm();
298  size_t nvtx = graph_->getNodeNumRows();
299  size_t nedges = graph_->getNodeNumEntries();
300 
301  // Unfortunately we have to copy the offsets and edge Ids
302  // because edge Ids are not usually stored in vertex id order.
303 
304  size_t n = nvtx + 1;
305  lno_t *offs = new lno_t [n];
306  env_->localMemoryAssertion(__FILE__, __LINE__, n, offs);
307 
308  gno_t *adjids = NULL;
309  if (nedges){
310  adjids = new gno_t [nedges];
311  env_->localMemoryAssertion(__FILE__, __LINE__, nedges, adjids);
312  }
313 
314  offs[0] = 0;
315  for (size_t v=0; v < nvtx; v++){
316  ArrayView<const lno_t> nbors;
317  graph_->getLocalRowView(v, nbors);
318  offs[v+1] = offs[v] + nbors.size();
319  for (lno_t e=offs[v], i=0; e < offs[v+1]; e++)
320  adjids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]);
321  }
322 
323  offs_ = arcp(offs, 0, n, true);
324  adjids_ = arcp(adjids, 0, nedges, true);
325 
326  if (nWeightsPerVertex_ > 0) {
327  vertexWeights_ =
328  arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
329  vertexDegreeWeight_ =
330  arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
331  for (int i=0; i < nWeightsPerVertex_; i++)
332  vertexDegreeWeight_[i] = false;
333  }
334 
335  if (nWeightsPerEdge_ > 0)
336  edgeWeights_ = arcp(new input_t[nWeightsPerEdge_], 0, nWeightsPerEdge_, true);
337 }
338 
340 template <typename User, typename UserCoord>
342  const scalar_t *weightVal, int stride, int idx)
343 {
344  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
345  setVertexWeights(weightVal, stride, idx);
346  else
347  setEdgeWeights(weightVal, stride, idx);
348 }
349 
351 template <typename User, typename UserCoord>
353  const scalar_t *weightVal, int stride, int idx)
354 {
355  typedef StridedData<lno_t,scalar_t> input_t;
356  env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index",
357  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
358  size_t nvtx = getLocalNumVertices();
359  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
360  vertexWeights_[idx] = input_t(weightV, stride);
361 }
362 
364 template <typename User, typename UserCoord>
366  int idx)
367 {
368  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
369  setVertexWeightIsDegree(idx);
370  else {
371  std::ostringstream emsg;
372  emsg << __FILE__ << "," << __LINE__
373  << " error: setWeightIsNumberOfNonZeros is supported only for"
374  << " vertices" << std::endl;
375  throw std::runtime_error(emsg.str());
376  }
377 }
378 
380 template <typename User, typename UserCoord>
382  int idx)
383 {
384  env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index",
385  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
386 
387  vertexDegreeWeight_[idx] = true;
388 }
389 
391 template <typename User, typename UserCoord>
393  const scalar_t *weightVal, int stride, int idx)
394 {
395  typedef StridedData<lno_t,scalar_t> input_t;
396  env_->localInputAssertion(__FILE__, __LINE__, "invalid edge weight index",
397  idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION);
398  size_t nedges = getLocalNumEdges();
399  ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges*stride, false);
400  edgeWeights_[idx] = input_t(weightV, stride);
401 }
402 
404 template <typename User, typename UserCoord>
405  template<typename Adapter>
407  const User &in, User *&out,
408  const PartitioningSolution<Adapter> &solution) const
409 {
410  // Get an import list (rows to be received)
411  size_t numNewVtx;
412  ArrayRCP<gno_t> importList;
413  try{
414  numNewVtx = Zoltan2::getImportList<Adapter,
416  (solution, this, importList);
417  }
419 
420  // Move the rows, creating a new graph.
421  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewVtx,
422  importList.getRawPtr());
423  out = outPtr.get();
424  outPtr.release();
425 }
426 
428 template <typename User, typename UserCoord>
429  template<typename Adapter>
431  const User &in, RCP<User> &out,
432  const PartitioningSolution<Adapter> &solution) const
433 {
434  // Get an import list (rows to be received)
435  size_t numNewVtx;
436  ArrayRCP<gno_t> importList;
437  try{
438  numNewVtx = Zoltan2::getImportList<Adapter,
440  (solution, this, importList);
441  }
443 
444  // Move the rows, creating a new graph.
445  out = XpetraTraits<User>::doMigration(in, numNewVtx,
446  importList.getRawPtr());
447 }
448 
449 } //namespace Zoltan2
450 
451 #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.
fast typical checks for valid arguments
#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
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.
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
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.