Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_CommGraphModel.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
24 #ifndef _ZOLTAN2_COMMGRAPHMODEL_HPP_
25 #define _ZOLTAN2_COMMGRAPHMODEL_HPP_
26 
27 #include <Zoltan2_Model.hpp>
28 #include <Zoltan2_ModelHelpers.hpp>
29 #include <Zoltan2_InputTraits.hpp>
31 #include <Zoltan2_GraphAdapter.hpp>
35 #include <Zoltan2_MeshAdapter.hpp>
36 #include <Zoltan2_StridedData.hpp>
37 #include <unordered_map>
38 
39 namespace Zoltan2 {
40 
42 
54 template <typename Adapter>
55 class CommGraphModel : public Model<Adapter>
56 {
57 public:
58 
59 #ifndef DOXYGEN_SHOULD_SKIP_THIS
60  typedef typename Adapter::scalar_t scalar_t;
61  typedef typename Adapter::gno_t gno_t;
62  typedef typename Adapter::lno_t lno_t;
63  typedef typename Adapter::node_t node_t;
64  typedef typename Adapter::user_t user_t;
65  typedef typename Adapter::userCoord_t userCoord_t;
66  typedef StridedData<lno_t, scalar_t> input_t;
67  typedef typename Adapter::offset_t offset_t;
68 #endif
69 
72 
84  const RCP<const Environment> &/* env */, const RCP<const Comm<int> > &/* comm */,
85  const modelFlag_t &modelflags = modelFlag_t())
86  {
87  throw std::runtime_error("CommGraphModel is not implemented for MatrixAdapter yet.");
88  }
89 
91  const RCP<const Environment> &env, const RCP<const Comm<int> > &comm,
92  const modelFlag_t &modelflags = modelFlag_t());
93 
94  CommGraphModel(const RCP<const MeshAdapter<user_t> > &/* ia */,
95  const RCP<const Environment> &/* env */, const RCP<const Comm<int> > &/* comm */,
96  const modelFlag_t &modelflags = modelFlag_t())
97  {
98  throw std::runtime_error("CommGraphModel is not implemented for MeshAdapter yet.");
99  }
100 
101  CommGraphModel(const RCP<const VectorAdapter<userCoord_t> > &/* ia */,
102  const RCP<const Environment> &/* env */, const RCP<const Comm<int> > &/* comm */,
103  const modelFlag_t &modelflags = modelFlag_t())
104  {
105  throw std::runtime_error("cannot build CommGraphModel from VectorAdapter");
106  }
107 
108  CommGraphModel(const RCP<const IdentifierAdapter<user_t> > &/* ia */,
109  const RCP<const Environment> &/* env */, const RCP<const Comm<int> > &/* comm */,
110  const modelFlag_t &modelflags = modelFlag_t())
111  {
112  throw std::runtime_error("cannot build GraphModel from IdentifierAdapter");
113  }
114 
117  const RCP<const Comm<int> > getComm() { return comm_; }
118 
121  size_t getLocalNumVertices() const { return nLocalVertices_; }
122 
125  size_t getGlobalNumVertices() const { return nGlobalVertices_; }
126 
130  size_t getLocalNumEdges() const { return nLocalEdges_; }
131 
135  size_t getGlobalNumEdges() const { return nGlobalEdges_; }
136 
139  int getNumWeightsPerVertex() const { return nWeightsPerVertex_; }
140 
143  int getNumWeightsPerEdge() const { return nWeightsPerEdge_; }
144 
145 
154  ArrayView<const gno_t> &Ids,
155  ArrayView<input_t> &wgts) const
156  {
157  Ids = vGids_.view(0, nLocalVertices_);
158  wgts = vWeights_.view(0, nWeightsPerVertex_);
159  return nLocalVertices_;
160  }
161 
162  // Implied Vertex LNOs from getVertexList are used as indices to offsets
163  // array.
164  // Vertex GNOs are returned as neighbors in edgeIds.
165 
166  size_t getEdgeList( ArrayView<const gno_t> &edgeIds,
167  ArrayView<const offset_t> &offsets,
168  ArrayView<input_t> &wgts) const
169  {
170  edgeIds = eGids_.view(0, nLocalEdges_);
171  offsets = eOffsets_.view(0, nLocalVertices_+1);
172  wgts = eWeights_.view(0, nWeightsPerEdge_);
173  return nLocalEdges_;
174  }
175 
180  inline void getVertexDist(ArrayView<size_t> &vtxdist) const
181  {
182  vtxdist = vtxDist_();
183  if (vtxDist_.size() == 0) {
184  throw std::runtime_error("getVertexDist is available only "
185  "when consecutiveIdsRequired");
186  }
187  }
188 
190  // The Model interface.
192 
193  size_t getLocalNumObjects() const { return nLocalVertices_; }
194 
195  size_t getGlobalNumObjects() const { return nGlobalVertices_; }
196 
198  // Migration-related functions.
200 
201  int getNumActiveRanks() const { return nActiveRanks_; }
202 
203  int getDestinationRank() const { return destRank_; }
204 
205  int getStartRank() const { return startRank_; }
206 
207  int getEndRank() const { return endRank_; }
208 
209 private:
210 
211  void print(); // For debugging
212  void migrateGraph(); // For debugging
213 
214  const RCP<const Environment > env_;
215  const RCP<const Comm<int> > comm_;
216 
217  int threshold_; // threshold on #vertices each rank stores post-migration
218  int nActiveRanks_ ; // # ranks for the small graph to be partitioned on
219  int destRank_, startRank_, endRank_;
220 
221 
222  size_t nLocalVertices_; // # local vertices in built graph
223  size_t nGlobalVertices_; // # global vertices in built graph
224  ArrayRCP<gno_t> vGids_; // vertices of graph built in model;
225  // may be same as adapter's input
226  // or may be renumbered 0 to (N-1).
227 
228  int nWeightsPerVertex_;
229  ArrayRCP<input_t> vWeights_;
230 
231  // Note: in some cases, size of these arrays
232  // may be larger than nLocalEdges_. So do not use .size().
233  // Use nLocalEdges_, nGlobalEdges_
234 
235  size_t nLocalEdges_; // # local edges in built graph
236  size_t nGlobalEdges_; // # global edges in built graph
237  ArrayRCP<gno_t> eGids_; // edges of graph built in model
238  ArrayRCP<offset_t> eOffsets_; // edge offsets build in model
239  // May be same as adapter's input
240  // or may differ
241  // due to renumbering, self-edge
242  // removal, or local graph.
243 
244  int nWeightsPerEdge_;
245  ArrayRCP<input_t> eWeights_; // edge weights in built graph
246  // May be same as adapter's input
247  // or may differ due to self-edge
248  // removal, or local graph.
249 
250  ArrayRCP<size_t> vtxDist_; // If consecutiveIdsRequired,
251  // vtxDist (as needed by ParMETIS
252  // and Scotch) is also created.
253  // Otherwise, it is Teuchos::null.
254 };
255 
256 
258 // GraphModel from GraphAdapter
259 template <typename Adapter>
261  const RCP<const GraphAdapter<user_t,userCoord_t> > &bia,
262  const RCP<const Environment> &env,
263  const RCP<const Comm<int> > &comm,
264  const modelFlag_t &/* modelflags */):
265  env_(env),
266  comm_(comm),
267  nLocalVertices_(0),
268  nGlobalVertices_(0),
269  vGids_(),
270  nWeightsPerVertex_(0),
271  vWeights_(),
272  nLocalEdges_(0),
273  nGlobalEdges_(0),
274  eGids_(),
275  eOffsets_(),
276  nWeightsPerEdge_(0),
277  eWeights_(),
278  vtxDist_()
279 {
280  int commSize = comm_->getSize();
281 
282  // Get XpetraCrsGraphAdapter from GraphAdapter
283  RCP<XpetraCrsGraphAdapter<user_t, userCoord_t>> ia;
284  try{
285  RCP<GraphAdapter<user_t, userCoord_t>> tmp =
286  rcp_const_cast<GraphAdapter<user_t, userCoord_t>>(bia);
287  ia = rcp_dynamic_cast<XpetraCrsGraphAdapter<user_t, userCoord_t>>(tmp);
288  }
290 
291  // Get the graph from the input adapter
292  auto inGraph = ia->getXpetraGraph();
293 
294  // Get the importer of the graph
295  auto imp = inGraph->getImporter();
296 
297  // Identify nbor PIDs and number of entries sent per PID
298  std::map<int,double> exportpidmap;
299  auto exportpids = imp->getExportPIDs();
300  size_t nexportpids = imp->getNumExportIDs();
301  for (size_t i = 0; i < nexportpids; i++) {
302  int k = exportpids[i];
303  if (exportpidmap.find(k) != exportpidmap.end())
304  exportpidmap[k] = exportpidmap[k] + 1.;
305  else
306  exportpidmap[k] = 1.;
307  }
308 
309  // Set sizes
310  // There is only one vertex in each rank
311  nLocalVertices_ = 1;
312  nLocalEdges_ = exportpidmap.size();
313 
314  // Allocate space
315  vGids_ = arcp(new gno_t[nLocalVertices_],
316  0, nLocalVertices_, true);
317  eGids_ = arcp(new gno_t[nLocalEdges_],
318  0, nLocalEdges_, true);
319  eOffsets_ = arcp(new offset_t[nLocalVertices_+1],
320  0, nLocalVertices_+1, true);
321  scalar_t *wgts2 = new scalar_t [nLocalEdges_];
322 
323  // Form the vertices
324  vGids_[0] = comm->getRank();
325 
326  // Form the edges
327  size_t ptr = 0;
328  eOffsets_[0] = ptr;
329  for (std::map<int,double>::iterator it = exportpidmap.begin();
330  it != exportpidmap.end(); it++) {
331  eGids_[ptr] = it->first;
332  wgts2[ptr++] = it->second;
333  }
334  eOffsets_[nLocalVertices_] = ptr;
335 
336  // Edge weights
337  nWeightsPerEdge_ = 1;
338  input_t *wgts = new input_t [nWeightsPerEdge_];
339  eWeights_ = arcp(wgts, 0, nWeightsPerEdge_, true);
340 
341  for (int w=0; w < nWeightsPerEdge_; w++){
342  int stride=0;
343  ArrayRCP<const scalar_t> wgtArray = arcp(wgts2, 0, nLocalEdges_, true);
344  eWeights_[w] = input_t(wgtArray, stride);
345  }
346 
347  // Vertex weights
348  nWeightsPerVertex_ = 1;
349  input_t *weightInfo = new input_t [nWeightsPerVertex_];
350 
351  for (int idx=0; idx < nWeightsPerVertex_; idx++){
352  scalar_t *wgt = new scalar_t [nLocalVertices_];
353  wgt[0] = inGraph->getLocalNumEntries();
354  ArrayRCP<const scalar_t> wgtArray = arcp(wgt, 0, nLocalVertices_, true);
355  weightInfo[idx] = input_t(wgtArray, 1);
356  }
357 
358  vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_, true);
359 
360  reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
361  &nLocalVertices_, &nGlobalVertices_);
362  reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
363  &nLocalEdges_, &nGlobalEdges_);
364 
365  // Build vtxDist_ array starting with vGid on each rank
366  vtxDist_ = arcp(new size_t[commSize+1], 0, commSize+1, true);
367  vtxDist_[0] = 0;
368  Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, commSize, &vtxDist_[1]);
369  for (int i = 0; i < commSize; i++)
370  vtxDist_[i+1] += vtxDist_[i];
371 
372  // Migrate the quotient graph into smaller number of MPI ranks (active ranks)
373  migrateGraph();
374 }
375 
376 template <typename Adapter>
378 {
379 
380  // Set default threshold for migration
381  threshold_ = 1024;
382 
383  // Check if the user set the threshold value
384  const ParameterList &pl = env_->getParameters();
385  const Teuchos::ParameterEntry *pe = pl.getEntryPtr("quotient_threshold");
386  if (pe)
387  threshold_ = pe->getValue<int>(&threshold_);
388 
389  // Compute the sizes of/in the new distribution
390  nActiveRanks_ = std::ceil((double) nGlobalVertices_ / threshold_);
391  size_t avgVertexShare = nGlobalVertices_ / nActiveRanks_;
392  size_t myVertexShare = 0;
393 
394  int me = comm_->getRank();
395  int commSize = comm_->getSize();
396 
397  // Save the original pointers
398  ArrayRCP<offset_t> old_eOffsets_ = eOffsets_;
399  ArrayRCP<gno_t> old_eGids_ = eGids_;
400  size_t old_nLocalEdges_ = nLocalEdges_;
401  ArrayRCP<input_t> old_vWeights_ = vWeights_;
402  ArrayRCP<input_t> old_eWeights_ = eWeights_;
403 
404  // Compute whom to send to
405  destRank_ = me / (int) avgVertexShare;
406  if(destRank_ >= nActiveRanks_)
407  destRank_ = nActiveRanks_ - 1;
408 
409  // Start with sending the size of the edge list
410  RCP<CommRequest<int>> *requests;
411  if(me < nActiveRanks_) {
412 
413  // Determine the range of ranks to receive edges from
414  // Needs to be updated when chunks are introduced
415  startRank_ = me * static_cast<int>(avgVertexShare);
416  endRank_ = (me+1) * static_cast<int>(avgVertexShare);
417  if(me == nActiveRanks_ - 1 ) // Last rank gets the surplus
418  endRank_ = static_cast<int>(nGlobalVertices_);
419  myVertexShare = endRank_ - startRank_;
420 
421  eOffsets_ = arcp(new offset_t[myVertexShare+1], 0, myVertexShare+1, true);
422  eOffsets_[0] = 0;
423 
424  // Receive the sizes of their edge list
425  requests = new RCP<CommRequest<int>>[myVertexShare];
426  for(int i = startRank_; i < endRank_; i++) {
427  requests[i-startRank_] = Teuchos::ireceive<int, offset_t>(*comm_,
428  arcp(&eOffsets_[i-startRank_+1], 0, 1, false),
429  i);
430  }
431 
432  // Send adjacency size even though this rank will remain active
433  Teuchos::send<int, offset_t>(*comm_, 1, &old_eOffsets_[nLocalVertices_], destRank_);
434 
435  // Wait
436  Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
437 
438  // Prefix sum over the offsets
439  for(size_t i = 1; i <= myVertexShare; i++)
440  eOffsets_[i] += eOffsets_[i-1];
441 
442  // Recompute the number of local edges
443  nLocalEdges_ = eOffsets_[myVertexShare];
444 
445  // Reallocate the adjacency array
446  eGids_ = arcp(new gno_t[nLocalEdges_], 0, nLocalEdges_, true);
447 
448 
449  // Receive the adjacency lists
450  for(int i = startRank_; i < endRank_; i++) {
451  offset_t adjStartRank_ = eOffsets_[i-startRank_];
452  offset_t adjSize = eOffsets_[i-startRank_+1] - adjStartRank_;
453  requests[i-startRank_] = Teuchos::ireceive<int, gno_t>(*comm_,
454  arcp(&eGids_[adjStartRank_], 0, adjSize, false),
455  i);
456  }
457 
458  // Send adjacency even though this rank will remain active
459  Teuchos::send<int, gno_t>(*comm_, old_nLocalEdges_, &old_eGids_[0], destRank_);
460  Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
461 
462 
463  // Migrate vertex weights arrays
464  scalar_t *wgts = new scalar_t [myVertexShare];
465  for(int i = startRank_; i < endRank_; i++) {
466  requests[i-startRank_] = Teuchos::ireceive<int, scalar_t>(*comm_,
467  arcp(&wgts[i-startRank_], 0, 1, false), // assumes one vertex per rank
468  i);
469  }
470 
471  const scalar_t *wPtr;
472  size_t wLen = 0;
473  int stride = 0;
474  old_vWeights_[0].getStridedList(wLen, wPtr, stride);
475  Teuchos::send<int, scalar_t>(*comm_, nLocalVertices_, wPtr, destRank_);
476 
477  Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
478 
479  input_t *weightInfo = new input_t [nWeightsPerVertex_];
480  for (int idx=0; idx < nWeightsPerVertex_; idx++){
481  ArrayRCP<const scalar_t> wgtArray = arcp(wgts, 0, myVertexShare, true);
482  weightInfo[idx] = input_t(wgtArray, 1);
483  }
484  vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_, true);
485 
486  // Migrate edge weights arrays
487  scalar_t *ewgts = new scalar_t [nLocalEdges_];
488  for(int i = startRank_; i < endRank_; i++) {
489  offset_t adjStartRank_ = eOffsets_[i-startRank_];
490  offset_t adjSize = eOffsets_[i-startRank_+1] - adjStartRank_;
491  requests[i-startRank_] = Teuchos::ireceive<int, scalar_t>(*comm_,
492  arcp(&ewgts[adjStartRank_], 0, adjSize, false), // assumes one vertex per rank
493  i);
494  }
495 
496  old_eWeights_[0].getStridedList(wLen, wPtr, stride);
497  Teuchos::send<int, scalar_t>(*comm_, old_nLocalEdges_, wPtr, destRank_);
498 
499  Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
500 
501  input_t *eweightInfo = new input_t [nWeightsPerEdge_];
502  for (int idx=0; idx < nWeightsPerEdge_; idx++){
503  ArrayRCP<const scalar_t> ewgtArray = arcp(ewgts, 0, nLocalEdges_, true);
504  eweightInfo[idx] = input_t(ewgtArray, 1);
505  }
506  eWeights_ = arcp<input_t>(eweightInfo, 0, nWeightsPerEdge_, true);
507 
508 
509  // Finalize the migration
510  vGids_ = arcp(new gno_t[myVertexShare], 0, myVertexShare, true);
511  for(int i = startRank_; i < endRank_; i++)
512  vGids_[i-startRank_] = i;
513 
514  nLocalVertices_ = myVertexShare;
515 
516 
517  }
518  else {
519 
520  // Send adjacency size
521  Teuchos::send<int, offset_t>(*comm_, 1, &eOffsets_[nLocalVertices_], destRank_);
522 
523  // Send adjacency list
524  Teuchos::send<int, gno_t>(*comm_, nLocalEdges_, &eGids_[0], destRank_);
525 
526  // Send vertex weights list
527  const scalar_t *wPtr;
528  size_t wLen = 0;
529  int stride = 0;
530  vWeights_[0].getStridedList(wLen, wPtr, stride);
531  Teuchos::send<int, scalar_t>(*comm_, nLocalVertices_, wPtr, destRank_);
532 
533  // Send edge weights list
534  eWeights_[0].getStridedList(wLen, wPtr, stride);
535  Teuchos::send<int, scalar_t>(*comm_, nLocalEdges_, wPtr, destRank_);
536 
537  nLocalVertices_ = 0;
538  }
539 
540  for (int i = 0; i <= commSize; i++)
541  vtxDist_[i] = 0;
542 
543  Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, commSize, &vtxDist_[1]);
544  for (int i = 0; i < commSize; i++)
545  vtxDist_[i+1] += vtxDist_[i];
546 
547 }
548 
550 template <typename Adapter>
551 void CommGraphModel<Adapter>::print()
552 {
553  std::ostream *os = env_->getDebugOStream();
554 
555  int me = comm_->getRank();
556 
557  *os << me
558  << " Nvtx " << nLocalVertices_
559  << " Nedge " << nLocalEdges_
560  << " NVWgt " << nWeightsPerVertex_
561  << " NEWgt " << nWeightsPerEdge_
562  << std::endl;
563 
564  for (size_t i = 0; i < nLocalVertices_; i++) {
565  *os << me << " " << i << " GID " << vGids_[i] << ": ";
566  for (offset_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++)
567  *os << eGids_[j] << " " ;
568  *os << std::endl;
569  }
570 
571  if (nWeightsPerVertex_) {
572  for (size_t i = 0; i < nLocalVertices_; i++) {
573  *os << me << " " << i << " VWGTS " << vGids_[i] << ": ";
574  for (int j = 0; j < nWeightsPerVertex_; j++)
575  *os << vWeights_[j][i] << " ";
576  *os << std::endl;
577  }
578  }
579 
580  if (nWeightsPerEdge_) {
581  for (size_t i = 0; i < nLocalVertices_; i++) {
582  *os << me << " " << i << " EWGTS " << vGids_[i] << ": ";
583  for (offset_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++) {
584  *os << eGids_[j] << " (";
585  for (int w = 0; w < nWeightsPerEdge_; w++)
586  *os << eWeights_[w][j] << " ";
587  *os << ") ";
588  }
589  *os << std::endl;
590  }
591  }
592 
593 }
594 
595 } // namespace Zoltan2
596 
597 
598 #endif
599 
size_t getGlobalNumEdges() const
Returns the global number edges. For local graphs, the number of global edges is the number of local ...
IdentifierAdapter defines the interface for identifiers.
size_t getLocalNumVertices() const
Returns the number vertices on this process.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
MatrixAdapter defines the adapter interface for matrices.
Defines the Model interface.
GraphAdapter defines the interface for graph-based user data.
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
Defines the IdentifierAdapter interface.
size_t getGlobalNumVertices() const
Returns the global number vertices.
Defines the VectorAdapter interface.
typename Zoltan2::InputTraits< ztcrsmatrix_t >::node_t node_t
Provides access for Zoltan2 to Xpetra::CrsGraph data.
Defines XpetraCrsGraphAdapter class.
size_t getEdgeList(ArrayView< const gno_t > &edgeIds, ArrayView< const offset_t > &offsets, ArrayView< input_t > &wgts) const
Defines helper functions for use in the models.
CommGraphModel defines the interface required for communication graph.
int getNumWeightsPerEdge() const
Returns the number (0 or greater) of weights per edge.
VectorAdapter defines the interface for vector input.
The StridedData class manages lists of weights or coordinates.
Traits for application input objects.
size_t getLocalNumEdges() const
Returns the number of edges on this process. In global or subset graphs, includes off-process edges...
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
size_t getVertexList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const
Sets pointers to this process&#39; vertex Ids and their weights.
size_t getLocalNumObjects() const
Return the local number of objects.
int getNumWeightsPerVertex() const
Returns the number (0 or greater) of weights per vertex.
CommGraphModel(const RCP< const MeshAdapter< user_t > > &, const RCP< const Environment > &, const RCP< const Comm< int > > &, const modelFlag_t &modelflags=modelFlag_t())
CommGraphModel(const RCP< const VectorAdapter< userCoord_t > > &, const RCP< const Environment > &, const RCP< const Comm< int > > &, const modelFlag_t &modelflags=modelFlag_t())
Defines the MatrixAdapter interface.
The base class for all model classes.
CommGraphModel(const RCP< const IdentifierAdapter< user_t > > &, const RCP< const Environment > &, const RCP< const Comm< int > > &, const modelFlag_t &modelflags=modelFlag_t())
Defines the GraphAdapter interface.
CommGraphModel(const RCP< const MatrixAdapter< user_t, userCoord_t > > &, const RCP< const Environment > &, const RCP< const Comm< int > > &, const modelFlag_t &modelflags=modelFlag_t())
Constructor.
size_t getGlobalNumObjects() const
Return the global number of objects.
const RCP< const Comm< int > > getComm()
Return the communicator used by the model.
This file defines the StridedData class.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:39
void getVertexDist(ArrayView< size_t > &vtxdist) const
Return the vtxDist array Array of size comm-&gt;getSize() + 1 Array[n+1] - Array[n] is number of vertice...