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 GraphAdapter<User,UserCoord> base_adapter_t;
96  typedef User user_t;
97  typedef UserCoord userCoord_t;
98 #endif
99 
103 
113  XpetraCrsGraphAdapter(const RCP<const User> &ingraph,
114  int nVtxWeights=0, int nEdgeWeights=0);
115 
128  void setWeights(const scalar_t *val, int stride, int idx);
129 
145  void setVertexWeights(const scalar_t *val, int stride, int idx);
146 
152  void setWeightIsDegree(int idx);
153 
159  void setVertexWeightIsDegree(int idx);
160 
183  void setEdgeWeights(const scalar_t *val, int stride, int idx);
184 
187  RCP<const xgraph_t> getXpetraGraph() const { return graph_; }
188 
191  RCP<const User> getUserGraph() const { return ingraph_; }
192 
194  // The Adapter interface.
196 
198  // The GraphAdapter interface.
200 
201  // TODO: Assuming rows == objects;
202  // TODO: Need to add option for columns or nonzeros?
203  size_t getLocalNumVertices() const { return graph_->getNodeNumRows(); }
204 
205  void getVertexIDsView(const gno_t *&ids) const
206  {
207  ids = NULL;
208  if (getLocalNumVertices())
209  ids = graph_->getRowMap()->getNodeElementList().getRawPtr();
210  }
211 
212  size_t getLocalNumEdges() const { return graph_->getNodeNumEntries(); }
213 
214  void getEdgesView(const lno_t *&offsets, const gno_t *&adjIds) const
215  {
216  offsets = offs_.getRawPtr();
217  adjIds = (getLocalNumEdges() ? adjids_.getRawPtr() : NULL);
218  }
219 
220  int getNumWeightsPerVertex() const { return nWeightsPerVertex_;}
221 
222  void getVertexWeightsView(const scalar_t *&weights, int &stride,
223  int idx) const
224  {
225  env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
226  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
227  size_t length;
228  vertexWeights_[idx].getStridedList(length, weights, stride);
229  }
230 
231  bool useDegreeAsVertexWeight(int idx) const {return vertexDegreeWeight_[idx];}
232 
233  int getNumWeightsPerEdge() const { return nWeightsPerEdge_;}
234 
235  void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
236  {
237  env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
238  idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION);
239  size_t length;
240  edgeWeights_[idx].getStridedList(length, weights, stride);
241  }
242 
243 
244  template <typename Adapter>
245  void applyPartitioningSolution(const User &in, User *&out,
246  const PartitioningSolution<Adapter> &solution) const;
247 
248  template <typename Adapter>
249  void applyPartitioningSolution(const User &in, RCP<User> &out,
250  const PartitioningSolution<Adapter> &solution) const;
251 
252 private:
253 
254  RCP<const User > ingraph_;
255  RCP<const xgraph_t > graph_;
256  RCP<const Comm<int> > comm_;
257 
258  ArrayRCP<const lno_t> offs_;
259  ArrayRCP<const gno_t> adjids_;
260 
261  int nWeightsPerVertex_;
262  ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_;
263  ArrayRCP<bool> vertexDegreeWeight_;
264 
265  int nWeightsPerEdge_;
266  ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_;
267 
268  int coordinateDim_;
269  ArrayRCP<StridedData<lno_t, scalar_t> > coords_;
270 
271  // A default Environment for error messages. User-written
272  // InputAdapter classes can use some other error return convention
273  // if desired.
274  RCP<const Environment> env_;
275 };
276 
278 // Definitions
280 
281 template <typename User, typename UserCoord>
283  const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts):
284  ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
285  nWeightsPerVertex_(nVtxWgts), vertexWeights_(), vertexDegreeWeight_(),
286  nWeightsPerEdge_(nEdgeWgts), edgeWeights_(),
287  coordinateDim_(0), coords_(),
288  env_(rcp(new Environment))
289 {
290  typedef StridedData<lno_t,scalar_t> input_t;
291 
292  graph_ = rcp_const_cast<const xgraph_t>(
293  XpetraTraits<User>::convertToXpetra(rcp_const_cast<User>(ingraph)));
294  comm_ = graph_->getComm();
295  size_t nvtx = graph_->getNodeNumRows();
296  size_t nedges = graph_->getNodeNumEntries();
297 
298  // Unfortunately we have to copy the offsets and edge Ids
299  // because edge Ids are not usually stored in vertex id order.
300 
301  size_t n = nvtx + 1;
302  lno_t *offs = new lno_t [n];
303  env_->localMemoryAssertion(__FILE__, __LINE__, n, offs);
304 
305  gno_t *adjids = NULL;
306  if (nedges){
307  adjids = new gno_t [nedges];
308  env_->localMemoryAssertion(__FILE__, __LINE__, nedges, adjids);
309  }
310 
311  offs[0] = 0;
312  for (size_t v=0; v < nvtx; v++){
313  ArrayView<const lno_t> nbors;
314  graph_->getLocalRowView(v, nbors);
315  offs[v+1] = offs[v] + nbors.size();
316  for (lno_t e=offs[v], i=0; e < offs[v+1]; e++)
317  adjids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]);
318  }
319 
320  offs_ = arcp(offs, 0, n, true);
321  adjids_ = arcp(adjids, 0, nedges, true);
322 
323  if (nWeightsPerVertex_ > 0) {
324  vertexWeights_ =
325  arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
326  vertexDegreeWeight_ =
327  arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
328  for (int i=0; i < nWeightsPerVertex_; i++)
329  vertexDegreeWeight_[i] = false;
330  }
331 
332  if (nWeightsPerEdge_ > 0)
333  edgeWeights_ = arcp(new input_t[nWeightsPerEdge_], 0, nWeightsPerEdge_, true);
334 }
335 
337 template <typename User, typename UserCoord>
339  const scalar_t *weightVal, int stride, int idx)
340 {
341  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
342  setVertexWeights(weightVal, stride, idx);
343  else
344  setEdgeWeights(weightVal, stride, idx);
345 }
346 
348 template <typename User, typename UserCoord>
350  const scalar_t *weightVal, int stride, int idx)
351 {
352  typedef StridedData<lno_t,scalar_t> input_t;
353  env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index",
354  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
355  size_t nvtx = getLocalNumVertices();
356  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false);
357  vertexWeights_[idx] = input_t(weightV, stride);
358 }
359 
361 template <typename User, typename UserCoord>
363  int idx)
364 {
365  if (this->getPrimaryEntityType() == GRAPH_VERTEX)
367  else {
368  std::ostringstream emsg;
369  emsg << __FILE__ << "," << __LINE__
370  << " error: setWeightIsNumberOfNonZeros is supported only for"
371  << " vertices" << std::endl;
372  throw std::runtime_error(emsg.str());
373  }
374 }
375 
377 template <typename User, typename UserCoord>
379  int idx)
380 {
381  env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index",
382  idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION);
383 
384  vertexDegreeWeight_[idx] = true;
385 }
386 
388 template <typename User, typename UserCoord>
390  const scalar_t *weightVal, int stride, int idx)
391 {
392  typedef StridedData<lno_t,scalar_t> input_t;
393  env_->localInputAssertion(__FILE__, __LINE__, "invalid edge weight index",
394  idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION);
395  size_t nedges = getLocalNumEdges();
396  ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges*stride, false);
397  edgeWeights_[idx] = input_t(weightV, stride);
398 }
399 
401 template <typename User, typename UserCoord>
402  template<typename Adapter>
404  const User &in, User *&out,
405  const PartitioningSolution<Adapter> &solution) const
406 {
407  // Get an import list (rows to be received)
408  size_t numNewVtx;
409  ArrayRCP<gno_t> importList;
410  try{
411  numNewVtx = Zoltan2::getImportList<Adapter,
413  (solution, this, importList);
414  }
416 
417  // Move the rows, creating a new graph.
418  RCP<User> outPtr = XpetraTraits<User>::doMigration(in, numNewVtx,
419  importList.getRawPtr());
420  out = outPtr.get();
421  outPtr.release();
422 }
423 
425 template <typename User, typename UserCoord>
426  template<typename Adapter>
428  const User &in, RCP<User> &out,
429  const PartitioningSolution<Adapter> &solution) const
430 {
431  // Get an import list (rows to be received)
432  size_t numNewVtx;
433  ArrayRCP<gno_t> importList;
434  try{
435  numNewVtx = Zoltan2::getImportList<Adapter,
437  (solution, this, importList);
438  }
440 
441  // Move the rows, creating a new graph.
442  out = XpetraTraits<User>::doMigration(in, numNewVtx,
443  importList.getRawPtr());
444 }
445 
446 } //namespace Zoltan2
447 
448 #endif
InputTraits< User >::scalar_t scalar_t
bool useDegreeAsVertexWeight(int idx) const
Indicate whether vertex weight with index idx should be the global degree of the vertex.
Helper functions for Partitioning Problems.
RCP< const xgraph_t > getXpetraGraph() const
Access to Xpetra-wrapped user&#39;s graph.
fast typical checks for valid arguments
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
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.
default_part_t part_t
The data type to represent part numbers.
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
Xpetra::CrsGraph< zlno_t, zgno_t, znode_t > xgraph_t
Traits of Xpetra classes, including migration method.
int getNumWeightsPerEdge() const
Returns the number (0 or greater) of edge weights.
RCP< const User > getUserGraph() const
Access to user&#39;s graph.
static RCP< User > convertToXpetra(const RCP< User > &a)
Convert the object to its Xpetra wrapped version.
size_t getLocalNumEdges() const
Returns the number of edges on this process.
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.
int getNumWeightsPerVertex() const
Returns the number (0 or greater) of weights per vertex.
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.
void getEdgesView(const lno_t *&offsets, const gno_t *&adjIds) const
Gets adjacency lists for all vertices in a compressed sparse row (CSR) format.
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 getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
void getVertexIDsView(const gno_t *&ids) const
Sets pointers to this process&#39; graph entries.
enum GraphEntityType getPrimaryEntityType() const
Returns the entity to be partitioned, ordered, colored, etc. Valid values are GRAPH_VERTEX or GRAPH_E...
Defines the GraphAdapter interface.
void getVertexWeightsView(const scalar_t *&weights, int &stride, int idx) const
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.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
default_scalar_t scalar_t
The data type for weights and coordinates.
This file defines the StridedData class.
size_t getLocalNumVertices() const
Returns the number of vertices on this process.