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_XPETRACRSGRAPHADAPTER_HPP_
00051 #define _ZOLTAN2_XPETRACRSGRAPHADAPTER_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 XpetraCrsGraphAdapter : public GraphAdapter<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 GraphAdapter<User> base_adapter_t;
00096   typedef User user_t;
00097 #endif
00098 
00101   ~XpetraCrsGraphAdapter() { }
00102 
00110   XpetraCrsGraphAdapter(const RCP<const User> &ingraph);
00111 
00152   XpetraCrsGraphAdapter(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   XpetraCrsGraphAdapter(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(const scalar_t *val, int stride, int idx);
00223 
00246   void setEdgeWeights(const scalar_t *val, int stride, int idx);
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 Adapter interface.
00282 
00284   // The GraphAdapter interface.
00286 
00287   // TODO:  Assuming rows == objects; 
00288   // TODO:  Need to add option for columns or nonzeros?
00289   size_t getLocalNumVertices() const { return graph_->getNodeNumRows(); }
00290 
00291   void getVertexIDsView(const gid_t *&ids) const 
00292   {
00293     ids = NULL;
00294     if (getLocalNumVertices())
00295       ids = graph_->getRowMap()->getNodeElementList().getRawPtr();
00296   }
00297 
00298   size_t getLocalNumEdges() const { return graph_->getNodeNumEntries(); }
00299 
00300   void getEdgeView(const lno_t *&offsets, const gid_t *&adjIds) const
00301   {
00302     adjIds = NULL;
00303     offsets = NULL;
00304     if (getLocalNumVertices()) {
00305       offsets = offs_.getRawPtr();
00306       adjIds = adjids_.getRawPtr();
00307     }
00308   }
00309 
00310   int getNumWeightsPerVertex() const { return vertexWeightDim_;}
00311 
00312   void getVertexWeightsView(const scalar_t *&weights, int &stride,
00313                             int idx) const
00314   {
00315     env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
00316       idx >= 0 && idx < vertexWeightDim_, BASIC_ASSERTION);
00317     size_t length;
00318     vertexWeights_[idx].getStridedList(length, weights, stride);
00319   }
00320 
00321 
00322   int getNumWeightsPerEdge() const { return edgeWeightDim_;}
00323 
00324   void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const
00325   {
00326     env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index",
00327       idx >= 0 && idx < edgeWeightDim_, BASIC_ASSERTION);
00328     size_t length;
00329     edgeWeights_[idx].getStridedList(length, weights, stride);
00330   }
00331 
00332 
00333   int getDimension() const { return coordinateDim_; }
00334 
00335   void getVertexCoordinatesView(const scalar_t *&coords, int &stride,
00336                                 int idx) const
00337   {
00338     env_->localInputAssertion(__FILE__, __LINE__, 
00339       "invalid coordinate dimension",
00340       idx >= 0 && idx < coordinateDim_, BASIC_ASSERTION);
00341     size_t length;
00342     coords_[idx].getStridedList(length, coords, stride);
00343   }
00344 
00345   template <typename Adapter>
00346     size_t applyPartitioningSolution(const User &in, User *&out,
00347       const PartitioningSolution<Adapter> &solution) const;
00348 
00349 private:
00350 
00351   void initializeData(
00352     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00353     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00354     vector<const scalar_t *> &coords,  vector<int> &coordStrides);
00355 
00356   RCP<const User > ingraph_;
00357   RCP<const xgraph_t > graph_;
00358   RCP<const Comm<int> > comm_;
00359 
00360   ArrayRCP<const lno_t> offs_;
00361   ArrayRCP<const gid_t> adjids_;
00362 
00363   int vertexWeightDim_;
00364   ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_;
00365 
00366   int edgeWeightDim_;
00367   ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_;
00368 
00369   int coordinateDim_;
00370   ArrayRCP<StridedData<lno_t, scalar_t> > coords_;
00371 
00372   // A default Environment for error messages.  User-written
00373   // InputAdapter classes can use some other error return convention
00374   // if desired.
00375   RCP<const Environment> env_;
00376 };
00377 
00379 // Definitions
00381 
00382 template <typename User>
00383   XpetraCrsGraphAdapter<User>::XpetraCrsGraphAdapter(
00384     const RCP<const User> &ingraph):
00385       ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
00386       vertexWeightDim_(0), vertexWeights_(),
00387       edgeWeightDim_(0), edgeWeights_(),
00388       coordinateDim_(0), coords_(),
00389       env_(rcp(new Environment))
00390 {
00391   vector<const scalar_t *> emptyValues;
00392   vector<int> emptyStrides;
00393 
00394   initializeData(emptyValues, emptyStrides, emptyValues, emptyStrides,
00395     emptyValues, emptyStrides);
00396 }
00397 
00398 template <typename User>
00399   XpetraCrsGraphAdapter<User>::XpetraCrsGraphAdapter(
00400   const RCP<const User> &ingraph,
00401     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00402     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides):
00403       ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
00404       vertexWeightDim_(vWeights.size()), vertexWeights_(),
00405       edgeWeightDim_(eWeights.size()), edgeWeights_(),
00406       coordinateDim_(0), coords_(),
00407       env_(rcp(new Environment))
00408 {
00409   vector<const scalar_t *> emptyValues;
00410   vector<int> emptyStrides;
00411 
00412   initializeData(vWeights, vWeightStrides, eWeights, eWeightStrides,
00413     emptyValues, emptyStrides);
00414 }
00415 
00416 template <typename User>
00417   XpetraCrsGraphAdapter<User>::XpetraCrsGraphAdapter(
00418     const RCP<const User> &ingraph,
00419     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00420     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00421     vector<const scalar_t *> &coords,  vector<int> &coordStrides):
00422       ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(),
00423       vertexWeightDim_(vWeights.size()), vertexWeights_(),
00424       edgeWeightDim_(eWeights.size()), edgeWeights_(),
00425       coordinateDim_(coords.size()), coords_(),
00426       env_(rcp(new Environment))
00427 {
00428   initializeData(vWeights, vWeightStrides, eWeights, eWeightStrides,
00429     coords, coordStrides);
00430 }
00431 
00432 template <typename User>
00433   void XpetraCrsGraphAdapter<User>::initializeData(
00434     vector<const scalar_t *> &vWeights,  vector<int> &vWeightStrides,
00435     vector<const scalar_t *> &eWeights,  vector<int> &eWeightStrides,
00436     vector<const scalar_t *> &coords,  vector<int> &coordStrides)
00437 {
00438   env_->localInputAssertion(__FILE__, __LINE__, 
00439     "invalid number of dimensions", 
00440     vertexWeightDim_ >= 0 && edgeWeightDim_ >= 0 && coordinateDim_ >= 0, 
00441     BASIC_ASSERTION);
00442 
00443   typedef StridedData<lno_t,scalar_t> input_t;
00444 
00445   if (vertexWeightDim_)
00446     vertexWeights_ = 
00447       arcp(new input_t [vertexWeightDim_], 0, vertexWeightDim_, true);
00448 
00449   if (edgeWeightDim_)
00450     edgeWeights_ = 
00451       arcp(new input_t [edgeWeightDim_], 0, edgeWeightDim_, true);
00452 
00453   if (coordinateDim_)
00454     coords_ = 
00455       arcp(new input_t [coordinateDim_], 0, coordinateDim_, true);
00456 
00457   graph_ = XpetraTraits<User>::convertToXpetra(ingraph_);
00458   comm_ = graph_->getComm();
00459   size_t nvtx = graph_->getNodeNumRows();
00460   size_t nedges = graph_->getNodeNumEntries();
00461 
00462   // Unfortunately we have to copy the offsets and edge Ids
00463   // because edge Ids are not usually stored in vertex id order.
00464 
00465   size_t n = nvtx + 1;
00466   lno_t *offs = new lno_t [n];
00467   env_->localMemoryAssertion(__FILE__, __LINE__, n, offs);
00468 
00469   gid_t *adjids = NULL;
00470   if (nedges){
00471     adjids = new gid_t [nedges];
00472     env_->localMemoryAssertion(__FILE__, __LINE__, nedges, adjids);
00473   }
00474 
00475   offs[0] = 0;
00476   for (size_t v=0; v < nvtx; v++){
00477     ArrayView<const lno_t> nbors;
00478     graph_->getLocalRowView(v, nbors);
00479     offs[v+1] = offs[v] + nbors.size();
00480     for (lno_t e=offs[v], i=0; e < offs[v+1]; e++)
00481       adjids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]);
00482   }
00483 
00484   offs_ = arcp(offs, 0, n, true);
00485   adjids_ = arcp(adjids, 0, nedges, true);
00486 
00487   int stride = 1;
00488   for (int dim=0; dim < coordinateDim_; dim++){
00489     if (coordStrides.size())
00490       stride = coordStrides[dim];
00491     ArrayRCP<const scalar_t> coordV(coords[dim], 0, nvtx, false);
00492     coords_[dim] = input_t(coordV, stride);
00493   }
00494 
00495   stride = 1;
00496   for (int dim=0; dim < vertexWeightDim_; dim++){
00497     if (vWeightStrides.size())
00498       stride = vWeightStrides[dim];
00499     ArrayRCP<const scalar_t> wgtV(vWeights[dim], 0, nvtx, false);
00500     vertexWeights_[dim] = input_t(wgtV, stride);
00501   }
00502 
00503   stride = 1;
00504   for (int dim=0; dim < edgeWeightDim_; dim++){
00505     if (eWeightStrides.size())
00506       stride = eWeightStrides[dim];
00507     ArrayRCP<const scalar_t> ewgtV(eWeights[dim], 0, nedges, false);
00508     edgeWeights_[dim] = input_t(ewgtV, stride);
00509   }
00510 }
00511 
00512 template <typename User>
00513   template<typename Adapter>
00514     size_t XpetraCrsGraphAdapter<User>::applyPartitioningSolution(
00515       const User &in, User *&out, 
00516       const PartitioningSolution<Adapter> &solution) const
00517 {
00518   // Get an import list
00519 
00520   size_t len = solution.getLocalNumberOfIds();
00521   const gid_t *gids = solution.getIdList();
00522   const partId_t *parts = solution.getPartList();
00523   ArrayRCP<gid_t> gidList = arcp(const_cast<gid_t *>(gids), 0, len, false);
00524   ArrayRCP<partId_t> partList = arcp(const_cast<partId_t *>(parts), 0, len, 
00525     false);
00526 
00527   ArrayRCP<lno_t> dummyIn;
00528   ArrayRCP<gid_t> importList;
00529   ArrayRCP<lno_t> dummyOut;
00530   size_t numNewVtx;
00531   const RCP<const Comm<int> > comm = graph_->getComm();
00532 
00533   try{
00534     numNewVtx = solution.convertSolutionToImportList(
00535       0, dummyIn, importList, dummyOut);
00536   }
00537   Z2_FORWARD_EXCEPTIONS;
00538 
00539   gno_t lsum = numNewVtx;
00540   gno_t gsum = 0;
00541   reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum, &gsum);
00542 
00543   RCP<const User> inPtr = rcp(&in, false);
00544 
00545   RCP<const User> outPtr = XpetraTraits<User>::doMigration(
00546    inPtr, lsum, importList.getRawPtr());
00547 
00548   out = const_cast<User *>(outPtr.get());
00549   outPtr.release();
00550   return numNewVtx;
00551 }
00552   
00553 }  //namespace Zoltan2
00554   
00555 #endif