Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_AlgBlock.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef _ZOLTAN2_ALGBLOCK_HPP_
11 #define _ZOLTAN2_ALGBLOCK_HPP_
12 
13 #include <Zoltan2_Algorithm.hpp>
16 
17 #include <bitset>
18 #include <sstream>
19 #include <string>
20 
25 namespace Zoltan2{
26 
36 };
37 
55 template <typename Adapter>
56 class AlgBlock : public Algorithm<Adapter>
57 {
58 
59 private:
60  const RCP<const Environment> env;
61  const RCP<const Comm<int> > problemComm;
62  const RCP<const typename Adapter::base_adapter_t > adapter;
63 
64 public:
65  typedef typename Adapter::lno_t lno_t; // local ids
66  typedef typename Adapter::gno_t gno_t; // global ids
67  typedef typename Adapter::scalar_t scalar_t; // scalars
68  typedef typename Adapter::part_t part_t; // part numbers
69 
70  // Constructor
72  const RCP<const Environment> &env_,
73  const RCP<const Comm<int> > &problemComm_,
74  const RCP<const typename Adapter::base_adapter_t > &adapter_
75  ) :
76  env(env_), problemComm(problemComm_), adapter(adapter_)
77  {}
78 
79  // Partitioning method
80  void partition(const RCP<PartitioningSolution<Adapter> > &solution)
81  {
82  env->debug(DETAILED_STATUS, std::string("Entering AlgBlock"));
83 
84  int rank = env->myRank_;
85  int nprocs = env->numProcs_;
86 
88  // From the IdentifierModel we need:
89  // the number of gnos
90  // number of weights per gno
91  // the weights
92 
93  modelFlag_t modelFlag;
94  IdentifierModel<typename Adapter::base_adapter_t> ids(adapter, env, problemComm, modelFlag);
95  size_t numGnos = ids.getLocalNumIdentifiers();
96 
97  ArrayView<const gno_t> idList;
98  typedef StridedData<lno_t, scalar_t> input_t;
99  ArrayView<input_t> wgtList;
100 
101  ids.getIdentifierList(idList, wgtList);
102 
103  // If user supplied no weights, we use uniform weights.
104  bool uniformWeights = (wgtList.size() == 0);
105 
107  // Partitioning problem parameters of interest:
108  // objective
109  // imbalance_tolerance
110 
111  const Teuchos::ParameterList &pl = env->getParameters();
112  const Teuchos::ParameterEntry *pe;
113 
114  pe = pl.getEntryPtr("partitioning_objective");
115  if (pe) {
116  std::string po = pe->getValue<std::string>(&po);
117  if (po == std::string("balance_object_count"))
118  uniformWeights = true; // User requests that we ignore weights
119  }
120 
121  double imbalanceTolerance=1.1;
122  pe = pl.getEntryPtr("imbalance_tolerance");
123  if (pe) imbalanceTolerance = pe->getValue<double>(&imbalanceTolerance);
124 
126  // From the Solution we get part information:
127  // number of parts and part sizes
128 
129  size_t numGlobalParts = solution->getTargetGlobalNumberOfParts();
130 
131  Array<scalar_t> part_sizes(numGlobalParts);
132 
133  if (solution->criteriaHasUniformPartSizes(0))
134  for (unsigned int i=0; i<numGlobalParts; i++)
135  part_sizes[i] = 1.0 / numGlobalParts;
136  else
137  for (unsigned int i=0; i<numGlobalParts; i++)
138  part_sizes[i] = solution->getCriteriaPartSize(0, i);
139 
140  for (unsigned int i=1; i<numGlobalParts; i++)
141  part_sizes[i] += part_sizes[i-1];
142 
143  // TODO assertion that last part sizes is about equal to 1.0
144 
145 
147  // The algorithm
148  //
149  // Block partitioning algorithm lifted from zoltan/src/simple/block.c
150  // The solution is:
151  // a list of part numbers in gno order
152  // an imbalance for each weight
153 
154  scalar_t wtsum(0);
155 
156  if (!uniformWeights) {
157  for (size_t i=0; i<numGnos; i++)
158  wtsum += wgtList[0][i]; // [] operator knows stride
159  }
160  else
161  wtsum = static_cast<scalar_t>(numGnos);
162 
163  Array<scalar_t> scansum(nprocs+1, 0);
164 
165  Teuchos::gatherAll<int, scalar_t>(*problemComm, 1, &wtsum, nprocs,
166  scansum.getRawPtr()+1);
167 
168  /* scansum = sum of weights on lower processors, excluding self. */
169 
170  for (int i=2; i<=nprocs; i++)
171  scansum[i] += scansum[i-1];
172 
173  scalar_t globalTotalWeight = scansum[nprocs];
174 
175  if (env->getDebugLevel() >= VERBOSE_DETAILED_STATUS) {
176  std::ostringstream oss("Part sizes: ");
177  for (unsigned int i=0; i < numGlobalParts; i++)
178  oss << part_sizes[i] << " ";
179  oss << std::endl << std::endl << "Weights : ";
180  for (int i=0; i <= nprocs; i++)
181  oss << scansum[i] << " ";
182  oss << std::endl;
183  env->debug(VERBOSE_DETAILED_STATUS, oss.str());
184  }
185 
186  /* Loop over objects and assign part. */
187  part_t part = 0;
188  wtsum = scansum[rank];
189  Array<scalar_t> partTotal(numGlobalParts, 0);
190  ArrayRCP<part_t> gnoPart= arcp(new part_t[numGnos], 0, numGnos);
191 
192  env->memory("Block algorithm memory");
193 
194  for (size_t i=0; i<numGnos; i++){
195  scalar_t gnoWeight = (uniformWeights ? 1.0 : wgtList[0][i]);
196  /* wtsum is now sum of all lower-ordered object */
197  /* determine new part number for this object,
198  using the "center of gravity" */
199  while (unsigned(part)<numGlobalParts-1 &&
200  (wtsum+0.5*gnoWeight) > part_sizes[part]*globalTotalWeight)
201  part++;
202  gnoPart[i] = part;
203  partTotal[part] += gnoWeight;
204  wtsum += gnoWeight;
205  }
206 
208  // Done
209 
210  solution->setParts(gnoPart);
211 
212  env->debug(DETAILED_STATUS, std::string("Exiting AlgBlock"));
213  }
214 };
215 
216 } // namespace Zoltan2
217 
218 #endif
Adapter::lno_t lno_t
AlgBlock(const RCP< const Environment > &env_, const RCP< const Comm< int > > &problemComm_, const RCP< const typename Adapter::base_adapter_t > &adapter_)
Adapter::part_t part_t
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
Defines the PartitioningSolution class.
sub-steps, each method&#39;s entry and exit
SparseMatrixAdapter_t::part_t part_t
Defines the IdentifierModel interface.
A PartitioningSolution is a solution to a partitioning problem.
Adapter::scalar_t scalar_t
The StridedData class manages lists of weights or coordinates.
Algorithm defines the base class for all algorithms.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
Adapter::gno_t gno_t
void partition(const RCP< PartitioningSolution< Adapter > > &solution)
Partitioning method.
IdentifierModel defines the interface for all identifier models.
include more detail about sub-steps
blockParams
The boolean parameters of interest to the Block algorithm.
size_t getIdentifierList(ArrayView< const gno_t > &Ids, ArrayView< input_t > &wgts) const