|
Zoltan2
|
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_GraphAdapter.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, typename UserCoord=User> 00084 class XpetraCrsGraphAdapter : public GraphAdapter<User,UserCoord> { 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>::zgid_t zgid_t; 00093 typedef typename InputTraits<User>::part_t part_t; 00094 typedef typename InputTraits<User>::node_t node_t; 00095 typedef Xpetra::CrsGraph<lno_t, gno_t, node_t> xgraph_t; 00096 typedef GraphAdapter<User,UserCoord> base_adapter_t; 00097 typedef User user_t; 00098 typedef UserCoord userCoord_t; 00099 #endif 00100 00103 ~XpetraCrsGraphAdapter() { } 00104 00114 XpetraCrsGraphAdapter(const RCP<const User> &ingraph, 00115 int nVtxWeights=0, int nEdgeWeights=0); 00116 00129 void setWeights(const scalar_t *val, int stride, int idx); 00130 00146 void setVertexWeights(const scalar_t *val, int stride, int idx); 00147 00153 void setWeightIsDegree(int idx); 00154 00160 void setVertexWeightIsDegree(int idx); 00161 00184 void setEdgeWeights(const scalar_t *val, int stride, int idx); 00185 00188 RCP<const xgraph_t> getXpetraGraph() const { return graph_; } 00189 00192 RCP<const User> getUserGraph() const { return ingraph_; } 00193 00195 // The Adapter interface. 00197 00199 // The GraphAdapter interface. 00201 00202 // TODO: Assuming rows == objects; 00203 // TODO: Need to add option for columns or nonzeros? 00204 size_t getLocalNumVertices() const { return graph_->getNodeNumRows(); } 00205 00206 void getVertexIDsView(const zgid_t *&ids) const 00207 { 00208 ids = NULL; 00209 if (getLocalNumVertices()) 00210 ids = graph_->getRowMap()->getNodeElementList().getRawPtr(); 00211 } 00212 00213 size_t getLocalNumEdges() const { return graph_->getNodeNumEntries(); } 00214 00215 void getEdgesView(const lno_t *&offsets, const zgid_t *&adjIds) const 00216 { 00217 offsets = offs_.getRawPtr(); 00218 adjIds = (getLocalNumEdges() ? adjids_.getRawPtr() : NULL); 00219 } 00220 00221 int getNumWeightsPerVertex() const { return nWeightsPerVertex_;} 00222 00223 void getVertexWeightsView(const scalar_t *&weights, int &stride, 00224 int idx) const 00225 { 00226 env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index", 00227 idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION); 00228 size_t length; 00229 vertexWeights_[idx].getStridedList(length, weights, stride); 00230 } 00231 00232 bool useDegreeAsVertexWeight(int idx) const {return vertexDegreeWeight_[idx];} 00233 00234 int getNumWeightsPerEdge() const { return nWeightsPerEdge_;} 00235 00236 void getEdgeWeightsView(const scalar_t *&weights, int &stride, int idx) const 00237 { 00238 env_->localInputAssertion(__FILE__, __LINE__, "invalid weight index", 00239 idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION); 00240 size_t length; 00241 edgeWeights_[idx].getStridedList(length, weights, stride); 00242 } 00243 00244 00245 template <typename Adapter> 00246 void applyPartitioningSolution(const User &in, User *&out, 00247 const PartitioningSolution<Adapter> &solution) const; 00248 00249 private: 00250 00251 RCP<const User > ingraph_; 00252 RCP<const xgraph_t > graph_; 00253 RCP<const Comm<int> > comm_; 00254 00255 ArrayRCP<const lno_t> offs_; 00256 ArrayRCP<const zgid_t> adjids_; 00257 00258 int nWeightsPerVertex_; 00259 ArrayRCP<StridedData<lno_t, scalar_t> > vertexWeights_; 00260 ArrayRCP<bool> vertexDegreeWeight_; 00261 00262 int nWeightsPerEdge_; 00263 ArrayRCP<StridedData<lno_t, scalar_t> > edgeWeights_; 00264 00265 int coordinateDim_; 00266 ArrayRCP<StridedData<lno_t, scalar_t> > coords_; 00267 00268 // A default Environment for error messages. User-written 00269 // InputAdapter classes can use some other error return convention 00270 // if desired. 00271 RCP<const Environment> env_; 00272 }; 00273 00275 // Definitions 00277 00278 template <typename User, typename UserCoord> 00279 XpetraCrsGraphAdapter<User,UserCoord>::XpetraCrsGraphAdapter( 00280 const RCP<const User> &ingraph, int nVtxWgts, int nEdgeWgts): 00281 ingraph_(ingraph), graph_(), comm_() , offs_(), adjids_(), 00282 nWeightsPerVertex_(nVtxWgts), vertexWeights_(), vertexDegreeWeight_(), 00283 nWeightsPerEdge_(nEdgeWgts), edgeWeights_(), 00284 coordinateDim_(0), coords_(), 00285 env_(rcp(new Environment)) 00286 { 00287 typedef StridedData<lno_t,scalar_t> input_t; 00288 00289 graph_ = XpetraTraits<User>::convertToXpetra(ingraph_); 00290 comm_ = graph_->getComm(); 00291 size_t nvtx = graph_->getNodeNumRows(); 00292 size_t nedges = graph_->getNodeNumEntries(); 00293 00294 // Unfortunately we have to copy the offsets and edge Ids 00295 // because edge Ids are not usually stored in vertex id order. 00296 00297 size_t n = nvtx + 1; 00298 lno_t *offs = new lno_t [n]; 00299 env_->localMemoryAssertion(__FILE__, __LINE__, n, offs); 00300 00301 zgid_t *adjids = NULL; 00302 if (nedges){ 00303 adjids = new zgid_t [nedges]; 00304 env_->localMemoryAssertion(__FILE__, __LINE__, nedges, adjids); 00305 } 00306 00307 offs[0] = 0; 00308 for (size_t v=0; v < nvtx; v++){ 00309 ArrayView<const lno_t> nbors; 00310 graph_->getLocalRowView(v, nbors); 00311 offs[v+1] = offs[v] + nbors.size(); 00312 for (lno_t e=offs[v], i=0; e < offs[v+1]; e++) 00313 adjids[e] = graph_->getColMap()->getGlobalElement(nbors[i++]); 00314 } 00315 00316 offs_ = arcp(offs, 0, n, true); 00317 adjids_ = arcp(adjids, 0, nedges, true); 00318 00319 if (nWeightsPerVertex_ > 0) { 00320 vertexWeights_ = 00321 arcp(new input_t[nWeightsPerVertex_], 0, nWeightsPerVertex_, true); 00322 vertexDegreeWeight_ = 00323 arcp(new bool[nWeightsPerVertex_], 0, nWeightsPerVertex_, true); 00324 for (int i=0; i < nWeightsPerVertex_; i++) 00325 vertexDegreeWeight_[i] = false; 00326 } 00327 00328 if (nWeightsPerEdge_ > 0) 00329 edgeWeights_ = arcp(new input_t[nWeightsPerEdge_], 0, nWeightsPerEdge_, true); 00330 } 00331 00333 template <typename User, typename UserCoord> 00334 void XpetraCrsGraphAdapter<User,UserCoord>::setWeights( 00335 const scalar_t *weightVal, int stride, int idx) 00336 { 00337 if (this->getPrimaryEntityType() == GRAPH_VERTEX) 00338 setVertexWeights(weightVal, stride, idx); 00339 else 00340 setEdgeWeights(weightVal, stride, idx); 00341 } 00342 00344 template <typename User, typename UserCoord> 00345 void XpetraCrsGraphAdapter<User,UserCoord>::setVertexWeights( 00346 const scalar_t *weightVal, int stride, int idx) 00347 { 00348 typedef StridedData<lno_t,scalar_t> input_t; 00349 env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index", 00350 idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION); 00351 size_t nvtx = getLocalNumVertices(); 00352 ArrayRCP<const scalar_t> weightV(weightVal, 0, nvtx*stride, false); 00353 vertexWeights_[idx] = input_t(weightV, stride); 00354 } 00355 00357 template <typename User, typename UserCoord> 00358 void XpetraCrsGraphAdapter<User,UserCoord>::setWeightIsDegree( 00359 int idx) 00360 { 00361 if (this->getPrimaryEntityType() == GRAPH_VERTEX) 00362 setVertexWeightIsDegree(idx); 00363 else { 00364 std::ostringstream emsg; 00365 emsg << __FILE__ << "," << __LINE__ 00366 << " error: setWeightIsNumberOfNonZeros is supported only for" 00367 << " vertices" << std::endl; 00368 throw std::runtime_error(emsg.str()); 00369 } 00370 } 00371 00373 template <typename User, typename UserCoord> 00374 void XpetraCrsGraphAdapter<User,UserCoord>::setVertexWeightIsDegree( 00375 int idx) 00376 { 00377 env_->localInputAssertion(__FILE__, __LINE__, "invalid vertex weight index", 00378 idx >= 0 && idx < nWeightsPerVertex_, BASIC_ASSERTION); 00379 00380 vertexDegreeWeight_[idx] = true; 00381 } 00382 00384 template <typename User, typename UserCoord> 00385 void XpetraCrsGraphAdapter<User,UserCoord>::setEdgeWeights( 00386 const scalar_t *weightVal, int stride, int idx) 00387 { 00388 typedef StridedData<lno_t,scalar_t> input_t; 00389 env_->localInputAssertion(__FILE__, __LINE__, "invalid edge weight index", 00390 idx >= 0 && idx < nWeightsPerEdge_, BASIC_ASSERTION); 00391 size_t nedges = getLocalNumEdges(); 00392 ArrayRCP<const scalar_t> weightV(weightVal, 0, nedges*stride, false); 00393 edgeWeights_[idx] = input_t(weightV, stride); 00394 } 00395 00397 template <typename User, typename UserCoord> 00398 template<typename Adapter> 00399 void XpetraCrsGraphAdapter<User,UserCoord>::applyPartitioningSolution( 00400 const User &in, User *&out, 00401 const PartitioningSolution<Adapter> &solution) const 00402 { 00403 // Get an import list 00404 00405 size_t len = solution.getLocalNumberOfIds(); 00406 const zgid_t *gids = solution.getIdList(); 00407 const part_t *parts = solution.getPartList(); 00408 ArrayRCP<zgid_t> gidList = arcp(const_cast<zgid_t *>(gids), 0, len, false); 00409 ArrayRCP<part_t> partList = arcp(const_cast<part_t *>(parts), 0, len, 00410 false); 00411 00412 ArrayRCP<lno_t> dummyIn; 00413 ArrayRCP<zgid_t> importList; 00414 ArrayRCP<lno_t> dummyOut; 00415 size_t numNewVtx; 00416 const RCP<const Comm<int> > comm = graph_->getComm(); 00417 00418 try{ 00419 numNewVtx = solution.convertSolutionToImportList( 00420 0, dummyIn, importList, dummyOut); 00421 } 00422 Z2_FORWARD_EXCEPTIONS; 00423 00424 RCP<const User> inPtr = rcp(&in, false); 00425 00426 RCP<const User> outPtr = XpetraTraits<User>::doMigration( 00427 inPtr, numNewVtx, importList.getRawPtr()); 00428 00429 out = const_cast<User *>(outPtr.get()); 00430 outPtr.release(); 00431 } 00432 00433 } //namespace Zoltan2 00434 00435 #endif
1.7.6.1