Proto  3.2
Proto_BoxPartition.H
Go to the documentation of this file.
1 #pragma once
2 #ifndef _PROTO_BOX_PARTITION_
3 #define _PROTO_BOX_PARTITION_
4 
5 #include "Proto_Morton.H"
6 #include <unordered_map>
7 namespace Proto
8 {
9  typedef Point PatchID;
10  /// Box Partition
11  /**
12  * This data structure defines the "layoutness" of a collection of patches.
13  * More concretely, Box Partition encapsulates the information of which tile locations
14  * in a domain have a patch, which tiles are empty, and which MPI processes are
15  * responsible for which patch.
16  *
17  * Two objects with the same (or equivalent) Box Partitions are "compatible" with one
18  * another in the sense of DataIterator because the two objects in question are guaranteed
19  * to have the same number of patches for a given MPI process.
20  */
22  {
23  public:
24 
25  // Constructor
26  inline BoxPartition(
27  const ProblemDomain& a_patchDomain);
28 
29  /// Constructor
30  /**
31  * Create a BoxPartition from a "patch domain" and an array of patches
32  * in that domain. Here patches are assumed to have a uniform size so as
33  * to evenly tile a rectangular layout. By default, patches will be distributed
34  * evenly across all available processes.
35  *
36  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
37  * \param a_patches A vector of Point each representing a patch
38  */
39  inline BoxPartition(
40  const ProblemDomain& a_patchDomain,
41  const std::vector<Point>& a_patches);
42 
43  /// Constructor
44  /**
45  * Create a BoxPartition from a "patch domain" and an array of patches
46  * in that domain. Here patches are assumed to have a uniform size so as
47  * to evenly tile a rectangular layout. Patches will be distributed evenly
48  * across the range of processes in <code>[a_startProc, a_endProc)</code>
49  *
50  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
51  * \param a_patches A vector of Point each representing a patch
52  */
53  inline BoxPartition(
54  const ProblemDomain& a_patchDomain,
55  const std::vector<Point>& a_patches,
56  unsigned int a_startProc,
57  unsigned int a_endProc);
58 
59  /// Constructor (Exteral Load Balancing)
60  inline BoxPartition(
61  const ProblemDomain& a_patchDomain,
62  const std::vector<std::pair<Point,unsigned int>>& a_assignedPatches);
63 
64  /// Define
65  /**
66  * Create a BoxPartition from a "patch domain" and an array of patches
67  * in that domain. Here patches are assumed to have a uniform size so as
68  * to evenly tile a rectangular layout. Patches will be distributed evenly
69  * across the range of processes in <code>[a_startProc, a_endProc)</code>
70  *
71  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
72  * \param a_patches A vector of Point each representing a patch
73  */
74  inline void define(
75  const ProblemDomain& a_patchDomain,
76  const std::vector<Point>& a_patches,
77  unsigned int a_startProc,
78  unsigned int a_endProc);
79 
80  /// Define
81  /**
82  * Create a BoxPartition from a set of patches that have already been assigned
83  * to processors. Use this function if load balancing is executed externally.
84  *
85  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
86  * \param a_assignedPatches A vector of patch-processor pairs
87  */
88  inline void define(
89  const ProblemDomain& a_patchDomain,
90  const std::vector<std::pair<Point,unsigned int>>& a_assignedPatches);
91 
92  /// Sort By Processor
93  /** Return a new BoxPartition that is identical to *this except that it is sorted
94  * by processor
95  */
96  inline std::shared_ptr<BoxPartition> sortByProc() const;
97 
98  inline bool isSorted() const { return m_procSorted; }
99  /// Load Balance
100  /**
101  * Rebalance the load of this by distributing the input patches evenly
102  * across the range of processes in <code>[a_startProc, a_endProc)</code>
103  * The input patches must be contained in the existing ProblemDomain of this
104  *
105  * \param a_patches A vector of patches represented as Points
106  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
107  * \param a_patches A vector of Point each representing a patch
108  */
109  inline void loadBalance(
110  std::vector<Point>& a_patches,
111  unsigned int a_startProc,
112  unsigned int a_endProc);
113 
114  /// Load Assign
115  /**
116  * Manually assign the load of this using the syntax
117  * <code> loadAssign(patches, P0, N0, P1, N1, ..., Pk, Nk) </code>
118  * where process Pi is assigned Ni boxes. The sum over all Ni should be
119  * equal to the length of the patch vector.
120  *
121  * \param a_patches A vector of patches represented as Points
122  * \param a_patchDomain A ProblemDomain where each Point corresponds to a Box
123  * \param a_patches A vector of Point each representing a patch
124  */
125  template<typename... vals>
126  inline void loadAssign(
127  std::vector<Point>& a_patches,
128  vals... args);
129 
130  /// Load Assign
131  /**
132  * Manually assign the load of this layout. The first input is a vector of
133  * <code>pair<int, unsigned int></code> where the first entry of each pair is a
134  * process and the second is the number of boxes to be assigned to that process.
135  * The second input is the set of patches themselves represented as Points.
136  *
137  * \param a_assignment A vector of proc-assignment pairs
138  * \param a_patches A vector of patches represented as Points
139  */
140  inline void loadAssign(
141  std::vector<std::pair<int, unsigned int>>& a_assignment,
142  std::vector<Point>& a_patches);
143 
144  /// Load Assign
145  /**
146  * Manually (re)assign the load of this layout. The input is a vector of
147  * <code>pair<int, unsigned int></code> where the first entry of each pair is a
148  * process and the second is the number of boxes to be assigned to that process.
149  * The patches themselves are unchanged by this function.
150  *
151  * \param a_assignment A vector of proc-assignment pairs
152  * \param a_patches A vector of patches represented as Points
153  */
154  inline void loadAssign(
155  std::vector<std::pair<int, unsigned int>>& a_assignment);
156 
157 
158  /// Compatibility Query
159  /**
160  * Determine if this has the same layout structure as another BoxPartition.
161  */
162  inline bool compatible(const BoxPartition& a_rhs);
163 
164  /// Number of Processes
165  /**
166  * Query the number of processes assigned to this BoxPartition
167  */
168  inline unsigned int numProcs() const;
169 
170  /// Number of Boxes (Global)
171  /**
172  * Query the number of patches in this BoxPartition across all processes
173  */
174  inline unsigned int numBoxes() const;
175 
176  /// Number of Boxes (Local)
177  /**
178  * Query the number of patches in this BoxPartition on a specified process
179  */
180  inline unsigned int numBoxes(unsigned int a_proc) const;
181 
182  /// Access Partition
183  /**
184  * Access the vector of pair<Point, unsigned int> which maps each patch
185  * (represented as a Point) to a process number
186  */
187  inline const std::vector<std::pair<Point, unsigned int>>& partition() const
188  { return m_partition; }
189 
190  /// Get Processor Starting Index
191  /**
192  * Get the index in global array at which a specified process's data begins.
193  * Returns this->size() if the processor is not assigned to this.
194  */
195  inline unsigned int procStartIndex(unsigned int a_proc) const;
196 
197  /// Get Processor Ending Index
198  /**
199  * Get the index in global array at which a specified process's data ends
200  * Returns this->size() if the processor is not assigned to this.
201  */
202  inline unsigned int procEndIndex(unsigned int a_proc) const;
203 
204  /// Get Global Index
205  /** Get the global index from a local index and processor number. Works even
206  * if the data in this is unsorted.
207  *
208  * */
209  inline unsigned int globalIndex(unsigned int a_localIndex, unsigned int a_proc);
210 
211  /// Get Local Index
212  /** Get the global index from a local index and processor number. Works even
213  * if the data in this is unsorted.
214  *
215  * */
216  inline unsigned int localIndex(unsigned int a_globalIndex, unsigned int a_proc);
217  /// Get Patch Index
218  /**
219  * Get the index in global array corresponding to a specified patch.
220  * Returns this->size() if the patch is not in this partition's domain.
221  */
222  inline unsigned int find(Point a_pt);
223 
224  inline const ProblemDomain& domain() const {return m_patchDomain; }
225 
226  /// Print
227  inline void print() const;
228 
229  /// Check If This Controls Load Balancing
230  inline bool doLoadBalance() const { return m_doLoadBalance; }
231  private:
232 
233  inline bool checkProcSorting(const std::vector<std::pair<Point, unsigned int>> a_data);
234 
235  template<typename... vals>
236  inline void unpack(
237  std::vector<Point>& a_patches,
238  unsigned int a_globalIndex,
239  int a_proc,
240  unsigned int a_num,
241  vals... a_args);
242 
243  inline void assign(
244  std::vector<Point>& a_patches,
245  unsigned int a_globalIndex,
246  int a_proc,
247  unsigned int a_num);
248 
249  bool m_procSorted = true;
250  bool m_doLoadBalance = true;
251  ProblemDomain m_patchDomain; ///< Domain in patch space
252  std::unordered_map<uint64_t, int> m_indexMap; ///< Maps Morton index to global index
253  std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> m_procMap; ///< Maps processor number to global index
254  std::vector<std::pair<Point, unsigned int>> m_partition; ///< Maps each patch to a proc
255  std::unordered_map<unsigned int, std::vector<unsigned int>> m_procMapUnsorted; ///< Same as procMap for unsorted data
256  };
257 
258 #include "implem/Proto_BoxPartitionImplem.H"
259 } // end namespace Proto
260 #endif //end include guard
void define(const ProblemDomain &a_patchDomain, const std::vector< std::pair< Point, unsigned int >> &a_assignedPatches)
Define.
Definition: Proto_BoxPartition.H:70
unsigned int find(Point a_pt)
Get Patch Index.
Definition: Proto_BoxPartition.H:324
bool doLoadBalance() const
Check If This Controls Load Balancing.
Definition: Proto_BoxPartition.H:230
const std::vector< std::pair< Point, unsigned int > > & partition() const
Access Partition.
Definition: Proto_BoxPartition.H:187
unsigned int globalIndex(unsigned int a_localIndex, unsigned int a_proc)
Get Global Index.
Definition: Proto_BoxPartition.H:299
void loadAssign(std::vector< Point > &a_patches, vals... args)
Load Assign.
Definition: Proto_BoxPartition.H:151
Point PatchID
Definition: Proto_BoxPartition.H:9
unsigned int numProcs() const
Number of Processes.
Definition: Proto_BoxPartition.H:251
Box Partition.
Definition: Proto_BoxPartition.H:21
std::vector< std::pair< Point, unsigned int > > m_partition
Maps each patch to a proc.
Definition: Proto_BoxPartition.H:254
ProblemDomain m_patchDomain
Domain in patch space.
Definition: Proto_BoxPartition.H:251
std::unordered_map< unsigned int, std::pair< unsigned int, unsigned int > > m_procMap
Maps processor number to global index.
Definition: Proto_BoxPartition.H:253
unsigned int procEndIndex(unsigned int a_proc) const
Get Processor Ending Index.
Definition: Proto_BoxPartition.H:290
bool isSorted() const
Definition: Proto_BoxPartition.H:98
void assign(std::vector< Point > &a_patches, unsigned int a_globalIndex, int a_proc, unsigned int a_num)
Definition: Proto_BoxPartition.H:133
std::shared_ptr< BoxPartition > sortByProc() const
Sort By Processor.
Definition: Proto_BoxPartition.H:121
unsigned int numBoxes() const
Number of Boxes (Global)
Definition: Proto_BoxPartition.H:261
bool checkProcSorting(const std::vector< std::pair< Point, unsigned int >> a_data)
Definition: Proto_BoxPartition.H:58
void unpack(std::vector< Point > &a_patches, unsigned int a_globalIndex, int a_proc, unsigned int a_num, vals... a_args)
Definition: Proto_BoxPartition.H:364
bool compatible(const BoxPartition &a_rhs)
Compatibility Query.
Definition: Proto_BoxPartition.H:226
void loadBalance(std::vector< Point > &a_patches, unsigned int a_startProc, unsigned int a_endProc)
Load Balance.
Definition: Proto_BoxPartition.H:197
Definition: Proto_Array.H:17
void define(const ProblemDomain &a_patchDomain, const std::vector< Point > &a_patches, unsigned int a_startProc, unsigned int a_endProc)
Define.
Definition: Proto_BoxPartition.H:37
std::unordered_map< unsigned int, std::vector< unsigned int > > m_procMapUnsorted
Same as procMap for unsorted data.
Definition: Proto_BoxPartition.H:255
Integer Valued Vector.
Definition: Proto_Point.H:24
bool m_doLoadBalance
Definition: Proto_BoxPartition.H:250
void print() const
Print.
Definition: Proto_BoxPartition.H:339
BoxPartition(const ProblemDomain &a_patchDomain)
Definition: Proto_BoxPartition.H:2
unsigned int procStartIndex(unsigned int a_proc) const
Get Processor Starting Index.
Definition: Proto_BoxPartition.H:281
unsigned int localIndex(unsigned int a_globalIndex, unsigned int a_proc)
Get Local Index.
Definition: Proto_BoxPartition.H:309
bool m_procSorted
Definition: Proto_BoxPartition.H:249
Represents a rectangular domain over which a problem can be defined, including periodic images...
Definition: Proto_ProblemDomain.H:22
std::unordered_map< uint64_t, int > m_indexMap
Maps Morton index to global index.
Definition: Proto_BoxPartition.H:252
const ProblemDomain & domain() const
Definition: Proto_BoxPartition.H:224