Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_MappingSolution.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #ifndef _ZOLTAN2_MAPPINGSOLUTION_HPP_
51 #define _ZOLTAN2_MAPPINGSOLUTION_HPP_
52 #include "Teuchos_Comm.hpp"
53 #include "Zoltan2_Environment.hpp"
56 #include <unordered_map>
57 
58 namespace Zoltan2 {
59 
63 template <typename Adapter>
64 class MappingSolution : public PartitioningSolution<Adapter>
65 {
66 public:
67 
68 #ifndef DOXYGEN_SHOULD_SKIP_THIS
69  typedef typename Adapter::part_t part_t;
70  typedef typename Adapter::scalar_t t_scalar_t;
71  typedef typename Adapter::lno_t lno_t;
72  typedef typename Adapter::gno_t gno_t;
73 #endif
74 
78  const RCP<const Environment> &env,
79  const RCP<const Comm<int> > &comm,
80  const RCP<Algorithm<Adapter> > &algorithm = Teuchos::null)
81  :PartitioningSolution <Adapter> (
82  env, comm, 1, algorithm),
83  nParts(0), nRanks(1), myRank(comm->getRank()), maxPart(0),
84  mapping_algorithm(algorithm) {}
85 
86  virtual ~MappingSolution() {}
87 
88  typedef std::unordered_map<lno_t, int> rankmap_t;
89 
94  void getMyPartsView(part_t &numParts, part_t *&parts)
95  {
96  bool useAlg = true;
97 
98  // Check first whether this algorithm answers getMyPartsView.
99  if (mapping_algorithm != Teuchos::null) {
100  try {
101  mapping_algorithm->getMyPartsView(numParts, parts);
102  }
103  catch (NotImplemented &e) {
104  // It is OK if the algorithm did not implement this method;
105  // we'll get the information from the solution below.
106  useAlg = false;
107  }
109  }
110 
111  if (!useAlg) {
112 
113  // Algorithm did not implement this method.
114 
115  // Did the algorithm register a result with the solution?
116  if ((partsForRank==Teuchos::null) && (rankForPart==Teuchos::null)) {
117  numParts = 0;
118  parts = NULL;
119  throw std::runtime_error("No mapping solution available.");
120  }
121 
122  if (partsForRank == Teuchos::null) {
123  // Need to create the array since we haven't created it before.
124  Teuchos::Array<part_t> tmp;
125 
126  part_t cnt = 0;
127  for (typename rankmap_t::iterator it = rankForPart->begin();
128  it != rankForPart->end(); it++) {
129  if (it->second == myRank) {
130  tmp.push_back(it->first);
131  cnt++;
132  }
133  }
134  if (cnt)
135  partsForRank = arcp(&tmp[0], 0, cnt, true);
136  }
137 
138  numParts = partsForRank.size();
139  if (numParts)
140  parts = partsForRank.getRawPtr();
141  else
142  parts = NULL;
143  }
144  }
145 
152  int getRankForPart(part_t part) {
153 
154  int r = -1;
155 
156  // Check first whether this algorithm answers getRankForPart.
157  // Some algorithms can compute getRankForPart implicitly, without having
158  // to store the mapping explicitly. It is more efficient for them
159  // to implement getRankForPart themselves.
160  if (mapping_algorithm != Teuchos::null) {
161  try {
162  r = mapping_algorithm->getRankForPart(part);
163  }
164  catch (NotImplemented &e) {
165  // It is OK if the algorithm did not implement this method;
166  // we'll get the information from the solution below.
167  }
169  }
170 
171  if (r == -1) { // Algorithm did not implement this method
172  if (rankForPart==Teuchos::null) {
173  throw std::runtime_error("No mapping solution available.");
174  }
175 
176  if (part < 0 || part > maxPart) {
177  throw std::runtime_error("Invalid part number input to getRankForPart");
178  }
179 
180 
181  typename rankmap_t::iterator it;
182  if ((it = rankForPart->find(part)) != rankForPart->end())
183  r = it->second;
184  else
185  throw std::runtime_error("Invalid part number input to getRankForPart");
186  }
187  return r;
188  }
189 
192  // Methods for storing mapping data in the solution.
193  // Algorithms can store their data in the solution, or implement
194  // getRankForPart and getMyPartsView themselves.
195 
196  void setMap_PartsForRank(ArrayRCP<int> &idx, ArrayRCP<part_t> &parts) {
197  nRanks = idx.size() - 1;
198  nParts = parts.size();
199 
200  // Need data stored in unordered_map; create it
201  rankForPart = rcp(new rankmap_t(idx[nRanks]));
202 
203  maxPart = 0;
204  for (int i = 0; i < nRanks; i++) {
205  for (part_t j = idx[i]; j < idx[i+1]; j++) {
206  (*rankForPart)[parts[j]] = i;
207  if (parts[j] > maxPart) maxPart = parts[j];
208  }
209  }
210 
211  // Parts for this rank are already contiguous in parts arcp.
212  // Keep a view of them.
213  partsForRank = parts.persistingView(idx[myRank],idx[myRank+1]-idx[myRank]);
214  }
215 
223  void setMap_RankForLocalElements(ArrayRCP<int> &ranks) {
224  this->setParts(ranks);
225  }
226 
227 
228  void setMap_RankForPart(ArrayRCP<part_t> &parts, ArrayRCP<int> &ranks) {
229  nParts = parts.size();
230  int maxRank = 0;
231 
232  // Need data stored in unordered_map; create it
233  rankForPart = rcp(new rankmap_t(parts.size()));
234 
235  for (size_t i = 0; i < nParts; i++) {
236  (*rankForPart)[parts[i]] = ranks[i];
237  if (parts[i] > maxPart) maxPart = parts[i];
238  if (ranks[i] > maxRank) maxRank = ranks[i];
239  }
240  nRanks = maxRank+1;
241  }
242 
243  void setMap_RankForPart(RCP<rankmap_t> &rankmap) {
244  rankForPart = rankmap;
245  nParts = rankForPart.size();
246  int maxRank = 0;
247  typename rankmap_t::iterator it;
248  for (it = rankForPart->begin(); it != rankForPart->end(); it++) {
249  if (it->first > maxPart) maxPart = it->first;
250  if (it->second > maxRank) maxRank = it->second;
251  }
252  nRanks = maxRank+1;
253  }
254  // TODO: can add other methods for setting the map, particularly if decide
255  // TODO: to store only local procs and parts info rather than global info.
256 
257 private:
258 
259  part_t nParts; // Global number of parts
260  int nRanks; // Global number of ranks
261  int myRank; // This ranks
262  part_t maxPart; // Maximum part number
263 
264  // Ways to access the answer: it can be stored in MappingSolution or
265  // provided by the Algorithm.
266  ArrayRCP<part_t> partsForRankIdx;
267  ArrayRCP<part_t> partsForRank;
268  RCP<rankmap_t> rankForPart;
269 
270  const RCP<Algorithm<Adapter> > mapping_algorithm;
271 
272 };
273 
274 } // namespace Zoltan2
275 
276 #endif
void setMap_PartsForRank(ArrayRCP< int > &idx, ArrayRCP< part_t > &parts)
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
PartitionMapping maps a solution or an input distribution to ranks.
void setMap_RankForLocalElements(ArrayRCP< int > &ranks)
This is a mapping from local elements to ranks.
std::unordered_map< lno_t, int > rankmap_t
MappingSolution(const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, const RCP< Algorithm< Adapter > > &algorithm=Teuchos::null)
Constructor.
Defines the PartitioningSolution class.
void setMap_RankForPart(ArrayRCP< part_t > &parts, ArrayRCP< int > &ranks)
SparseMatrixAdapter_t::part_t part_t
A PartitioningSolution is a solution to a partitioning problem.
Exception thrown when a called base-class method is not implemented.
Algorithm defines the base class for all algorithms.
void setParts(ArrayRCP< part_t > &partList)
The algorithm uses setParts to set the solution.
int getRankForPart(part_t part)
Get the rank containing a part. Simplifying assumption: a part is wholy assigned to a rank; it is not...
void getMyPartsView(part_t &numParts, part_t *&parts)
Get the parts belonging to this rank.
Defines the Environment class.
void setMap_RankForPart(RCP< rankmap_t > &rankmap)