WARPXM v1.10.0
Loading...
Searching...
No Matches
wxsplitrange.h
Go to the documentation of this file.
1#ifndef wxsplitrange_h
2#define wxsplitrange_h
3
4// WarpX lib includes
5#include "lib/wxrange.h"
6
7// std includes
8#include <map>
9#include <vector>
10#include <list>
11#include <cmath>
12
17template<typename ID_type> class WxSplitRange
18{
19public:
20 typedef int empty_range_t;
21 typedef std::vector<ID_type> SubRangesAssigned_C_ordering_t;
22
33 WxSplitRange(const WxRange& range, const std::list<ID_type>& id_list)
34 : _ndims(range.ndims()),
35 _fullRange(range),
36 _lowerPoints(range.ndims()),
37 _upperPoints(range.ndims())
38 {
39 _numsubranges = _divideRange(id_list.size(), range, _lowerPoints, _upperPoints);
40 // create map to subranges
41 std::vector<int> subrangeIndex(_ndims, 0);
42 typename std::list<ID_type>::const_iterator id_itr = id_list.begin();
43 do
44 {
45 _subrangeMap.insert(SubRangePair_t(*id_itr, subrangeIndex));
46 _assignedSubRange_ids.push_back(*id_itr);
47 ++id_itr;
48 } while (_advanceIndex(subrangeIndex));
49 };
50
54 virtual ~WxSplitRange(){};
55
59 unsigned ndims() const
60 {
61 return _fullRange.ndims();
62 }
63
67 unsigned numRanges() const
68 {
69 return _numsubranges;
70 }
71
75 const WxRange& getGlobalRange() const
76 {
77 return _fullRange;
78 }
79
87 {
88 return _assignedSubRange_ids;
89 }
90
99 /* To be implemented later when we need it
100 ID_type getNeigh() {
101 return neighHolder->getNeigh(n, *this, lp, up);
102 }
103 */
104
111 WxRange getRange(const ID_type& id) const
112 {
113 typename SubRangeMap_t::const_iterator itr = _subrangeMap.find(id);
114 if (itr != _subrangeMap.end())
115 {
116 Distribution_Position_t index = (*itr).second;
117 std::vector<int> lower, upper;
118 for (int i = 0; i < _ndims; ++i)
119 {
120 lower.push_back(_lowerPoints[i][index[i]]);
121 upper.push_back(_upperPoints[i][index[i]]);
122 }
123 return WxRange(_ndims, &lower[0], &upper[0]);
124 }
125
126 // not found: throw an exception
128 throw e;
129 }
130
131 const std::vector<int>& getLowerPoints(int dim) const
132 {
133 return _lowerPoints[dim];
134 }
135
136 const std::vector<int>& getUpperPoints(int dim) const
137 {
138 return _upperPoints[dim];
139 }
140
146 void stretchDimension(int dim, unsigned int stretchFactor)
147 {
148 std::vector<int> lowerExtension(_ndims, 0);
149 std::vector<int> upperExtension(_ndims, 0);
150 upperExtension[dim] = _fullRange.length(dim) * (stretchFactor - 1);
151
152 _fullRange = _fullRange.extend(&lowerExtension[0], &upperExtension[0]);
153
154 int numPoints = _lowerPoints[dim].size();
155 std::vector<int> newLower(numPoints);
156 int baseline =
157 _lowerPoints[dim][0]; // starting point of lowest range remains the same
158
159 for (int i = 0; i < numPoints; ++i)
160 {
161 newLower[i] = (_lowerPoints[dim][i] - baseline) * stretchFactor + baseline;
162 _upperPoints[dim][i] =
163 (_upperPoints[dim][i] - _lowerPoints[dim][i] + 1) * stretchFactor +
164 newLower[i] - 1;
165 }
166 _lowerPoints[dim] = newLower;
167 }
168
176 {
177 WxSplitRange<ID_type> newSR(*this);
178
179 std::vector<int> lowerExtension(_ndims, 0);
180 std::vector<int> upperExtension(_ndims, 1);
181
182 newSR._fullRange = _fullRange.extend(&lowerExtension[0],
183 &upperExtension[0]); // extend the full range
184
185 for (int dim = 0; dim < ndims(); dim++)
186 {
187 int numPoints = _upperPoints[dim].size();
188 std::vector<int> newUpper(numPoints);
189
190 for (int i = 0; i < numPoints; ++i)
191 newSR._upperPoints[dim][i] += 1; // and extend all of the sub ranges.
192 }
193 return newSR;
194 }
195
201 void addDimension(int lowerPoint, int upperPoint)
202 {
203 std::vector<int> newlowervec(1, lowerPoint);
204 std::vector<int> newuppervec(1, upperPoint);
205
206 _lowerPoints.push_back(newlowervec);
207 _upperPoints.push_back(newuppervec);
208 _ndims += 1;
209 _fullRange = _fullRange.extDim(lowerPoint, upperPoint);
210
211 // lastly have to add range index of 0 to the new subrange indices
212 for (typename SubRangeMap_t::iterator itr = _subrangeMap.begin();
213 itr != _subrangeMap.end();
214 ++itr)
215 (*itr).second.push_back(0);
216 }
217
224 /* const ID_type & getRank( const std::vector<int> coords ) const
225 {
226 unsigned
227 WxSplitRange<ID_type>::getRank(TYPE coords[]) const
228 {
229 typename SubRangeMap_t::const_iterator i, iend;
230 iend = _data->rangeMap.end();
231 for (i = _data->rangeMap.begin(); i != iend; ++i) {
232 if ((*i).second.contains(coords)) {
233 return (*i).first;
234 }
235 }
236 // Doesn't exist in the decomp: throw a tde.
237 WxExcept wxe("WxSplitRange::getRank: ");
238 wxe << "Point " << coords[0];
239 for (unsigned i = 1; i < _ndims; ++i)
240 wxe << "," << coords[i];
241 wxe << " is not in decomposition.";
242 throw wxe;
243 }
244 } */
245
246private:
247 // types of ID_type -> WxRange map and pairs
248 typedef std::vector<int> Distribution_Position_t; // split coordinates
249 typedef std::map<ID_type, Distribution_Position_t> SubRangeMap_t;
250 typedef std::pair<ID_type, Distribution_Position_t> SubRangePair_t;
251
252 typedef std::vector<std::vector<int>> Distribution_Storage_t;
253
254 unsigned _ndims;
255 WxRange _fullRange;
256 Distribution_Storage_t _lowerPoints; // _lowerPoints[dim][index]
257 Distribution_Storage_t _upperPoints; // _upperPoints[dim][index]
258 SubRangeMap_t _subrangeMap;
259 int _numsubranges;
260 SubRangesAssigned_C_ordering_t _assignedSubRange_ids;
261
262 // TODO: certainly more can be done here, but this is generally working now. In the
263 // future, more can be done to maximize subrange volume to surface area ratio and
264 // maximally use subranges available
265 int _divideRange(unsigned maxSubRangesDesired,
266 const WxRange& decompRange,
267 Distribution_Storage_t& lowerPoints,
268 Distribution_Storage_t& upperPoints)
269 {
270 // first-pass attempt at dividing the range up into NxM sub-ranges. arrangement
271 // of subranges structured to be compatible with Global Arrays' irreg config call
272
273 int ndims = decompRange.ndims();
274 // real averageVolume = decompRange.size() / (real) maxSubRangesDesired;
275 real uniformNumSplits_f = std::pow(maxSubRangesDesired, 1.0 / ndims);
276 int numSplitsInt = std::floor(uniformNumSplits_f); // nominal number of sub-ranges
277 // (splits+1) in each dimension
278
279 int numSubRangesActuallyAssigned = 1;
280
281 for (int i = 0; i < ndims; ++i)
282 {
283 int numThisDim = 0;
284 int nominalLength = (real) decompRange.length(i) / numSplitsInt;
285 if (i ==
286 ndims - 1) // if we can afford some more splits in this last dim, do so
287 {
288 int remainingSplitsThisDim =
289 maxSubRangesDesired / numSubRangesActuallyAssigned;
290 nominalLength =
291 (real) decompRange.length(i) / ((real) remainingSplitsThisDim);
292 }
293 int lowerPos = decompRange.lower(i);
294 do
295 {
296 lowerPoints[i].push_back(lowerPos);
297 int upperPos =
298 std::min(lowerPos + nominalLength - 1, decompRange.upper(i));
299 if (i == ndims - 1)
300 if ((numThisDim + 2) * numSubRangesActuallyAssigned >
301 maxSubRangesDesired) // special case to prevent exceeding
302 // maxSubRangesDesired
303 upperPos =
304 decompRange.upper(i); // this should be the last split added,
305 // so extend upper pos to end
306
307 upperPoints[i].push_back(upperPos);
308 lowerPos = upperPos + 1;
309 ++numThisDim;
310 } while (lowerPos <= decompRange.upper(i));
311 numSubRangesActuallyAssigned *= numThisDim;
312 }
313 return numSubRangesActuallyAssigned;
314 };
315
316 bool _advanceIndex(Distribution_Position_t& subrangeIndex, int dim = 0) const
317 {
318 bool higherResult;
319 if (dim < _ndims - 1)
320 {
321 higherResult = _advanceIndex(subrangeIndex, dim + 1); // recursively advance
322 if (higherResult)
323 return true;
324 }
325 // reaching here, we need to advance this dim or return false if we can't
326
327 int nextIndex = subrangeIndex[dim] + 1;
328 if (nextIndex == _lowerPoints[dim].size())
329 return false; // nowhere further to go
330
331 for (int i = dim + 1; i < _ndims; ++i)
332 subrangeIndex[i] = 0; // reset all higher indices to zero
333
334 subrangeIndex[dim] = nextIndex; // advance this index
335 return true;
336 };
337};
338
339#endif // wxsplitrange_h
unsigned ndims() const
Dimensionality of box.
Definition: wxbox.h:113
TYPE upper(unsigned dim) const
Upper bound along dimension 'dim'.
Definition: wxbox.h:147
TYPE lower(unsigned dim) const
Lower bound along dimension 'dim'.
Definition: wxbox.h:124
WxBox< TYPE > extDim(TYPE low, TYPE upp) const
Returns a new box which has one greater dimension than this one.
WxRange represents a hyper-rectangular domain of an n-dimensional space of integers.
Definition: wxrange.h:23
int length(unsigned dim) const
Length of edge along dimension 'dim'.
Definition: wxrange.h:294
WxRange extend(const int low[], const int upp[]) const
Returns a range which is extended by the given amount along each side in each dimension.
Definition: wxrange.h:170
WxSplitRange splits a range into smaller ranges in a cartesian manner.
Definition: wxsplitrange.h:18
const std::vector< int > & getLowerPoints(int dim) const
Definition: wxsplitrange.h:131
unsigned numRanges() const
Number of sub-ranges in split.
Definition: wxsplitrange.h:67
const SubRangesAssigned_C_ordering_t getAssignedSubRangeIDs() const
Returns the assigned subrange ids for all of the assigned subranges.
Definition: wxsplitrange.h:86
void stretchDimension(int dim, unsigned int stretchFactor)
modifies the split range such that in the dimension specified all the range coordinates are stretched...
Definition: wxsplitrange.h:146
WxSplitRange< ID_type > cell_to_node_center() const
modifies the split range such that the global range and each sub-range are modified such that the low...
Definition: wxsplitrange.h:175
unsigned ndims() const
Dimension of range split.
Definition: wxsplitrange.h:59
int empty_range_t
Definition: wxsplitrange.h:20
WxRange getRange(const ID_type &id) const
Return neighbor for a given sub-range and side.
Definition: wxsplitrange.h:111
const WxRange & getGlobalRange() const
Return the global range that was split.
Definition: wxsplitrange.h:75
void addDimension(int lowerPoint, int upperPoint)
modifies the split range such that the number of dimensions is increased by one, covering the unsplit...
Definition: wxsplitrange.h:201
WxSplitRange(const WxRange &range, const std::list< ID_type > &id_list)
Split supplied range into smaller number of ranges.
Definition: wxsplitrange.h:33
const std::vector< int > & getUpperPoints(int dim) const
Definition: wxsplitrange.h:136
virtual ~WxSplitRange()
Destory a split range.
Definition: wxsplitrange.h:54
std::vector< ID_type > SubRangesAssigned_C_ordering_t
Definition: wxsplitrange.h:21
#define real
Definition: wmoclunstructuredreconstruction.h:11