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;
92 typedef typename Adapter::offset_t offset_t;
110 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
114 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
118 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
122 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
125 throw std::runtime_error(
"cannot build GraphModel from VectorAdapter");
129 const RCP<const Environment> &env,
const RCP<
const Comm<int> > &comm,
132 throw std::runtime_error(
"cannot build GraphModel from IdentifierAdapter");
137 const RCP<const Comm<int> >
getComm() {
return comm_; }
178 ArrayView<const gno_t> &Ids,
179 ArrayView<input_t> &wgts)
const
181 Ids = vGids_.view(0, nLocalVertices_);
182 wgts = vWeights_.view(0, nWeightsPerVertex_);
183 return nLocalVertices_;
194 xyz = vCoords_.view(0, vCoordDim_);
195 return nLocalVertices_;
214 ArrayView<const offset_t> &offsets,
215 ArrayView<input_t> &wgts)
const
217 edgeIds = eGids_.view(0, nLocalEdges_);
218 offsets = eOffsets_.view(0, nLocalVertices_+1);
219 wgts = eWeights_.view(0, nWeightsPerEdge_);
229 vtxdist = vtxDist_();
230 if (vtxDist_.size() == 0) {
231 throw std::runtime_error(
"getVertexDist is available only "
232 "when consecutiveIdsRequired");
246 void shared_constructor(
const RCP<const Adapter>&ia,
modelFlag_t &modelFlags);
248 template <
typename AdapterWithCoords>
249 void shared_GetVertexCoords(
const AdapterWithCoords *ia);
253 const RCP<const Environment > env_;
254 const RCP<const Comm<int> > comm_;
262 size_t nLocalVertices_;
263 size_t nGlobalVertices_;
264 ArrayRCP<gno_t> vGids_;
268 int nWeightsPerVertex_;
269 ArrayRCP<input_t> vWeights_;
272 ArrayRCP<input_t> vCoords_;
279 size_t nGlobalEdges_;
280 ArrayRCP<gno_t> eGids_;
281 ArrayRCP<offset_t> eOffsets_;
287 int nWeightsPerEdge_;
288 ArrayRCP<input_t> eWeights_;
293 ArrayRCP<size_t> vtxDist_;
302 template <
typename Adapter>
305 const RCP<const Environment> &env,
306 const RCP<
const Comm<int> > &comm,
314 nWeightsPerVertex_(0),
334 if (symTranspose || symBipartite || vertexCols || vertexNz){
335 throw std::runtime_error(
"graph build option not yet implemented");
339 gno_t
const *vtxIds=NULL, *nborIds=NULL;
340 offset_t
const *offsets=NULL;
342 nLocalVertices_ = ia->getLocalNumIDs();
343 ia->getIDsView(vtxIds);
347 if (ia->CRSViewAvailable()) {
348 ia->getCRSView(offsets, nborIds);
352 throw std::runtime_error(
"Only MatrixAdapter::getCRSView is supported "
359 nLocalEdges_ = offsets[nLocalVertices_];
360 vGids_ = arcp_const_cast<gno_t>(
361 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
362 eGids_ = arcp_const_cast<gno_t>(
363 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
364 eOffsets_ = arcp_const_cast<offset_t>(
365 arcp<const offset_t>(offsets, 0, nLocalVertices_+1,
false));
368 nWeightsPerEdge_ = 0;
372 shared_constructor(ia, modelFlags);
375 if (ia->coordinatesAvailable()) {
377 shared_GetVertexCoords<adapterWithCoords_t>(ia->getCoordinateInput());
385 template <
typename Adapter>
388 const RCP<const Environment> &env,
389 const RCP<
const Comm<int> > &comm,
397 nWeightsPerVertex_(0),
414 env_->localInputAssertion(__FILE__, __LINE__,
415 "GraphModel from GraphAdapter is implemented only for "
416 "Graph Vertices as primary object, not for Graph Edges",
421 gno_t
const *vtxIds=NULL, *nborIds=NULL;
422 offset_t
const *offsets=NULL;
424 nLocalVertices_ = ia->getLocalNumVertices();
425 ia->getVertexIDsView(vtxIds);
426 ia->getEdgesView(offsets, nborIds);
431 nLocalEdges_ = offsets[nLocalVertices_];
432 vGids_ = arcp_const_cast<gno_t>(
433 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
434 eGids_ = arcp_const_cast<gno_t>(
435 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
436 eOffsets_ = arcp_const_cast<offset_t>(
437 arcp<const offset_t>(offsets, 0, nLocalVertices_+1,
false));
440 nWeightsPerEdge_ = ia->getNumWeightsPerEdge();
441 if (nWeightsPerEdge_ > 0){
442 input_t *wgts =
new input_t [nWeightsPerEdge_];
443 eWeights_ = arcp(wgts, 0, nWeightsPerEdge_,
true);
446 for (
int w=0; w < nWeightsPerEdge_; w++){
447 const scalar_t *ewgts=NULL;
450 ia->getEdgeWeightsView(ewgts, stride, w);
452 ArrayRCP<const scalar_t> wgtArray(ewgts, 0, nLocalEdges_,
false);
453 eWeights_[w] = input_t(wgtArray, stride);
457 shared_constructor(ia, modelFlags);
460 if (ia->coordinatesAvailable()) {
462 shared_GetVertexCoords<adapterWithCoords_t>(ia->getCoordinateInput());
469 template <
typename Adapter>
472 const RCP<const Environment> &env,
473 const RCP<
const Comm<int> > &comm,
481 nWeightsPerVertex_(0),
493 env_->timerStart(
MACRO_TIMERS,
"GraphModel constructed from MeshAdapter");
508 gno_t
const *vtxIds=NULL;
510 nLocalVertices_ = ia->getLocalNumOf(primaryEType);
511 ia->getIDsViewOf(primaryEType, vtxIds);
515 vGids_ = arcp_const_cast<gno_t>(
516 arcp<const gno_t>(vtxIds, 0, nLocalVertices_,
false));
520 if (!ia->avail2ndAdjs(primaryEType, secondAdjEType)) {
531 nLocalEdges_ = eOffsets_[nLocalVertices_];
538 gno_t
const *nborIds=NULL;
539 offset_t
const *offsets=NULL;
541 ia->get2ndAdjsView(primaryEType, secondAdjEType, offsets, nborIds);
544 nLocalEdges_ = offsets[nLocalVertices_];
545 eGids_ = arcp_const_cast<gno_t>(
546 arcp<const gno_t>(nborIds, 0, nLocalEdges_,
false));
547 eOffsets_ = arcp_const_cast<offset_t>(
548 arcp<const offset_t>(offsets, 0, nLocalVertices_+1,
false));
558 if (ia->avail2ndAdjs(primaryEType, secondAdjEType)) {
559 nWeightsPerEdge_ = ia->getNumWeightsPer2ndAdj(primaryEType, secondAdjEType);
560 if (nWeightsPerEdge_ > 0){
561 input_t *wgts =
new input_t [nWeightsPerEdge_];
562 eWeights_ = arcp(wgts, 0, nWeightsPerEdge_,
true);
565 for (
int w=0; w < nWeightsPerEdge_; w++){
566 const scalar_t *ewgts=NULL;
569 ia->get2ndAdjWeightsView(primaryEType, secondAdjEType,
572 ArrayRCP<const scalar_t> wgtArray(ewgts, 0,
573 nLocalEdges_*stride,
false);
574 eWeights_[w] = input_t(wgtArray, stride);
579 shared_constructor(ia, modelFlags);
583 shared_GetVertexCoords<adapterWithCoords_t>(&(*ia));
585 env_->timerStop(
MACRO_TIMERS,
"GraphModel constructed from MeshAdapter");
591 template <
typename Adapter>
593 const RCP<const Adapter> &ia,
603 size_t adapterNLocalEdges = nLocalEdges_;
604 ArrayRCP<gno_t> adapterVGids = vGids_;
605 ArrayRCP<gno_t> adapterEGids = eGids_;
606 ArrayRCP<offset_t> adapterEOffsets = eOffsets_;
607 ArrayRCP<input_t> adapterEWeights = eWeights_;
618 vGids_ = arcp(
new gno_t[nLocalVertices_],
619 0, nLocalVertices_,
true);
620 eGids_ = arcp(
new gno_t[adapterNLocalEdges],
621 0, adapterNLocalEdges,
true);
622 eOffsets_ = arcp(
new offset_t[nLocalVertices_+1],
623 0, nLocalVertices_+1,
true);
625 scalar_t **tmpEWeights = NULL;
626 if (nWeightsPerEdge_ > 0){
627 eWeights_ = arcp(
new input_t[nWeightsPerEdge_], 0,
628 nWeightsPerEdge_,
true);
631 tmpEWeights =
new scalar_t*[nWeightsPerEdge_];
632 for (
int w = 0; w < nWeightsPerEdge_; w++)
633 tmpEWeights[w] =
new scalar_t[adapterNLocalEdges];
637 std::unordered_map<gno_t, lno_t> globalToLocal(nLocalVertices_);
638 for (
size_t i = 0; i < nLocalVertices_; i++)
639 globalToLocal[adapterVGids[i]] = i;
644 for (
size_t i = 0; i < nLocalVertices_; i++) {
645 vGids_[i] = gno_t(i);
646 for (offset_t j = adapterEOffsets[i]; j < adapterEOffsets[i+1]; j++) {
648 if (removeSelfEdges && (adapterEGids[j] == adapterVGids[i]))
652 typename std::unordered_map<gno_t, lno_t>::iterator localidx;
653 if ((localidx = globalToLocal.find(adapterEGids[j])) !=
654 globalToLocal.end()) {
657 eGids_[ecnt] = localidx->second;
658 for (
int w = 0; w < nWeightsPerEdge_; w++)
659 tmpEWeights[w][ecnt] = adapterEWeights[w][j];
664 eOffsets_[i+1] = ecnt;
666 nLocalEdges_ = eOffsets_[nLocalVertices_];
667 if (nWeightsPerEdge_) {
668 for (
int w = 0; w < nWeightsPerEdge_; w++) {
669 ArrayRCP<const scalar_t> wgtArray(tmpEWeights[w],
670 0, adapterNLocalEdges,
true);
671 eWeights_[w] = input_t(wgtArray, 0);
673 delete [] tmpEWeights;
677 else if (consecutiveIdsRequired || removeSelfEdges || subsetGraph) {
685 if (consecutiveIdsRequired) {
687 vGids_ = arcp(
new gno_t[nLocalVertices_], 0, nLocalVertices_,
true);
690 int np = comm_->getSize();
691 vtxDist_ = arcp(
new size_t[np+1], 0, np+1,
true);
693 Teuchos::gatherAll(*comm_, 1, &nLocalVertices_, np, &vtxDist_[1]);
694 for (
int i = 0; i < np; i++)
695 vtxDist_[i+1] += vtxDist_[i];
701 eGids_ = arcp(
new gno_t[adapterNLocalEdges],
702 0, adapterNLocalEdges,
true);
704 scalar_t **tmpEWeights = NULL;
705 if (subsetGraph || removeSelfEdges) {
707 eOffsets_ = arcp(
new offset_t[nLocalVertices_+1],
708 0, nLocalVertices_+1,
true);
712 if (nWeightsPerEdge_ > 0){
713 eWeights_ = arcp(
new input_t[nWeightsPerEdge_], 0,
714 nWeightsPerEdge_,
true);
717 tmpEWeights =
new scalar_t*[nWeightsPerEdge_];
718 for (
int w = 0; w < nWeightsPerEdge_; w++)
719 tmpEWeights[w] =
new scalar_t[adapterNLocalEdges];
724 Teuchos::ArrayRCP<int> edgeRemoteRanks;
725 Teuchos::ArrayRCP<lno_t> edgeRemoteLids;
726 std::unordered_map<gno_t, size_t> edgeRemoteUniqueMap;
728 if (subsetGraph || consecutiveIdsRequired) {
731 gno_t myMinGID = std::numeric_limits<gno_t>::max();
732 size_t nVtx = adapterVGids.size();
733 for (
size_t i = 0; i < nVtx; i++)
734 if (adapterVGids[i] < myMinGID) myMinGID = adapterVGids[i];
737 reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_MIN, 1,
740 gno_t dummy = Teuchos::OrdinalTraits<gno_t>::invalid();
741 Tpetra::Map<lno_t,gno_t> vtxMap(dummy, adapterVGids(), minGID, comm_);
748 Teuchos::ArrayRCP<gno_t> edgeRemoteUniqueGids =
749 arcp(
new gno_t[adapterNLocalEdges], 0, adapterNLocalEdges,
true);
751 size_t nEdgeUnique = 0;
752 for (
size_t i = 0; i < adapterNLocalEdges; i++) {
753 if (edgeRemoteUniqueMap.find(adapterEGids[i]) ==
754 edgeRemoteUniqueMap.end()) {
755 edgeRemoteUniqueGids[nEdgeUnique] = adapterEGids[i];
756 edgeRemoteUniqueMap[adapterEGids[i]] = nEdgeUnique;
761 edgeRemoteRanks = arcp(
new int[nEdgeUnique], 0, nEdgeUnique,
true);
762 edgeRemoteLids = arcp(
new lno_t[nEdgeUnique], 0, nEdgeUnique,
true);
763 vtxMap.getRemoteIndexList(edgeRemoteUniqueGids(0, nEdgeUnique),
764 edgeRemoteRanks(), edgeRemoteLids());
769 int me = comm_->getRank();
770 for (
size_t i = 0; i < nLocalVertices_; i++) {
772 if (consecutiveIdsRequired)
773 vGids_[i] = vtxDist_[me] + i;
775 for (offset_t j = adapterEOffsets[i]; j < adapterEOffsets[i+1]; j++) {
777 if (removeSelfEdges && (adapterVGids[i] == adapterEGids[j]))
780 size_t remoteIdx = edgeRemoteUniqueMap[adapterEGids[j]];
782 if (subsetGraph && (edgeRemoteRanks[remoteIdx] == -1))
786 if (consecutiveIdsRequired)
789 eGids_[ecnt] = edgeRemoteLids[remoteIdx]
790 + vtxDist_[edgeRemoteRanks[remoteIdx]];
792 eGids_[ecnt] = adapterEGids[j];
794 if (subsetGraph || removeSelfEdges) {
796 for (
int w = 0; w < nWeightsPerEdge_; w++)
797 tmpEWeights[w][ecnt] = adapterEWeights[w][j];
802 if (subsetGraph || removeSelfEdges)
803 eOffsets_[i+1] = ecnt;
806 if (nWeightsPerEdge_ && (subsetGraph || removeSelfEdges)) {
807 for (
int w = 0; w < nWeightsPerEdge_; w++) {
808 ArrayRCP<const scalar_t> wgtArray(tmpEWeights[w],
809 0, nLocalEdges_,
true);
810 eWeights_[w] = input_t(wgtArray, 1);
812 delete [] tmpEWeights;
817 nWeightsPerVertex_ = ia->getNumWeightsPerID();
819 if (nWeightsPerVertex_ > 0){
820 input_t *weightInfo =
new input_t [nWeightsPerVertex_];
821 env_->localMemoryAssertion(__FILE__, __LINE__, nWeightsPerVertex_,
824 for (
int idx=0; idx < nWeightsPerVertex_; idx++){
825 bool useNumNZ = ia->useDegreeAsWeight(idx);
827 scalar_t *wgts =
new scalar_t [nLocalVertices_];
828 env_->localMemoryAssertion(__FILE__, __LINE__, nLocalVertices_, wgts);
829 ArrayRCP<const scalar_t> wgtArray = arcp(wgts,
830 0, nLocalVertices_,
true);
831 for (
size_t i=0; i < nLocalVertices_; i++)
832 wgts[i] = eOffsets_[i+1] - eOffsets_[i];
833 weightInfo[idx] = input_t(wgtArray, 1);
838 ia->getWeightsView(
weights, stride, idx);
839 ArrayRCP<const scalar_t> wgtArray = arcp(
weights, 0,
840 stride*nLocalVertices_,
842 weightInfo[idx] = input_t(wgtArray, stride);
846 vWeights_ = arcp<input_t>(weightInfo, 0, nWeightsPerVertex_,
true);
851 nGlobalVertices_ = nLocalVertices_;
852 nGlobalEdges_ = nLocalEdges_;
855 reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
856 &nLocalVertices_, &nGlobalVertices_);
857 reduceAll<int, size_t>(*comm_, Teuchos::REDUCE_SUM, 1,
858 &nLocalEdges_, &nGlobalEdges_);
861 env_->memory(
"After construction of graph model");
866 template <
typename Adapter>
867 template <
typename AdapterWithCoords>
868 void GraphModel<Adapter>::shared_GetVertexCoords(
const AdapterWithCoords *ia)
872 vCoordDim_ = ia->getDimension();
875 input_t *coordInfo =
new input_t [vCoordDim_];
876 env_->localMemoryAssertion(__FILE__, __LINE__, vCoordDim_, coordInfo);
878 for (
int dim=0; dim < vCoordDim_; dim++){
879 const scalar_t *coords=NULL;
881 ia->getCoordinatesView(coords, stride, dim);
882 ArrayRCP<const scalar_t> coordArray = arcp(coords, 0,
883 stride*nLocalVertices_,
885 coordInfo[dim] = input_t(coordArray, stride);
888 vCoords_ = arcp<input_t>(coordInfo, 0, vCoordDim_,
true);
893 template <
typename Adapter>
894 void GraphModel<Adapter>::print()
899 std::ostream *os = env_->getDebugOStream();
901 int me = comm_->getRank();
904 <<
" " << (localGraph_ ?
"LOCAL GRAPH " :
"GLOBAL GRAPH ")
905 <<
" Nvtx " << nLocalVertices_
906 <<
" Nedge " << nLocalEdges_
907 <<
" NVWgt " << nWeightsPerVertex_
908 <<
" NEWgt " << nWeightsPerEdge_
909 <<
" CDim " << vCoordDim_
912 for (
size_t i = 0; i < nLocalVertices_; i++) {
913 *os << me <<
" " << i <<
" GID " << vGids_[i] <<
": ";
914 for (offset_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++)
915 *os << eGids_[j] <<
" " ;
919 if (nWeightsPerVertex_) {
920 for (
size_t i = 0; i < nLocalVertices_; i++) {
921 *os << me <<
" " << i <<
" VWGTS " << vGids_[i] <<
": ";
922 for (
int j = 0; j < nWeightsPerVertex_; j++)
923 *os << vWeights_[j][i] <<
" ";
928 if (nWeightsPerEdge_) {
929 for (
size_t i = 0; i < nLocalVertices_; i++) {
930 *os << me <<
" " << i <<
" EWGTS " << vGids_[i] <<
": ";
931 for (offset_t j = eOffsets_[i]; j < eOffsets_[i+1]; j++) {
932 *os << eGids_[j] <<
" (";
933 for (
int w = 0; w < nWeightsPerEdge_; w++)
934 *os << eWeights_[w][j] <<
" ";
942 for (
size_t i = 0; i < nLocalVertices_; i++) {
943 *os << me <<
" " << i <<
" COORDS " << vGids_[i] <<
": ";
944 for (
int j = 0; j < vCoordDim_; j++)
945 *os << vCoords_[j][i] <<
" ";
950 *os << me <<
" NO COORDINATES AVAIL " << std::endl;