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;
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> &,
const RCP<
const Comm<int> > &,
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;
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...
void get2ndAdjsViewFromAdjs(const Teuchos::RCP< const MeshAdapter< User > > &ia, const RCP< const Comm< int > > comm, Zoltan2::MeshEntityType sourcetarget, Zoltan2::MeshEntityType through, Teuchos::ArrayRCP< typename MeshAdapter< User >::offset_t > &offsets, Teuchos::ArrayRCP< typename MeshAdapter< User >::gno_t > &adjacencyIds)
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.
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
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...
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...
use nonzeros as graph vertices
size_t getEdgeList(ArrayView< const gno_t > &edgeIds, ArrayView< const offset_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.
GraphModel(const RCP< const VectorAdapter< userCoord_t > > &, const RCP< const Environment > &, const RCP< const Comm< int > > &, modelFlag_t &)
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.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t