Zoltan2 Version of the Day
Zoltan2_XpetraCrsGraphInput.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //   Zoltan2: A package of combinatorial algorithms for scientific computing
00006 //                  Copyright 2012 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Karen Devine      (kddevin@sandia.gov)
00039 //                    Erik Boman        (egboman@sandia.gov)
00040 //                    Siva Rajamanickam (srajama@sandia.gov)
00041 //
00042 // ***********************************************************************
00043 //
00044 // @HEADER
00045 
00050 #ifndef _ZOLTAN2_XPETRACRSGRAPHINPUT_HPP_
00051 #define _ZOLTAN2_XPETRACRSGRAPHINPUT_HPP_
00052 
00053 #include <Zoltan2_GraphInput.hpp>
00054 #include <Zoltan2_StridedData.hpp>
00055 #include <Zoltan2_XpetraTraits.hpp>
00056 #include <Zoltan2_Util.hpp>
00057 
00058 #include <Xpetra_CrsGraph.hpp>
00059 
00060 namespace Zoltan2 {
00061 
00083 template <typename User>
00084   class XpetraCrsGraphInput : public GraphInput<User> {
00085 
00086 public:
00087 
00088 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00089   typedef typename InputTraits<User>::scalar_t    scalar_t;
00090   typedef typename InputTraits<User>::lno_t    lno_t;
00091   typedef typename InputTraits<User>::gno_t    gno_t;
00092   typedef typename InputTraits<User>::gid_t    gid_t;
00093   typedef typename InputTraits<User>::node_t   node_t;
00094   typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> xgraph_t;
00095   typedef GraphInput<User>       base_adapter_t;
00096   typedef User user_t;
00097 #endif
00098 
00101   ~XpetraCrsGraphInput() { }
00102 
00110   XpetraCrsGraphInput(const RCP<const User> &ingraph);
00111 
00152   XpetraCrsGraphInput(const RCP<const User> &ingraph,
00153     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00154     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides);
00155 
00202   XpetraCrsGraphInput(const RCP<const User> &ingraph,
00203     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00204     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00205     vector<const scalar_t *> &coords,  vector<int> &coordStrides);
00206 
00222   void setVertexWeights(int dim, const scalar_t *val, int stride);
00223 
00246   void setEdgeWeights(int dim, const scalar_t *val, int stride);
00247 
00263   void setVertexCoordinates(int dim, const scalar_t *val, int stride);
00264 
00267   RCP<const xgraph_t> getXpetraGraph() const
00268   {
00269     return graph_;
00270   }
00271 
00274   RCP<const User> getUserGraph() const
00275   {
00276     return ingraph_;
00277   }
00278 
00280   // The InputAdapter interface.
00282 
00283   string inputAdapterName()const { return string("XpetraCrsGraph");}
00284 
00285   size_t getLocalNumberOfObjects() const { return getLocalNumberOfVertices();}
00286 
00287   int getNumberOfWeightsPerObject() const { return 0;}
00288 
00289   size_t getObjectWeights(int dim, const scalar_t *&wgt, int &stride) const
00290   {
00291     return getVertexWeights(dim, wgt, stride);
00292   }
00293 
00295   // The GraphInput interface.
00297 
00298   size_t getLocalNumberOfVertices() const { 
00299     return graph_->getNodeNumRows(); 
00300   }
00301 
00302   size_t getLocalNumberOfEdges() const { 
00303     return graph_->getNodeNumEntries();
00304   }
00305 
00306   int getVertexWeightDimension() const { 
00307     return vertexWeightDim_;
00308   }
00309 
00310   int getEdgeWeightDimension() const { 
00311     return edgeWeightDim_;
00312   }
00313 
00314   int getCoordinateDimension() const { 
00315     return coordinateDim_;
00316   }
00317 
00318   size_t getVertexListView(const gid_t *&ids,
00319     const lno_t *&offsets, const gid_t *& edgeId) const
00320   {
00321     size_t nvtx = getLocalNumberOfVertices();
00322     ids = edgeId = NULL;
00323     offsets = NULL;
00324 
00325     if (nvtx){
00326       ids = graph_->getRowMap()->getNodeElementList().getRawPtr();
00327       offsets = offs_.getRawPtr();
00328       edgeId = eids_.getRawPtr();
00329     }
00330     
00331     return nvtx;
00332   }
00333 
00334   size_t getVertexWeights(int dim,
00335     const scalar_t *&weights, int &stride) const
00336   {
00337     env_->localInputAssertion(__FILE__, __LINE__, "invalid weight dimension",
00338       dim >= 0 && dim < vertexWeightDim_, BASIC_ASSERTION);
00339 
00340     size_t length;
00341     vertexWeights_[dim].getStridedList(length, weights, stride);
00342     return length;
00343   }
00344 
00345   size_t getEdgeWeights(int dim,
00346     const scalar_t *&weights, int &stride) const
00347   {
00348     env_->localInputAssertion(__FILE__, __LINE__, "invalid weight dimension",
00349       dim >= 0 && dim < edgeWeightDim_, BASIC_ASSERTION);
00350 
00351     size_t length;
00352     edgeWeights_[dim].getStridedList(length, weights, stride);
00353     return length;
00354   }
00355 
00356   size_t getVertexCoordinates(int dim,
00357     const scalar_t *&coords, int &stride) const
00358   {
00359     env_->localInputAssertion(__FILE__, __LINE__, 
00360       "invalid coordinate dimension",
00361       dim >= 0 && dim < coordinateDim_, BASIC_ASSERTION);
00362 
00363     size_t length;
00364     coords_[dim].getStridedList(length, coords, stride);
00365     return length;
00366   }
00367 
00371   template<typename Adapter>
00372     size_t applyPartitioningSolution(const User &in, User *&out,
00373          const PartitioningSolution<Adapter> &solution) const;
00374 
00375 private:
00376 
00377   void initializeData(
00378     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00379     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00380     vector<const scalar_t *> &coords,  vector<int> &coordStrides);
00381 
00382   RCP<const User > ingraph_;
00383   RCP<const xgraph_t > graph_;
00384   RCP<const Comm<int> > comm_;
00385 
00386   ArrayRCP<const lno_t> offs_;
00387   ArrayRCP<const gid_t> eids_;
00388 
00389   int vertexWeightDim_;
00390   ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_;
00391 
00392   int edgeWeightDim_;
00393   ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_;
00394 
00395   int coordinateDim_;
00396   ArrayRCP<StridedData<lno_t, scalar_t> > coords_;
00397 
00398   // A default Environment for error messages.  User-written
00399   // InputAdapter classes can use some other error return convention
00400   // if desired.
00401   RCP<const Environment> env_;
00402 };
00403 
00405 // Definitions
00407 
00408 template <typename User>
00409   XpetraCrsGraphInput<User>::XpetraCrsGraphInput(
00410     const RCP<const User> &ingraph):
00411       ingraph_(ingraph), graph_(), comm_() , offs_(), eids_(),
00412       vertexWeightDim_(0), vertexWeights_(),
00413       edgeWeightDim_(0), edgeWeights_(),
00414       coordinateDim_(0), coords_(),
00415       env_(rcp(new Environment))
00416 {
00417   vector<const scalar_t *> emptyValues;
00418   vector<int> emptyStrides;
00419 
00420   initializeData(emptyValues, emptyStrides, emptyValues, emptyStrides,
00421     emptyValues, emptyStrides);
00422 }
00423 
00424 template <typename User>
00425   XpetraCrsGraphInput<User>::XpetraCrsGraphInput(
00426   const RCP<const User> &ingraph,
00427     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00428     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides):
00429       ingraph_(ingraph), graph_(), comm_() , offs_(), eids_(),
00430       vertexWeightDim_(vWeights.size()), vertexWeights_(),
00431       edgeWeightDim_(eWeights.size()), edgeWeights_(),
00432       coordinateDim_(0), coords_(),
00433       env_(rcp(new Environment))
00434 {
00435   vector<const scalar_t *> emptyValues;
00436   vector<int> emptyStrides;
00437 
00438   initializeData(vWeights, vWeightStrides, eWeights, eWeightStrides,
00439     emptyValues, emptyStrides);
00440 }
00441 
00442 template <typename User>
00443   XpetraCrsGraphInput<User>::XpetraCrsGraphInput(
00444     const RCP<const User> &ingraph,
00445     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00446     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00447     vector<const scalar_t *> &coords,  vector<int> &coordStrides):
00448       ingraph_(ingraph), graph_(), comm_() , offs_(), eids_(),
00449       vertexWeightDim_(vWeights.size()), vertexWeights_(),
00450       edgeWeightDim_(eWeights.size()), edgeWeights_(),
00451       coordinateDim_(coords.size()), coords_(),
00452       env_(rcp(new Environment))
00453 {
00454   initializeData(vWeights, vWeightStrides, eWeights, eWeightStrides,
00455     coords, coordStrides);
00456 }
00457 
00458 template <typename User>
00459   void XpetraCrsGraphInput<User>::initializeData(
00460     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00461     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00462     vector<const scalar_t *> &coords,  vector<int> &coordStrides)
00463 {
00464   env_->localInputAssertion(__FILE__, __LINE__, 
00465     "invalid number of dimensions", 
00466     vertexWeightDim_ >= 0 && edgeWeightDim_ >= 0 && coordinateDim_ >= 0, 
00467     BASIC_ASSERTION);
00468 
00469   typedef StridedData<lno_t,scalar_t> input_t;
00470 
00471   if (vertexWeightDim_)
00472     vertexWeights_ = 
00473       arcp(new input_t [vertexWeightDim_], 0, vertexWeightDim_, true);
00474 
00475   if (edgeWeightDim_)
00476     edgeWeights_ = 
00477       arcp(new input_t [edgeWeightDim_], 0, edgeWeightDim_, true);
00478 
00479   if (coordinateDim_)
00480     coords_ = 
00481       arcp(new input_t [coordinateDim_], 0, coordinateDim_, true);
00482 
00483   graph_ = XpetraTraits<User>::convertToXpetra(ingraph_);
00484   comm_ = graph_->getComm();
00485   size_t nvtx = graph_->getNodeNumRows();
00486   size_t nedges = graph_->getNodeNumEntries();
00487 
00488   // Unfortunately we have to copy the offsets and edge Ids
00489   // because edge Ids are not usually stored in vertex id order.
00490 
00491   size_t n = nvtx + 1;
00492   lno_t *offs = new lno_t [n];
00493   env_->localMemoryAssertion(__FILE__, __LINE__, n, offs);
00494 
00495   gid_t *eids = NULL;
00496   if (nedges){
00497     eids = new gid_t [nedges];
00498     env_->localMemoryAssertion(__FILE__, __LINE__, nedges, eids);
00499   }
00500 
00501   offs[0] = 0;
00502   for (size_t v=0; v < nvtx; v++){
00503     ArrayView<const lno_t> nbors;
00504     graph_->getLocalRowView(v, nbors);
00505     offs[v+1] = offs[v] + nbors.size();
00506     for (lno_t e=offs[v], i=0; e < offs[v+1]; e++)
00507       eids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]);
00508   }
00509 
00510   offs_ = arcp(offs, 0, n, true);
00511   eids_ = arcp(eids, 0, nedges, true);
00512 
00513   int stride = 1;
00514   for (int dim=0; dim < coordinateDim_; dim++){
00515     if (coordStrides.size())
00516       stride = coordStrides[dim];
00517     ArrayRCP<const scalar_t> coordV(coords[dim], 0, nvtx, false);
00518     coords_[dim] = input_t(coordV, stride);
00519   }
00520 
00521   stride = 1;
00522   for (int dim=0; dim < vertexWeightDim_; dim++){
00523     if (vWeightStrides.size())
00524       stride = vWeightStrides[dim];
00525     ArrayRCP<const scalar_t> wgtV(vWeights[dim], 0, nvtx, false);
00526     vertexWeights_[dim] = input_t(wgtV, stride);
00527   }
00528 
00529   stride = 1;
00530   for (int dim=0; dim < edgeWeightDim_; dim++){
00531     if (eWeightStrides.size())
00532       stride = eWeightStrides[dim];
00533     ArrayRCP<const scalar_t> ewgtV(eWeights[dim], 0, nedges, false);
00534     edgeWeights_[dim] = input_t(ewgtV, stride);
00535   }
00536 }
00537 
00538 template <typename User>
00539   template<typename Adapter>
00540     size_t XpetraCrsGraphInput<User>::applyPartitioningSolution(
00541       const User &in, User *&out, 
00542       const PartitioningSolution<Adapter> &solution) const
00543 {
00544   // Get an import list
00545 
00546   Zoltan2::Environment env;
00547   size_t len = solution.getLocalNumberOfIds();
00548   const gid_t *gids = solution.getIdList();
00549   const partId_t *parts = solution.getPartList();
00550   ArrayRCP<gid_t> gidList = arcp(const_cast<gid_t *>(gids), 0, len, false);
00551   ArrayRCP<partId_t> partList = arcp(const_cast<partId_t *>(parts), 0, len, 
00552     false);
00553 
00554   ArrayRCP<lno_t> dummyIn;
00555   ArrayRCP<gid_t> importList;
00556   ArrayRCP<lno_t> dummyOut;
00557   size_t numNewVtx;
00558   const RCP<const Comm<int> > comm = graph_->getComm();
00559 
00560   try{
00561     numNewVtx = solution.convertSolutionToImportList(
00562       0, dummyIn, importList, dummyOut);
00563   }
00564   Z2_FORWARD_EXCEPTIONS;
00565 
00566   gno_t lsum = numNewVtx;
00567   gno_t gsum = 0;
00568   reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum, &gsum);
00569 
00570   RCP<const User> inPtr = rcp(&in, false);
00571 
00572   RCP<const User> outPtr = XpetraTraits<User>::doMigration(
00573    inPtr, lsum, importList.getRawPtr());
00574 
00575   out = const_cast<User *>(outPtr.get());
00576   outPtr.release();
00577   return numNewVtx;
00578 }
00579   
00580 }  //namespace Zoltan2
00581   
00582 #endif