24 #ifndef _ZOLTAN2_COMMGRAPHMODEL_HPP_
25 #define _ZOLTAN2_COMMGRAPHMODEL_HPP_
37 #include <unordered_map>
54 template <
typename Adapter>
59 #ifndef DOXYGEN_SHOULD_SKIP_THIS
60 typedef typename Adapter::scalar_t scalar_t;
65 typedef typename Adapter::userCoord_t userCoord_t;
67 typedef typename Adapter::offset_t offset_t;
84 const RCP<const Environment> &,
const RCP<
const Comm<int> > &,
87 throw std::runtime_error(
"CommGraphModel is not implemented for MatrixAdapter yet.");
91 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
95 const RCP<const Environment> &,
const RCP<
const Comm<int> > &,
98 throw std::runtime_error(
"CommGraphModel is not implemented for MeshAdapter yet.");
102 const RCP<const Environment> &,
const RCP<
const Comm<int> > &,
105 throw std::runtime_error(
"cannot build CommGraphModel from VectorAdapter");
109 const RCP<const Environment> &,
const RCP<
const Comm<int> > &,
112 throw std::runtime_error(
"cannot build GraphModel from IdentifierAdapter");
117 const RCP<const Comm<int> >
getComm() {
return comm_; }
154 ArrayView<const gno_t> &Ids,
155 ArrayView<input_t> &wgts)
const
157 Ids = vGids_.view(0, nLocalVertices_);
158 wgts = vWeights_.view(0, nWeightsPerVertex_);
159 return nLocalVertices_;
167 ArrayView<const offset_t> &offsets,
168 ArrayView<input_t> &wgts)
const
170 edgeIds = eGids_.view(0, nLocalEdges_);
171 offsets = eOffsets_.view(0, nLocalVertices_+1);
172 wgts = eWeights_.view(0, nWeightsPerEdge_);
182 vtxdist = vtxDist_();
183 if (vtxDist_.size() == 0) {
184 throw std::runtime_error(
"getVertexDist is available only "
185 "when consecutiveIdsRequired");
214 const RCP<const Environment > env_;
215 const RCP<const Comm<int> > comm_;
219 int destRank_, startRank_, endRank_;
222 size_t nLocalVertices_;
223 size_t nGlobalVertices_;
224 ArrayRCP<gno_t> vGids_;
228 int nWeightsPerVertex_;
229 ArrayRCP<input_t> vWeights_;
236 size_t nGlobalEdges_;
237 ArrayRCP<gno_t> eGids_;
238 ArrayRCP<offset_t> eOffsets_;
244 int nWeightsPerEdge_;
245 ArrayRCP<input_t> eWeights_;
250 ArrayRCP<size_t> vtxDist_;
259 template <
typename Adapter>
262 const RCP<const Environment> &env,
263 const RCP<
const Comm<int> > &comm,
270 nWeightsPerVertex_(0),
280 int commSize = comm_->getSize();
283 RCP<XpetraCrsGraphAdapter<user_t, userCoord_t>> ia;
285 RCP<GraphAdapter<user_t, userCoord_t>> tmp =
292 auto inGraph = ia->getXpetraGraph();
295 auto imp = inGraph->getImporter();
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.;
306 exportpidmap[k] = 1.;
312 nLocalEdges_ = exportpidmap.size();
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_];
324 vGids_[0] = comm->getRank();
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;
334 eOffsets_[nLocalVertices_] = ptr;
337 nWeightsPerEdge_ = 1;
338 input_t *wgts =
new input_t [nWeightsPerEdge_];
339 eWeights_ = arcp(wgts, 0, nWeightsPerEdge_,
true);
341 for (
int w=0; w < nWeightsPerEdge_; w++){
343 ArrayRCP<const scalar_t> wgtArray = arcp(wgts2, 0, nLocalEdges_,
true);
344 eWeights_[w] = input_t(wgtArray, stride);
348 nWeightsPerVertex_ = 1;
349 input_t *weightInfo =
new input_t [nWeightsPerVertex_];
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);
358 vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_,
true);
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_);
366 vtxDist_ = arcp(
new size_t[commSize+1], 0, commSize+1,
true);
368 Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, commSize, &vtxDist_[1]);
369 for (
int i = 0; i < commSize; i++)
370 vtxDist_[i+1] += vtxDist_[i];
376 template <
typename Adapter>
384 const ParameterList &pl = env_->getParameters();
385 const Teuchos::ParameterEntry *pe = pl.getEntryPtr(
"quotient_threshold");
387 threshold_ = pe->getValue<
int>(&threshold_);
390 nActiveRanks_ = std::ceil((
double) nGlobalVertices_ / threshold_);
391 size_t avgVertexShare = nGlobalVertices_ / nActiveRanks_;
392 size_t myVertexShare = 0;
394 int me = comm_->getRank();
395 int commSize = comm_->getSize();
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_;
405 destRank_ = me / (int) avgVertexShare;
406 if(destRank_ >= nActiveRanks_)
407 destRank_ = nActiveRanks_ - 1;
410 RCP<CommRequest<int>> *requests;
411 if(me < nActiveRanks_) {
415 startRank_ = me *
static_cast<int>(avgVertexShare);
416 endRank_ = (me+1) * static_cast<int>(avgVertexShare);
417 if(me == nActiveRanks_ - 1 )
418 endRank_ =
static_cast<int>(nGlobalVertices_);
419 myVertexShare = endRank_ - startRank_;
421 eOffsets_ = arcp(
new offset_t[myVertexShare+1], 0, myVertexShare+1,
true);
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),
433 Teuchos::send<int, offset_t>(*comm_, 1, &old_eOffsets_[nLocalVertices_], destRank_);
436 Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
439 for(
size_t i = 1; i <= myVertexShare; i++)
440 eOffsets_[i] += eOffsets_[i-1];
443 nLocalEdges_ = eOffsets_[myVertexShare];
446 eGids_ = arcp(
new gno_t[nLocalEdges_], 0, nLocalEdges_,
true);
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),
459 Teuchos::send<int, gno_t>(*comm_, old_nLocalEdges_, &old_eGids_[0], destRank_);
460 Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
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),
471 const scalar_t *wPtr;
474 old_vWeights_[0].getStridedList(wLen, wPtr, stride);
475 Teuchos::send<int, scalar_t>(*comm_, nLocalVertices_, wPtr, destRank_);
477 Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
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);
484 vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_,
true);
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),
496 old_eWeights_[0].getStridedList(wLen, wPtr, stride);
497 Teuchos::send<int, scalar_t>(*comm_, old_nLocalEdges_, wPtr, destRank_);
499 Teuchos::waitAll<int>(*comm_, Teuchos::arrayView(requests, myVertexShare));
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);
506 eWeights_ = arcp<input_t>(eweightInfo, 0, nWeightsPerEdge_,
true);
510 vGids_ = arcp(
new gno_t[myVertexShare], 0, myVertexShare,
true);
511 for(
int i = startRank_; i < endRank_; i++)
512 vGids_[i-startRank_] = i;
514 nLocalVertices_ = myVertexShare;
521 Teuchos::send<int, offset_t>(*comm_, 1, &eOffsets_[nLocalVertices_], destRank_);
524 Teuchos::send<int, gno_t>(*comm_, nLocalEdges_, &eGids_[0], destRank_);
527 const scalar_t *wPtr;
530 vWeights_[0].getStridedList(wLen, wPtr, stride);
531 Teuchos::send<int, scalar_t>(*comm_, nLocalVertices_, wPtr, destRank_);
534 eWeights_[0].getStridedList(wLen, wPtr, stride);
535 Teuchos::send<int, scalar_t>(*comm_, nLocalEdges_, wPtr, destRank_);
540 for (
int i = 0; i <= commSize; i++)
543 Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, commSize, &vtxDist_[1]);
544 for (
int i = 0; i < commSize; i++)
545 vtxDist_[i+1] += vtxDist_[i];
550 template <
typename Adapter>
551 void CommGraphModel<Adapter>::print()
553 std::ostream *os = env_->getDebugOStream();
555 int me = comm_->getRank();
558 <<
" Nvtx " << nLocalVertices_
559 <<
" Nedge " << nLocalEdges_
560 <<
" NVWgt " << nWeightsPerVertex_
561 <<
" NEWgt " << nWeightsPerEdge_
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] <<
" " ;
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] <<
" ";
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] <<
" ";
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
Defines the IdentifierAdapter interface.
size_t getGlobalNumVertices() const
Returns the global number vertices.
Defines the VectorAdapter interface.
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 getDestinationRank() const
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.
~CommGraphModel()
Destructor.
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
size_t getVertexList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const
Sets pointers to this process' 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.
int getNumActiveRanks() const
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
void getVertexDist(ArrayView< size_t > &vtxdist) const
Return the vtxDist array Array of size comm->getSize() + 1 Array[n+1] - Array[n] is number of vertice...