50 #ifndef _ZOLTAN2_GRAPHMODEL_HPP_ 51 #define _ZOLTAN2_GRAPHMODEL_HPP_ 62 #include <unordered_map> 79 template <
typename Adapter>
84 #ifndef DOXYGEN_SHOULD_SKIP_THIS 85 typedef typename Adapter::scalar_t scalar_t;
86 typedef typename Adapter::gno_t gno_t;
87 typedef typename Adapter::lno_t lno_t;
88 typedef typename Adapter::node_t node_t;
89 typedef typename Adapter::user_t user_t;
90 typedef typename Adapter::userCoord_t userCoord_t;
109 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
113 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
117 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
121 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
124 throw std::runtime_error(
"cannot build GraphModel from VectorAdapter");
128 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
131 throw std::runtime_error(
"cannot build GraphModel from IdentifierAdapter");
136 const RCP<const Comm<int> >
getComm() {
return comm_; }
177 ArrayView<const gno_t> &Ids,
178 ArrayView<input_t> &wgts)
const 180 Ids = vGids_.view(0, nLocalVertices_);
181 wgts = vWeights_.view(0, nWeightsPerVertex_);
182 return nLocalVertices_;
193 xyz = vCoords_.view(0, vCoordDim_);
194 return nLocalVertices_;
213 ArrayView<const lno_t> &offsets,
214 ArrayView<input_t> &wgts)
const 216 edgeIds = eGids_.view(0, nLocalEdges_);
217 offsets = eOffsets_.view(0, nLocalVertices_+1);
218 wgts = eWeights_.view(0, nWeightsPerEdge_);
232 void shared_constructor(
const RCP<const Adapter>&ia,
modelFlag_t &modelFlags);
234 template <
typename AdapterWithCoords>
235 void shared_GetVertexCoords(
const AdapterWithCoords *ia);
239 const RCP<const Environment > env_;
240 const RCP<const Comm<int> > comm_;
248 size_t nLocalVertices_;
249 size_t nGlobalVertices_;
250 ArrayRCP<gno_t> vGids_;
254 int nWeightsPerVertex_;
255 ArrayRCP<input_t> vWeights_;
258 ArrayRCP<input_t> vCoords_;
265 size_t nGlobalEdges_;
266 ArrayRCP<gno_t> eGids_;
267 ArrayRCP<lno_t> eOffsets_;
273 int nWeightsPerEdge_;
274 ArrayRCP<input_t> eWeights_;
284 template <
typename Adapter>
287 const RCP<const Environment> &env,
288 const RCP<
const Comm<int> > &comm,
296 nWeightsPerVertex_(0),
315 if (symTranspose || symBipartite || vertexCols || vertexNz){
316 throw std::runtime_error(
"graph build option not yet implemented");
320 gno_t
const *vtxIds=NULL, *nborIds=NULL;
321 lno_t
const *offsets=NULL;
323 nLocalVertices_ = ia->getLocalNumIDs();
324 ia->getIDsView(vtxIds);
328 if (ia->CRSViewAvailable()) {
329 ia->getCRSView(offsets, nborIds);
333 throw std::runtime_error(
"Only MatrixAdapter::getCRSView is supported " 340 nLocalEdges_ = offsets[nLocalVertices_];
341 vGids_ = arcp_const_cast<gno_t>(
342 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
343 eGids_ = arcp_const_cast<gno_t>(
344 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
345 eOffsets_ = arcp_const_cast<lno_t>(
346 arcp<const lno_t>(offsets, 0, nLocalVertices_+1,
false));
349 nWeightsPerEdge_ = 0;
353 shared_constructor(ia, modelFlags);
356 if (ia->coordinatesAvailable()) {
358 shared_GetVertexCoords<adapterWithCoords_t>(ia->getCoordinateInput());
366 template <
typename Adapter>
369 const RCP<const Environment> &env,
370 const RCP<
const Comm<int> > &comm,
378 nWeightsPerVertex_(0),
394 env_->localInputAssertion(__FILE__, __LINE__,
395 "GraphModel from GraphAdapter is implemented only for " 396 "Graph Vertices as primary object, not for Graph Edges",
401 gno_t
const *vtxIds=NULL, *nborIds=NULL;
402 lno_t
const *offsets=NULL;
404 nLocalVertices_ = ia->getLocalNumVertices();
405 ia->getVertexIDsView(vtxIds);
406 ia->getEdgesView(offsets, nborIds);
411 nLocalEdges_ = offsets[nLocalVertices_];
412 vGids_ = arcp_const_cast<gno_t>(
413 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
414 eGids_ = arcp_const_cast<gno_t>(
415 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
416 eOffsets_ = arcp_const_cast<lno_t>(
417 arcp<const lno_t>(offsets, 0, nLocalVertices_+1,
false));
420 nWeightsPerEdge_ = ia->getNumWeightsPerEdge();
421 if (nWeightsPerEdge_ > 0){
422 input_t *wgts =
new input_t [nWeightsPerEdge_];
423 eWeights_ = arcp(wgts, 0, nWeightsPerEdge_,
true);
426 for (
int w=0; w < nWeightsPerEdge_; w++){
427 const scalar_t *ewgts=NULL;
430 ia->getEdgeWeightsView(ewgts, stride, w);
432 ArrayRCP<const scalar_t> wgtArray(ewgts, 0, nLocalEdges_,
false);
433 eWeights_[w] = input_t(wgtArray, stride);
437 shared_constructor(ia, modelFlags);
440 if (ia->coordinatesAvailable()) {
442 shared_GetVertexCoords<adapterWithCoords_t>(ia->getCoordinateInput());
449 template <
typename Adapter>
452 const RCP<const Environment> &env,
453 const RCP<
const Comm<int> > &comm,
461 nWeightsPerVertex_(0),
472 env_->timerStart(
MACRO_TIMERS,
"GraphModel constructed from MeshAdapter");
487 gno_t
const *vtxIds=NULL;
489 nLocalVertices_ = ia->getLocalNumOf(primaryEType);
490 ia->getIDsViewOf(primaryEType, vtxIds);
494 vGids_ = arcp_const_cast<gno_t>(
495 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
498 gno_t
const *nborIds=NULL;
499 lno_t
const *offsets=NULL;
501 if (!ia->avail2ndAdjs(primaryEType, secondAdjEType)) {
518 ia->get2ndAdjsView(primaryEType, secondAdjEType, offsets, nborIds);
524 nLocalEdges_ = offsets[nLocalVertices_];
525 eGids_ = arcp_const_cast<gno_t>(
526 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
527 eOffsets_ = arcp_const_cast<lno_t>(
528 arcp<const lno_t>(offsets, 0, nLocalVertices_+1,
false));
534 if (ia->avail2ndAdjs(primaryEType, secondAdjEType)) {
535 nWeightsPerEdge_ = ia->getNumWeightsPer2ndAdj(primaryEType, secondAdjEType);
536 if (nWeightsPerEdge_ > 0){
537 input_t *wgts =
new input_t [nWeightsPerEdge_];
538 eWeights_ = arcp(wgts, 0, nWeightsPerEdge_,
true);
541 for (
int w=0; w < nWeightsPerEdge_; w++){
542 const scalar_t *ewgts=NULL;
545 ia->get2ndAdjWeightsView(primaryEType, secondAdjEType,
548 ArrayRCP<const scalar_t> wgtArray(ewgts, 0,
549 nLocalEdges_*stride,
false);
550 eWeights_[w] = input_t(wgtArray, stride);
555 shared_constructor(ia, modelFlags);
559 shared_GetVertexCoords<adapterWithCoords_t>(&(*ia));
561 env_->timerStop(
MACRO_TIMERS,
"GraphModel constructed from MeshAdapter");
567 template <
typename Adapter>
569 const RCP<const Adapter> &ia,
579 size_t adapterNLocalEdges = nLocalEdges_;
580 ArrayRCP<gno_t> adapterVGids = vGids_;
581 ArrayRCP<gno_t> adapterEGids = eGids_;
582 ArrayRCP<lno_t> adapterEOffsets = eOffsets_;
583 ArrayRCP<input_t> adapterEWeights = eWeights_;
594 vGids_ = arcp(
new gno_t[nLocalVertices_],
595 0, nLocalVertices_,
true);
596 eGids_ = arcp(
new gno_t[adapterNLocalEdges],
597 0, adapterNLocalEdges,
true);
598 eOffsets_ = arcp(
new lno_t[nLocalVertices_+1],
599 0, nLocalVertices_+1,
true);
601 scalar_t **tmpEWeights = NULL;
602 if (nWeightsPerEdge_ > 0){
603 eWeights_ = arcp(
new input_t[nWeightsPerEdge_], 0,
604 nWeightsPerEdge_,
true);
607 tmpEWeights =
new scalar_t*[nWeightsPerEdge_];
608 for (
int w = 0; w < nWeightsPerEdge_; w++)
609 tmpEWeights[w] =
new scalar_t[adapterNLocalEdges];
613 std::unordered_map<gno_t, lno_t> globalToLocal(nLocalVertices_);
614 for (
size_t i = 0; i < nLocalVertices_; i++)
615 globalToLocal[adapterVGids[i]] = i;
620 for (
size_t i = 0; i < nLocalVertices_; i++) {
621 vGids_[i] = gno_t(i);
622 for (lno_t j = adapterEOffsets[i]; j < adapterEOffsets[i+1]; j++) {
624 if (removeSelfEdges && (adapterEGids[j] == adapterVGids[i]))
628 typename std::unordered_map<gno_t, lno_t>::iterator localidx;
629 if ((localidx = globalToLocal.find(adapterEGids[j])) !=
630 globalToLocal.end()) {
633 eGids_[ecnt] = localidx->second;
634 for (
int w = 0; w < nWeightsPerEdge_; w++)
635 tmpEWeights[w][ecnt] = adapterEWeights[w][j];
640 eOffsets_[i+1] = ecnt;
642 nLocalEdges_ = eOffsets_[nLocalVertices_];
643 if (nWeightsPerEdge_) {
644 for (
int w = 0; w < nWeightsPerEdge_; w++) {
645 ArrayRCP<const scalar_t> wgtArray(tmpEWeights[w],
646 0, adapterNLocalEdges,
true);
647 eWeights_[w] = input_t(wgtArray, 0);
649 delete [] tmpEWeights;
653 else if (consecutiveIdsRequired || removeSelfEdges || subsetGraph) {
661 Teuchos::ArrayRCP<size_t> vtxDist;
662 if (consecutiveIdsRequired) {
664 vGids_ = arcp(
new gno_t[nLocalVertices_], 0, nLocalVertices_,
true);
667 int np = comm_->getSize();
668 vtxDist = arcp(
new size_t[np+1], 0, np+1,
true);
670 Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, np, &vtxDist[1]);
671 for (
int i = 0; i < np; i++)
672 vtxDist[i+1] += vtxDist[i];
678 eGids_ = arcp(
new gno_t[adapterNLocalEdges],
679 0, adapterNLocalEdges,
true);
681 scalar_t **tmpEWeights = NULL;
682 if (subsetGraph || removeSelfEdges) {
684 eOffsets_ = arcp(
new lno_t[nLocalVertices_+1],
685 0, nLocalVertices_+1,
true);
689 if (nWeightsPerEdge_ > 0){
690 eWeights_ = arcp(
new input_t[nWeightsPerEdge_], 0,
691 nWeightsPerEdge_,
true);
694 tmpEWeights =
new scalar_t*[nWeightsPerEdge_];
695 for (
int w = 0; w < nWeightsPerEdge_; w++)
696 tmpEWeights[w] =
new scalar_t[adapterNLocalEdges];
701 Teuchos::ArrayRCP<int> edgeRemoteRanks;
702 Teuchos::ArrayRCP<lno_t> edgeRemoteLids;
703 std::unordered_map<gno_t, size_t> edgeRemoteUniqueMap;
705 if (subsetGraph || consecutiveIdsRequired) {
706 gno_t dummy = Teuchos::OrdinalTraits<gno_t>::invalid();
707 Tpetra::Map<lno_t,gno_t> vtxMap(dummy, adapterVGids(), 0, comm_);
714 Teuchos::ArrayRCP<gno_t> edgeRemoteUniqueGids =
715 arcp(
new gno_t[adapterNLocalEdges], 0, adapterNLocalEdges,
true);
717 size_t nEdgeUnique = 0;
718 for (
size_t i = 0; i < adapterNLocalEdges; i++) {
719 if (edgeRemoteUniqueMap.find(adapterEGids[i]) ==
720 edgeRemoteUniqueMap.end()) {
721 edgeRemoteUniqueGids[nEdgeUnique] = adapterEGids[i];
722 edgeRemoteUniqueMap[adapterEGids[i]] = nEdgeUnique;
727 edgeRemoteRanks = arcp(
new int[nEdgeUnique], 0, nEdgeUnique,
true);
728 edgeRemoteLids = arcp(
new lno_t[nEdgeUnique], 0, nEdgeUnique,
true);
729 vtxMap.getRemoteIndexList(edgeRemoteUniqueGids(0, nEdgeUnique),
730 edgeRemoteRanks(), edgeRemoteLids());
735 int me = comm_->getRank();
736 for (
size_t i = 0; i < nLocalVertices_; i++) {
738 if (consecutiveIdsRequired)
739 vGids_[i] = vtxDist[me] + i;
741 for (lno_t j = adapterEOffsets[i]; j < adapterEOffsets[i+1]; j++) {
743 if (removeSelfEdges && (adapterVGids[i] == adapterEGids[j]))
746 size_t remoteIdx = edgeRemoteUniqueMap[adapterEGids[j]];
748 if (subsetGraph && (edgeRemoteRanks[remoteIdx] == -1))
752 if (consecutiveIdsRequired)
755 eGids_[ecnt] = edgeRemoteLids[remoteIdx]
756 + vtxDist[edgeRemoteRanks[remoteIdx]];
758 eGids_[ecnt] = adapterEGids[j];
760 if (subsetGraph || removeSelfEdges) {
762 for (
int w = 0; w < nWeightsPerEdge_; w++)
763 tmpEWeights[w][ecnt] = adapterEWeights[w][j];
768 if (subsetGraph || removeSelfEdges)
769 eOffsets_[i+1] = ecnt;
772 if (nWeightsPerEdge_ && (subsetGraph || removeSelfEdges)) {
773 for (
int w = 0; w < nWeightsPerEdge_; w++) {
774 ArrayRCP<const scalar_t> wgtArray(tmpEWeights[w],
775 0, nLocalEdges_,
true);
776 eWeights_[w] = input_t(wgtArray, 1);
778 delete [] tmpEWeights;
783 nWeightsPerVertex_ = ia->getNumWeightsPerID();
785 if (nWeightsPerVertex_ > 0){
786 input_t *weightInfo =
new input_t [nWeightsPerVertex_];
787 env_->localMemoryAssertion(__FILE__, __LINE__, nWeightsPerVertex_,
790 for (
int idx=0; idx < nWeightsPerVertex_; idx++){
791 bool useNumNZ = ia->useDegreeAsWeight(idx);
793 scalar_t *wgts =
new scalar_t [nLocalVertices_];
794 env_->localMemoryAssertion(__FILE__, __LINE__, nLocalVertices_, wgts);
795 ArrayRCP<const scalar_t> wgtArray = arcp(wgts,
796 0, nLocalVertices_,
true);
797 for (
size_t i=0; i < nLocalVertices_; i++)
798 wgts[i] = eOffsets_[i+1] - eOffsets_[i];
799 weightInfo[idx] = input_t(wgtArray, 1);
802 const scalar_t *weights=NULL;
804 ia->getWeightsView(weights, stride, idx);
805 ArrayRCP<const scalar_t> wgtArray = arcp(weights, 0,
806 stride*nLocalVertices_,
808 weightInfo[idx] = input_t(wgtArray, stride);
812 vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_,
true);
817 nGlobalVertices_ = nLocalVertices_;
818 nGlobalEdges_ = nLocalEdges_;
821 reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
822 &nLocalVertices_, &nGlobalVertices_);
823 reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
824 &nLocalEdges_, &nGlobalEdges_);
827 env_->memory(
"After construction of graph model");
832 template <
typename Adapter>
833 template <
typename AdapterWithCoords>
838 vCoordDim_ = ia->getDimension();
841 input_t *coordInfo =
new input_t [vCoordDim_];
842 env_->localMemoryAssertion(__FILE__, __LINE__, vCoordDim_, coordInfo);
844 for (
int dim=0; dim < vCoordDim_; dim++){
845 const scalar_t *coords=NULL;
847 ia->getCoordinatesView(coords, stride, dim);
848 ArrayRCP<const scalar_t> coordArray = arcp(coords, 0,
849 stride*nLocalVertices_,
851 coordInfo[dim] = input_t(coordArray, stride);
854 vCoords_ = arcp<input_t>(coordInfo, 0, vCoordDim_,
true);
859 template <
typename Adapter>
865 std::ostream *os = env_->getDebugOStream();
867 int me = comm_->getRank();
870 <<
" " << (localGraph_ ?
"LOCAL GRAPH " :
"GLOBAL GRAPH ")
871 <<
" Nvtx " << nLocalVertices_
872 <<
" Nedge " << nLocalEdges_
873 <<
" NVWgt " << nWeightsPerVertex_
874 <<
" NEWgt " << nWeightsPerEdge_
875 <<
" CDim " << vCoordDim_
878 for (
size_t i = 0; i < nLocalVertices_; i++) {
879 *os << me <<
" " << i <<
" GID " << vGids_[i] <<
": ";
880 for (lno_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++)
881 *os << eGids_[j] <<
" " ;
885 if (nWeightsPerVertex_) {
886 for (
size_t i = 0; i < nLocalVertices_; i++) {
887 *os << me <<
" " << i <<
" VWGTS " << vGids_[i] <<
": ";
888 for (
int j = 0; j < nWeightsPerVertex_; j++)
889 *os << vWeights_[j][i] <<
" ";
894 if (nWeightsPerEdge_) {
895 for (
size_t i = 0; i < nLocalVertices_; i++) {
896 *os << me <<
" " << i <<
" EWGTS " << vGids_[i] <<
": ";
897 for (lno_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++) {
898 *os << eGids_[j] <<
" (";
899 for (
int w = 0; w < nWeightsPerEdge_; w++)
900 *os << eWeights_[w][j] <<
" ";
908 for (
size_t i = 0; i < nLocalVertices_; i++) {
909 *os << me <<
" " << i <<
" COORDS " << vGids_[i] <<
": ";
910 for (
int j = 0; j < vCoordDim_; j++)
911 *os << vCoords_[j][i] <<
" ";
916 *os << me <<
" NO COORDINATES AVAIL " << std::endl;
use columns as graph vertices
size_t getLocalNumEdges() const
Returns the number of edges on this process. In global or subset graphs, includes off-process edges...
size_t getVertexList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const
Sets pointers to this process' vertex Ids and their weights.
Time an algorithm (or other entity) as a whole.
IdentifierAdapter defines the interface for identifiers.
int getNumWeightsPerVertex() const
Returns the number (0 or greater) of weights per vertex.
size_t getGlobalNumObjects() const
Return the global number of objects.
fast typical checks for valid arguments
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
GraphModel(const RCP< const VectorAdapter< userCoord_t > > &ia, const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, modelFlag_t &flags)
MatrixAdapter defines the adapter interface for matrices.
Defines the Model interface.
GraphAdapter defines the interface for graph-based user data.
algorithm requires consecutive ids
Defines the MeshAdapter interface.
MeshAdapter defines the interface for mesh input.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
model must symmetrize input
Defines the IdentifierAdapter interface.
Defines the VectorAdapter interface.
GraphModel(const RCP< const MatrixAdapter< user_t, userCoord_t > > &ia, const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, modelFlag_t &modelFlags)
Constructor.
model must symmetrize input
size_t getGlobalNumVertices() const
Returns the global number vertices.
Defines helper functions for use in the models.
algorithm requires no self edges
int getCoordinateDim() const
Returns the dimension (0 to 3) of vertex coordinates.
size_t getVertexCoords(ArrayView< input_t > &xyz) const
Sets pointers to this process' vertex coordinates, if available. Order of coordinate info matches tha...
void get2ndAdjsViewFromAdjs(const Teuchos::RCP< const MeshAdapter< User > > &ia, const RCP< const Comm< int > > comm, Zoltan2::MeshEntityType sourcetarget, Zoltan2::MeshEntityType through, const typename MeshAdapter< User >::lno_t *&offsets, const typename MeshAdapter< User >::gno_t *&adjacencyIds)
use nonzeros as graph vertices
size_t getEdgeList(ArrayView< const gno_t > &edgeIds, ArrayView< const lno_t > &offsets, ArrayView< input_t > &wgts) const
Sets pointers to this process' edge (neighbor) global Ids, including off-process edges.
size_t getGlobalNumEdges() const
Returns the global number edges. For local graphs, the number of global edges is the number of local ...
VectorAdapter defines the interface for vector input.
The StridedData class manages lists of weights or coordinates.
size_t getLocalNumVertices() const
Returns the number vertices on this process.
GraphModel defines the interface required for graph models.
MeshEntityType
Enumerate entity types for meshes: Regions, Faces, Edges, or Vertices.
size_t getLocalNumObjects() const
Return the local number of objects.
Defines the MatrixAdapter interface.
The base class for all model classes.
int getNumWeightsPerEdge() const
Returns the number (0 or greater) of weights per edge.
Defines the GraphAdapter interface.
GraphModel(const RCP< const IdentifierAdapter< user_t > > &ia, const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, modelFlag_t &flags)
const RCP< const Comm< int > > getComm()
Return the communicator used by the model.
model represents graph within only one rank
This file defines the StridedData class.