MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_Zoltan2GraphAdapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
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
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef MUELU_ZOLTAN2GRAPHADAPTER_HPP_
48 #define MUELU_ZOLTAN2GRAPHADAPTER_HPP_
49 
50 #include "MueLu_ConfigDefs.hpp"
51 
52 #if defined(HAVE_MUELU_ZOLTAN2)
53 
54 #include <Teuchos_RCP.hpp>
55 #include <Teuchos_Comm.hpp>
56 #include <Teuchos_ArrayView.hpp>
57 #include <Xpetra_Map.hpp>
58 #include <Zoltan2_InputTraits.hpp>
59 #include <Zoltan2_GraphAdapter.hpp>
60 #include <Zoltan2_StridedData.hpp>
61 #include <Zoltan2_PartitioningSolution.hpp>
62 #include "MueLu_LWGraph.hpp"
63 
64 // Zoltab2 InputTraits for MueLu Graph objects
65 namespace Zoltan2 {
66 
67 template <typename LocalOrdinal,
68  typename GlobalOrdinal,
69  typename Node>
70 struct InputTraits<MueLu::LWGraph<LocalOrdinal, GlobalOrdinal, Node> > {
71  typedef Zoltan2::default_scalar_t scalar_t;
74  typedef size_t offset_t;
75  typedef Zoltan2::default_part_t part_t;
76  typedef Node node_t;
77  static inline std::string name() { return "MueLu::Graph"; }
78 
79  Z2_STATIC_ASSERT_TYPES // validate the types
80 };
81 } // end namespace Zoltan2
82 
83 namespace MueLu {
84 
85 template <typename User, typename UserCoord = User>
86 class MueLuGraphBaseAdapter : public Zoltan2::GraphAdapter<User, UserCoord> {
87  public:
88 #ifndef DOXYGEN_SHOULD_SKIP_THIS
89  typedef typename Zoltan2::InputTraits<User>::scalar_t scalar_t;
90  typedef typename Zoltan2::InputTraits<User>::offset_t offset_t;
91  typedef typename Zoltan2::InputTraits<User>::lno_t lno_t;
92  typedef typename Zoltan2::InputTraits<User>::gno_t gno_t;
93  typedef typename Zoltan2::InputTraits<User>::part_t part_t;
94  typedef typename Zoltan2::InputTraits<User>::node_t node_t;
95  typedef User xgraph_t;
96  typedef User user_t;
97  typedef UserCoord userCoord_t;
98 #endif
99 
101  const Teuchos::RCP<const Teuchos::Comm<int> > getComm() const { return graph_->GetComm(); }
102  const Teuchos::RCP<const Xpetra::Map<lno_t, gno_t, node_t> > getRowMap() const { return graph_->GetDomainMap(); }
104  // For some GraphBases' this is a ColMap, in others it is a seperate map that is
105  // only non-null in parallel.
107  if (map.is_null()) map = graph_->GetDomainMap();
108  return map;
109  }
110  size_t getLocalNumEntries() const { return graph_->GetNodeNumEdges(); }
111  size_t getLocalNumRows() const { return getRowMap()->getLocalNumElements(); }
112  size_t getLocalNumCols() const { return getColMap()->getLocalNumElements(); }
113 
114  void getLocalRowView(lno_t LocalRow, Teuchos::ArrayView<const lno_t> &indices) const {
115  indices = graph_->getNeighborVertices_av(LocalRow);
116  }
117 
121 
131  MueLuGraphBaseAdapter(const RCP<const User> &ingraph,
132  int nVtxWeights = 0, int nEdgeWeights = 0);
133 
146  void setWeights(const scalar_t *val, int stride, int idx);
147 
163  void setVertexWeights(const scalar_t *val, int stride, int idx);
164 
170  void setWeightIsDegree(int idx);
171 
177  void setVertexWeightIsDegree(int idx);
178 
201  void setEdgeWeights(const scalar_t *val, int stride, int idx);
202 
206 
210 
212  // The Adapter interface.
214 
216  // The GraphAdapter interface.
218 
219  // TODO: Assuming rows == objects;
220  // TODO: Need to add option for columns or nonzeros?
221  size_t getLocalNumVertices() const { return getLocalNumRows(); }
222 
223  void getVertexIDsView(const gno_t *&ids) const {
224  ids = NULL;
225  if (getLocalNumVertices())
226  ids = getRowMap()->getLocalElementList().getRawPtr();
227  }
228 
229  size_t getLocalNumEdges() const { return getLocalNumEntries(); }
230 
231  void getEdgesView(const offset_t *&offsets, const gno_t *&adjIds) const {
232  offsets = offs_.getRawPtr();
233  adjIds = (getLocalNumEdges() ? adjids_.getRawPtr() : NULL);
234  }
235 
237 
238  void getVertexWeightsView(const scalar_t *&weights, int &stride,
239  int idx) const {
240  if (idx < 0 || idx >= nWeightsPerVertex_) {
241  std::ostringstream emsg;
242  emsg << __FILE__ << ":" << __LINE__
243  << " Invalid vertex weight index " << idx << std::endl;
244  throw std::runtime_error(emsg.str());
245  }
246 
247  size_t length;
248  vertexWeights_[idx].getStridedList(length, weights, stride);
249  }
250 
251  bool useDegreeAsVertexWeight(int idx) const { return vertexDegreeWeight_[idx]; }
252 
253  int getNumWeightsPerEdge() const { return nWeightsPerEdge_; }
254 
255  void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const {
256  if (idx < 0 || idx >= nWeightsPerEdge_) {
257  std::ostringstream emsg;
258  emsg << __FILE__ << ":" << __LINE__
259  << " Invalid edge weight index " << idx << std::endl;
260  throw std::runtime_error(emsg.str());
261  }
262 
263  size_t length;
264  edgeWeights_[idx].getStridedList(length, weights, stride);
265  }
266 
267  template <typename Adapter>
268  void applyPartitioningSolution(const User &in, User *&out,
269  const Zoltan2::PartitioningSolution<Adapter> &solution) const {
270  TEUCHOS_TEST_FOR_EXCEPTION(1, std::invalid_argument, "applyPartitionlingSolution not implemeneted");
271  }
272 
273  template <typename Adapter>
274  void applyPartitioningSolution(const User &in, RCP<User> &out,
275  const Zoltan2::PartitioningSolution<Adapter> &solution) const {
276  TEUCHOS_TEST_FOR_EXCEPTION(1, std::invalid_argument, "applyPartitionlingSolution not implemeneted");
277  }
278 
279  private:
283 
286 
290 
293 
296 };
297 
299 // Definitions
301 
302 template <typename User, typename UserCoord>
304  const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts)
305  : ingraph_(ingraph)
306  , graph_()
307  , comm_()
308  , offs_()
309  , adjids_()
310  , nWeightsPerVertex_(nVtxWgts)
311  , vertexWeights_()
312  , vertexDegreeWeight_()
313  , nWeightsPerEdge_(nEdgeWgts)
314  , edgeWeights_()
315  , coordinateDim_(0)
316  , coords_() {
317  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
318  graph_ = ingraph;
319 
320  comm_ = getRowMap()->getComm();
321  size_t nvtx = getLocalNumRows();
322  size_t nedges = getLocalNumEntries();
323 
324  // Unfortunately we have to copy the offsets and edge Ids
325  // because edge Ids are not usually stored in vertex id order.
326  size_t n = nvtx + 1;
327  offs_.resize(n);
328  offset_t *offs = const_cast<offset_t *>(offs_.getRawPtr());
329  gno_t *adjids = 0;
330  if (nedges > 0) {
331  adjids_.resize(nedges);
332  adjids = const_cast<gno_t *>(adjids_.getRawPtr());
333  }
334 
335  offs[0] = 0;
336  for (size_t v = 0; v < nvtx; v++) {
338  getLocalRowView(v, nbors);
339  offs[v + 1] = offs[v] + nbors.size();
340  for (offset_t e = offs[v], i = 0; e < offs[v + 1]; e++) {
341  adjids[e] = getColMap()->getGlobalElement(nbors[i++]);
342  }
343  }
344 
345  if (nWeightsPerVertex_ > 0) {
347  arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
349  arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
350  for (int i = 0; i < nWeightsPerVertex_; i++)
351  vertexDegreeWeight_[i] = false;
352  }
353 }
354 
356 template <typename User, typename UserCoord>
358  const scalar_t *weightVal, int stride, int idx) {
359  if (this->getPrimaryEntityType() == Zoltan2::GRAPH_VERTEX)
360  setVertexWeights(weightVal, stride, idx);
361  else
362  setEdgeWeights(weightVal, stride, idx);
363 }
364 
366 template <typename User, typename UserCoord>
368  const scalar_t *weightVal, int stride, int idx) {
369  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
370 
371  if (idx < 0 || idx >= nWeightsPerVertex_) {
372  std::ostringstream emsg;
373  emsg << __FILE__ << ":" << __LINE__
374  << " Invalid vertex weight index " << idx << std::endl;
375  throw std::runtime_error(emsg.str());
376  }
377 
378  size_t nvtx = getLocalNumVertices();
379  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx * stride, false);
380  vertexWeights_[idx] = input_t(weightV, stride);
381 }
382 
384 template <typename User, typename UserCoord>
386  int idx) {
387  if (this->getPrimaryEntityType() == Zoltan2::GRAPH_VERTEX)
388  setVertexWeightIsDegree(idx);
389  else {
390  std::ostringstream emsg;
391  emsg << __FILE__ << "," << __LINE__
392  << " error: setWeightIsNumberOfNonZeros is supported only for"
393  << " vertices" << std::endl;
394  throw std::runtime_error(emsg.str());
395  }
396 }
397 
399 template <typename User, typename UserCoord>
401  int idx) {
402  if (idx < 0 || idx >= nWeightsPerVertex_) {
403  std::ostringstream emsg;
404  emsg << __FILE__ << ":" << __LINE__
405  << " Invalid vertex weight index " << idx << std::endl;
406  throw std::runtime_error(emsg.str());
407  }
408 
409  vertexDegreeWeight_[idx] = true;
410 }
411 
413 template <typename User, typename UserCoord>
415  const scalar_t *weightVal, int stride, int idx) {
416  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
417 
418  if (idx < 0 || idx >= nWeightsPerEdge_) {
419  std::ostringstream emsg;
420  emsg << __FILE__ << ":" << __LINE__
421  << " Invalid edge weight index " << idx << std::endl;
422  throw std::runtime_error(emsg.str());
423  }
424 
425  size_t nedges = getLocalNumEdges();
426  ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges * stride, false);
427  edgeWeights_[idx] = input_t(weightV, stride);
428 }
429 
430 } // namespace MueLu
431 
432 #endif // HAVE_MUELU_ZOLTAN2
433 
434 #endif
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
MueLu::DefaultLocalOrdinal LocalOrdinal
void setEdgeWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to edge weights.
void getLocalRowView(lno_t LocalRow, Teuchos::ArrayView< const lno_t > &indices) const
const Teuchos::RCP< const Xpetra::Map< lno_t, gno_t, node_t > > getRowMap() const
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > coords_
void applyPartitioningSolution(const User &in, RCP< User > &out, const Zoltan2::PartitioningSolution< Adapter > &solution) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T * getRawPtr() const
size_type size() const
void getEdgesView(const offset_t *&offsets, const gno_t *&adjIds) const
MueLu::DefaultNode Node
void setWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to weights for the primary entity type.
void resize(const size_type n, const T &val=T())
RCP< const xgraph_t > getXpetraGraph() const
Access to Xpetra-wrapped user&#39;s graph.
void getVertexIDsView(const gno_t *&ids) const
MueLu::DefaultGlobalOrdinal GlobalOrdinal
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.
const Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
MueLu::GraphBase Compatibility Layer.
void getVertexWeightsView(const scalar_t *&weights, int &stride, int idx) const
void applyPartitioningSolution(const User &in, User *&out, const Zoltan2::PartitioningSolution< Adapter > &solution) const
MueLuGraphBaseAdapter(const RCP< const User > &ingraph, int nVtxWeights=0, int nEdgeWeights=0)
Constructor for graph with no weights or coordinates.
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > vertexWeights_
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > edgeWeights_
void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
RCP< const User > getUserGraph() const
Access to user&#39;s graph.
const RCP< const Xpetra::Map< lno_t, gno_t, node_t > > getColMap() const
RCP< const Teuchos::Comm< int > > comm_
bool is_null() const