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 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_ZOLTAN2GRAPHADAPTER_HPP_
11 #define MUELU_ZOLTAN2GRAPHADAPTER_HPP_
12 
13 #include "MueLu_ConfigDefs.hpp"
14 
15 #if defined(HAVE_MUELU_ZOLTAN2)
16 
17 #include <Teuchos_RCP.hpp>
18 #include <Teuchos_Comm.hpp>
19 #include <Teuchos_ArrayView.hpp>
20 #include <Xpetra_Map.hpp>
21 #include <Zoltan2_InputTraits.hpp>
22 #include <Zoltan2_GraphAdapter.hpp>
23 #include <Zoltan2_StridedData.hpp>
24 #include <Zoltan2_PartitioningSolution.hpp>
25 #include "MueLu_LWGraph.hpp"
26 
27 // Zoltab2 InputTraits for MueLu Graph objects
28 namespace Zoltan2 {
29 
30 template <typename LocalOrdinal,
31  typename GlobalOrdinal,
32  typename Node>
33 struct InputTraits<MueLu::LWGraph<LocalOrdinal, GlobalOrdinal, Node> > {
34  typedef Zoltan2::default_scalar_t scalar_t;
37  typedef size_t offset_t;
38  typedef Zoltan2::default_part_t part_t;
39  typedef Node node_t;
40  static inline std::string name() { return "MueLu::Graph"; }
41 
42  Z2_STATIC_ASSERT_TYPES // validate the types
43 };
44 } // end namespace Zoltan2
45 
46 namespace MueLu {
47 
48 template <typename User, typename UserCoord = User>
49 class MueLuGraphBaseAdapter : public Zoltan2::GraphAdapter<User, UserCoord> {
50  public:
51 #ifndef DOXYGEN_SHOULD_SKIP_THIS
52  typedef typename Zoltan2::InputTraits<User>::scalar_t scalar_t;
53  typedef typename Zoltan2::InputTraits<User>::offset_t offset_t;
54  typedef typename Zoltan2::InputTraits<User>::lno_t lno_t;
55  typedef typename Zoltan2::InputTraits<User>::gno_t gno_t;
56  typedef typename Zoltan2::InputTraits<User>::part_t part_t;
57  typedef typename Zoltan2::InputTraits<User>::node_t node_t;
58  typedef User xgraph_t;
59  typedef User user_t;
60  typedef UserCoord userCoord_t;
61 #endif
62 
64  const Teuchos::RCP<const Teuchos::Comm<int> > getComm() const { return graph_->GetComm(); }
65  const Teuchos::RCP<const Xpetra::Map<lno_t, gno_t, node_t> > getRowMap() const { return graph_->GetDomainMap(); }
67  // For some GraphBases' this is a ColMap, in others it is a seperate map that is
68  // only non-null in parallel.
70  if (map.is_null()) map = graph_->GetDomainMap();
71  return map;
72  }
73  size_t getLocalNumEntries() const { return graph_->GetNodeNumEdges(); }
74  size_t getLocalNumRows() const { return getRowMap()->getLocalNumElements(); }
75  size_t getLocalNumCols() const { return getColMap()->getLocalNumElements(); }
76 
77  void getLocalRowView(lno_t LocalRow, Teuchos::ArrayView<const lno_t> &indices) const {
78  indices = graph_->getNeighborVertices_av(LocalRow);
79  }
80 
84 
95  int nVtxWeights = 0, int nEdgeWeights = 0);
96 
109  void setWeights(const scalar_t *val, int stride, int idx);
110 
126  void setVertexWeights(const scalar_t *val, int stride, int idx);
127 
133  void setWeightIsDegree(int idx);
134 
140  void setVertexWeightIsDegree(int idx);
141 
164  void setEdgeWeights(const scalar_t *val, int stride, int idx);
165 
169 
173 
175  // The Adapter interface.
177 
179  // The GraphAdapter interface.
181 
182  // TODO: Assuming rows == objects;
183  // TODO: Need to add option for columns or nonzeros?
184  size_t getLocalNumVertices() const { return getLocalNumRows(); }
185 
186  void getVertexIDsView(const gno_t *&ids) const {
187  ids = NULL;
188  if (getLocalNumVertices())
189  ids = getRowMap()->getLocalElementList().getRawPtr();
190  }
191 
192  size_t getLocalNumEdges() const { return getLocalNumEntries(); }
193 
194  void getEdgesView(const offset_t *&offsets, const gno_t *&adjIds) const {
195  offsets = offs_.getRawPtr();
196  adjIds = (getLocalNumEdges() ? adjids_.getRawPtr() : NULL);
197  }
198 
200 
201  void getVertexWeightsView(const scalar_t *&weights, int &stride,
202  int idx) const {
203  if (idx < 0 || idx >= nWeightsPerVertex_) {
204  std::ostringstream emsg;
205  emsg << __FILE__ << ":" << __LINE__
206  << " Invalid vertex weight index " << idx << std::endl;
207  throw std::runtime_error(emsg.str());
208  }
209 
210  size_t length;
211  vertexWeights_[idx].getStridedList(length, weights, stride);
212  }
213 
214  bool useDegreeAsVertexWeight(int idx) const { return vertexDegreeWeight_[idx]; }
215 
216  int getNumWeightsPerEdge() const { return nWeightsPerEdge_; }
217 
218  void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const {
219  if (idx < 0 || idx >= nWeightsPerEdge_) {
220  std::ostringstream emsg;
221  emsg << __FILE__ << ":" << __LINE__
222  << " Invalid edge weight index " << idx << std::endl;
223  throw std::runtime_error(emsg.str());
224  }
225 
226  size_t length;
227  edgeWeights_[idx].getStridedList(length, weights, stride);
228  }
229 
230  template <typename Adapter>
231  void applyPartitioningSolution(const User &in, User *&out,
232  const Zoltan2::PartitioningSolution<Adapter> &solution) const {
233  TEUCHOS_TEST_FOR_EXCEPTION(1, std::invalid_argument, "applyPartitionlingSolution not implemeneted");
234  }
235 
236  template <typename Adapter>
237  void applyPartitioningSolution(const User &in, RCP<User> &out,
238  const Zoltan2::PartitioningSolution<Adapter> &solution) const {
239  TEUCHOS_TEST_FOR_EXCEPTION(1, std::invalid_argument, "applyPartitionlingSolution not implemeneted");
240  }
241 
242  private:
246 
249 
253 
256 
259 };
260 
262 // Definitions
264 
265 template <typename User, typename UserCoord>
267  const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts)
268  : ingraph_(ingraph)
269  , graph_()
270  , comm_()
271  , offs_()
272  , adjids_()
273  , nWeightsPerVertex_(nVtxWgts)
274  , vertexWeights_()
275  , vertexDegreeWeight_()
276  , nWeightsPerEdge_(nEdgeWgts)
277  , edgeWeights_()
278  , coordinateDim_(0)
279  , coords_() {
280  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
281  graph_ = ingraph;
282 
283  comm_ = getRowMap()->getComm();
284  size_t nvtx = getLocalNumRows();
285  size_t nedges = getLocalNumEntries();
286 
287  // Unfortunately we have to copy the offsets and edge Ids
288  // because edge Ids are not usually stored in vertex id order.
289  size_t n = nvtx + 1;
290  offs_.resize(n);
291  offset_t *offs = const_cast<offset_t *>(offs_.getRawPtr());
292  gno_t *adjids = 0;
293  if (nedges > 0) {
294  adjids_.resize(nedges);
295  adjids = const_cast<gno_t *>(adjids_.getRawPtr());
296  }
297 
298  offs[0] = 0;
299  for (size_t v = 0; v < nvtx; v++) {
301  getLocalRowView(v, nbors);
302  offs[v + 1] = offs[v] + nbors.size();
303  for (offset_t e = offs[v], i = 0; e < offs[v + 1]; e++) {
304  adjids[e] = getColMap()->getGlobalElement(nbors[i++]);
305  }
306  }
307 
308  if (nWeightsPerVertex_ > 0) {
310  arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
312  arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true);
313  for (int i = 0; i < nWeightsPerVertex_; i++)
314  vertexDegreeWeight_[i] = false;
315  }
316 }
317 
319 template <typename User, typename UserCoord>
321  const scalar_t *weightVal, int stride, int idx) {
322  if (this->getPrimaryEntityType() == Zoltan2::GRAPH_VERTEX)
323  setVertexWeights(weightVal, stride, idx);
324  else
325  setEdgeWeights(weightVal, stride, idx);
326 }
327 
329 template <typename User, typename UserCoord>
331  const scalar_t *weightVal, int stride, int idx) {
332  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
333 
334  if (idx < 0 || idx >= nWeightsPerVertex_) {
335  std::ostringstream emsg;
336  emsg << __FILE__ << ":" << __LINE__
337  << " Invalid vertex weight index " << idx << std::endl;
338  throw std::runtime_error(emsg.str());
339  }
340 
341  size_t nvtx = getLocalNumVertices();
342  ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx * stride, false);
343  vertexWeights_[idx] = input_t(weightV, stride);
344 }
345 
347 template <typename User, typename UserCoord>
349  int idx) {
350  if (this->getPrimaryEntityType() == Zoltan2::GRAPH_VERTEX)
351  setVertexWeightIsDegree(idx);
352  else {
353  std::ostringstream emsg;
354  emsg << __FILE__ << "," << __LINE__
355  << " error: setWeightIsNumberOfNonZeros is supported only for"
356  << " vertices" << std::endl;
357  throw std::runtime_error(emsg.str());
358  }
359 }
360 
362 template <typename User, typename UserCoord>
364  int idx) {
365  if (idx < 0 || idx >= nWeightsPerVertex_) {
366  std::ostringstream emsg;
367  emsg << __FILE__ << ":" << __LINE__
368  << " Invalid vertex weight index " << idx << std::endl;
369  throw std::runtime_error(emsg.str());
370  }
371 
372  vertexDegreeWeight_[idx] = true;
373 }
374 
376 template <typename User, typename UserCoord>
378  const scalar_t *weightVal, int stride, int idx) {
379  typedef Zoltan2::StridedData<lno_t, scalar_t> input_t;
380 
381  if (idx < 0 || idx >= nWeightsPerEdge_) {
382  std::ostringstream emsg;
383  emsg << __FILE__ << ":" << __LINE__
384  << " Invalid edge weight index " << idx << std::endl;
385  throw std::runtime_error(emsg.str());
386  }
387 
388  size_t nedges = getLocalNumEdges();
389  ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges * stride, false);
390  edgeWeights_[idx] = input_t(weightV, stride);
391 }
392 
393 } // namespace MueLu
394 
395 #endif // HAVE_MUELU_ZOLTAN2
396 
397 #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