MueLu Version of the Day
Loading...
Searching...
No Matches
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
28namespace Zoltan2 {
29
30template <typename LocalOrdinal,
31 typename GlobalOrdinal,
32 typename Node>
33struct 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
46namespace MueLu {
47
48template <typename User, typename UserCoord = User>
49class 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(); }
66 const RCP<const Xpetra::Map<lno_t, gno_t, node_t> > getColMap() const {
67 // For some GraphBases' this is a ColMap, in others it is a seperate map that is
68 // only non-null in parallel.
69 Teuchos::RCP<const Xpetra::Map<lno_t, gno_t, node_t> > map = graph_->GetImportMap();
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
94 MueLuGraphBaseAdapter(const RCP<const User> &ingraph,
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
168 RCP<const xgraph_t> getXpetraGraph() const { return graph_; }
169
172 RCP<const User> getUserGraph() const { return ingraph_; }
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;
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
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:
243 RCP<const User> ingraph_;
244 RCP<const xgraph_t> graph_;
245 RCP<const Teuchos::Comm<int> > comm_;
246
247 ArrayRCP<const offset_t> offs_;
248 ArrayRCP<const gno_t> adjids_;
249
251 ArrayRCP<Zoltan2::StridedData<lno_t, scalar_t> > vertexWeights_;
252 ArrayRCP<bool> vertexDegreeWeight_;
253
255 ArrayRCP<Zoltan2::StridedData<lno_t, scalar_t> > edgeWeights_;
256
258 ArrayRCP<Zoltan2::StridedData<lno_t, scalar_t> > coords_;
259};
260
262// Definitions
264
265template <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++) {
300 ArrayView<const lno_t> nbors;
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
319template <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
329template <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
347template <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
362template <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
376template <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
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
MueLu::DefaultNode Node
void setEdgeWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to edge weights.
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > vertexWeights_
RCP< const Teuchos::Comm< int > > comm_
void applyPartitioningSolution(const User &in, RCP< User > &out, const Zoltan2::PartitioningSolution< Adapter > &solution) const
RCP< const User > getUserGraph() const
Access to user's graph.
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > coords_
void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
MueLuGraphBaseAdapter(const RCP< const User > &ingraph, int nVtxWeights=0, int nEdgeWeights=0)
Constructor for graph with no weights or coordinates.
void getEdgesView(const offset_t *&offsets, const gno_t *&adjIds) const
const Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
MueLu::GraphBase Compatibility Layer.
ArrayRCP< Zoltan2::StridedData< lno_t, scalar_t > > edgeWeights_
void setVertexWeightIsDegree(int idx)
Specify an index for which the vertex weight should be the degree of the vertex.
void applyPartitioningSolution(const User &in, User *&out, const Zoltan2::PartitioningSolution< Adapter > &solution) const
void getLocalRowView(lno_t LocalRow, Teuchos::ArrayView< const lno_t > &indices) const
void setWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to weights for the primary entity type.
void getVertexWeightsView(const scalar_t *&weights, int &stride, int idx) const
void getVertexIDsView(const gno_t *&ids) const
const Teuchos::RCP< const Xpetra::Map< lno_t, gno_t, node_t > > getRowMap() const
const RCP< const Xpetra::Map< lno_t, gno_t, node_t > > getColMap() const
void setVertexWeights(const scalar_t *val, int stride, int idx)
Provide a pointer to vertex weights.
RCP< const xgraph_t > getXpetraGraph() const
Access to Xpetra-wrapped user's graph.
void setWeightIsDegree(int idx)
Specify an index for which the weight should be the degree of the entity.
Namespace for MueLu classes and methods.