PlasCom2  1.0
XPACC Multi-physics simluation application
PCPPIntervalUtils.C
Go to the documentation of this file.
1 #include "PCPPIntervalUtils.H"
2 
3 namespace pcpp {
4  namespace util {
5 
6 
7  int SubIntervalFromStream(std::istream &inStream,const pcpp::IndexIntervalType &inInterval,
8  pcpp::IndexIntervalType &subInterval)
9  {
10  subInterval.Copy(inInterval);
11  int numDim = inInterval.size();
12  int ibDir = 0;
13  std::vector<int> iStart(numDim,0);
14  std::vector<int> iEnd(numDim,0);
15  inStream >> ibDir;
16  if(ibDir == 0)
17  return(1);
18  for(int iDim = 0;iDim < numDim;iDim++){
19  inStream >> iStart[iDim] >> iEnd[iDim];
20  if(iStart[iDim] == 0 || iEnd[iDim] == 0)
21  return(1);
22  }
23  int direction = ibDir;
24  int leftBoundary = 1;
25  if(ibDir < 0){
26  direction = -1*direction;
27  leftBoundary = 0;
28  }
29  direction = direction - 1;
30  if(leftBoundary){
31  subInterval[direction].first = iStart[direction]-1;
32  subInterval[direction].second = iEnd[direction]-1;
33  } else {
34  int startIndex = iStart[direction];
35  int endIndex = iEnd[direction];
36  if(iStart[direction] < 0)
37  startIndex *= -1;
38  if(iEnd[direction] < 0)
39  endIndex *= -1;
40  startIndex -= 1;
41  endIndex -= 1;
42  subInterval[direction].first -= startIndex;
43  subInterval[direction].second -= endIndex;
44  }
45  for(int iDim = 0;iDim < numDim;iDim++){
46  if(iDim != direction){
47  int startIndex = iStart[iDim];
48  int endIndex = iEnd[iDim];
49  if(startIndex < 0){
50  startIndex += 1;
51  startIndex *= -1;
52  subInterval[iDim].first = inInterval[iDim].second - startIndex;
53  } else {
54  startIndex -= 1;
55  subInterval[iDim].first = inInterval[iDim].first + startIndex;
56  }
57  if(endIndex < 0){
58  endIndex += 1;
59  endIndex *= 1;
60  subInterval[iDim].second = inInterval[iDim].second - endIndex;
61  } else {
62  endIndex -= 1;
63  subInterval[iDim].second = inInterval[iDim].first + endIndex;
64  }
65  }
66  }
67  // Check to make sure it actually overlaps
68  pcpp::IndexIntervalType overlapInterval(inInterval.Overlap(subInterval));
69  if(overlapInterval != subInterval)
70  return(1);
71  return(0);
72  };
73 
74  std::vector<pcpp::IndexIntervalType>
75  UniqueUnion(const std::vector<pcpp::IndexIntervalType> &intervalSet)
76  {
77  std::vector<pcpp::IndexIntervalType> uniqueUnion(intervalSet);
78  int numIntervals = intervalSet.size();
79  if(numIntervals <= 1)
80  return(uniqueUnion);
81  for(int iSet = 0;iSet < numIntervals-1;iSet++){
82  pcpp::IndexIntervalType interval1(uniqueUnion[iSet]);
83  for(int iCompare = iSet+1;iCompare < numIntervals;iSet++){
84  pcpp::IndexIntervalType compareInterval(interval1.Overlap(uniqueUnion[iCompare]));
85  if(compareInterval.NNodes() > 0){
86 
87  }
88  }
89  }
90 
91  }
92 
93  void CollapseInterval(size_t &xSize,size_t &ySize,size_t &zSize,
94  const pcpp::IndexIntervalType &inInterval,
95  pcpp::IndexIntervalType &outInterval)
96  {
97  outInterval = inInterval;
98  if(xSize == 1){
99  if(ySize == 1){
100  outInterval[0] = outInterval[2];
101  xSize = zSize;
102  outInterval[1].first = 0;
103  outInterval[1].second = 0;
104  outInterval[2] = outInterval[1];
105  } else {
106  outInterval[0] = outInterval[1];
107  xSize = ySize;
108  outInterval[1] = outInterval[2];
109  ySize = zSize;
110  outInterval[2].first = 0;
111  outInterval[2].second = 0;
112  zSize = 1;
113  }
114  } else if (ySize == 1){
115  if(zSize == 1){
116  outInterval[1].first = 0;
117  outInterval[1].second = 0;
118  outInterval[2] = outInterval[1];
119  } else {
120  outInterval[1] = outInterval[2];
121  outInterval[2].first = 0;
122  outInterval[2].second = 0;
123  ySize = zSize;
124  zSize = 1;
125  }
126  } else if (zSize == 1){
127  outInterval[2].first = 0;
128  outInterval[2].second = 0;
129  }
130  };
131 
132  std::deque<size_t> PrimeFactors(size_t inNumber)
133  {
134  std::deque<size_t> primeFactors;
135  size_t baseFac = 2;
136  while(baseFac*baseFac <= inNumber){
137  if(inNumber%baseFac == 0){
138  primeFactors.push_back(baseFac);
139  inNumber /= baseFac;
140  } else {
141  baseFac++;
142  }
143  }
144  if(inNumber >= 1)
145  primeFactors.push_back(inNumber);
146  return(primeFactors);
147  };
148 
152  std::vector<bool> partDirection,
153  int partID,int numPart,
154  pcpp::IndexIntervalType &outInterval,
155  std::vector<int> &numPartitions)
156  {
157 
158  if(numPart == 1){
159  outInterval = inInterval;
160  return(0);
161  }
162 
163  outInterval.resize(0);
164 
165  if(partID < 0 || numPart < 1){
166  std::cout << "numpart prob" << std::endl;
167  return(-1);
168  }
169 
170  int numDim = inInterval.size();
171 
172  if(numDim <= 0){
173  std::cout << "numdim prob" << std::endl;
174  return(-1);
175  }
176 
177  if(partDirection.empty()){
178  partDirection.resize(numDim,true);
179  } else if (partDirection.size() != numDim){
180  std::cout << "partdir prob" << std::endl;
181  return(-1);
182  }
183 
184  size_t maxTotalPossibleParts = 1;
185  std::vector<int> candidateDims;
186  std::vector<size_t> candidateSize;
187  numPartitions.resize(numDim,0);
188 
189  // Initialize some needed data structures
190  for(int iDim = 0;iDim < numDim;iDim++){
191  if(partDirection[iDim]){
192  size_t mySize = inInterval[iDim].second - inInterval[iDim].first + 1;
193  candidateDims.push_back(iDim);
194  candidateSize.push_back(mySize);
195  maxTotalPossibleParts *= mySize;
196  } else {
197  numPartitions[iDim] = 1;
198  }
199  }
200 
201  if(numPart > maxTotalPossibleParts){
202  std::cout << "maxpart" << std::endl;
203  return(-1);
204  }
205 
206  int partDims = candidateDims.size();
207  outInterval = inInterval;
208 
209  // prime factorization of desired number of partitions
210  std::deque<size_t> primeFactors(PrimeFactors(numPart));
211  int numFac = primeFactors.size();
212 
213  if(numFac == 0)
214  return(0);
215  if(numFac == 1 && primeFactors.front() == 1)
216  return(0);
217 
218  // If the number of prime factors is larger than the
219  // number of possible dimenions, reduce by recursively
220  // combining (i.e. multiplying) the two smallest factors.
221  // Resulting deque is sorted smallest to largest
222  while(numFac > partDims){
223  primeFactors[1] *= primeFactors.front();
224  primeFactors.pop_front();
225  std::sort(primeFactors.begin(),primeFactors.end());
226  numFac--;
227  }
228 
229  // Next, match the largest partitions to the dimensions with
230  // largest size until all the dimensions are partitioned.
231  while(!primeFactors.empty()){
232  int dimPart = primeFactors.back();
233  primeFactors.pop_back();
234  int dimPlane = 1;
235  if(!primeFactors.empty()){
236  std::deque<size_t>::iterator facIt = primeFactors.begin();
237  while(facIt != primeFactors.end())
238  dimPlane *= *facIt++;
239  }
240 
241  int maxSize = 0;
242  int maxDim = -1;
243  for(int iCand = 0;iCand < partDims;iCand++){
244  if((candidateSize[iCand] >= maxSize) && (numPartitions[candidateDims[iCand]] == 0)){
245  maxDim = candidateDims[iCand];
246  maxSize = candidateSize[iCand];
247  }
248  }
249  if(maxSize == 0 || maxDim < 0){
250  std::cout << "maxsize = " << maxSize << "maxDim = " << maxDim << std::endl;
251  return(-1);
252  }
253 
254  numPartitions[maxDim] = dimPart;
255  size_t iStart = outInterval[maxDim].first;
256  size_t iEnd = outInterval[maxDim].second;
257  size_t partRank = (partID/dimPlane)%dimPart;
258  Part1D(iStart,iEnd,dimPart,partRank,outInterval[maxDim].first,
259  outInterval[maxDim].second);
260  }
261 
262  return(0);
263 
264  };
265 
266 
283  int Part1D(const size_t iStart,const size_t iEnd,const size_t numPart,const size_t partIndex,
284  size_t &partStart,size_t &partEnd)
285  {
286  size_t intervalSize = iEnd - iStart + 1;
287  size_t partSize = intervalSize/numPart;
288  if(partSize == 0)
289  return(1);
290  size_t leftOver = intervalSize%numPart;
291  if(partIndex < leftOver)
292  partSize++;
293  size_t intervalStart = partIndex*partSize;
294  if(partIndex >= leftOver)
295  intervalStart += leftOver;
296  partStart = intervalStart + iStart;
297  partEnd = partStart + partSize - 1;
298  return(0);
299  };
300 
318  const std::vector<int> &cartDims,
319  const std::vector<int> &cartCoords,
320  pcpp::IndexIntervalType &partExtent,
321  std::ostream &messageStream)
322  {
323 
324  if(globalExtent.empty()){
325  messageStream << "PartitionCartesianExtent:Error: Global extent empty."
326  << std::endl;
327  return(1);
328  }
329  int numDim = cartDims.size();
330  if(globalExtent.ND() < numDim){
331  messageStream << "PartitionCartesianExtent:Error: Global extent dimension deficient, "
332  << globalExtent.ND() << " < " << numDim << "." << std::endl;
333  return(1);
334  }
335  std::vector<size_t> localStart(numDim,0);
336  std::vector<size_t> localSize(numDim,0);
337  for(int iDim = 0;iDim < numDim;iDim++){
338  size_t numPart = cartDims[iDim];
339  size_t intervalStart = globalExtent[iDim].first;
340  size_t intervalEnd = globalExtent[iDim].second;
341  size_t partStart = 0;
342  size_t partEnd = 0;
343  size_t partIndex = cartCoords[iDim];
344  if(Part1D(intervalStart,intervalEnd,numPart,partIndex,partStart,partEnd)){
345  messageStream << "PartitionCartesianExtent:Error: Global extent of insufficient size for number of partitions."
346  << std::endl;
347  return(1);
348  }
349  localSize[iDim] = partEnd - partStart + 1;
350  localStart[iDim] = partStart;
351  }
352  partExtent.Init(localStart,localSize);
353  return(0);
354  };
373  const std::vector<int> &cartDims,
374  const std::vector<int> &cartCoords,
375  pcpp::IndexIntervalType &partInterval,
376  std::ostream &messageStream)
377  {
378 
379  if(globalInterval.empty()){
380  messageStream << "PartitionCartesianInterval:Error: Global interval empty."
381  << std::endl;
382  return(1);
383  }
384  int numDim = cartDims.size();
385  if(globalInterval.ND() < numDim){
386  messageStream << "PartitionCartesianInterval:Error: Global interval dimension deficient, "
387  << globalInterval.ND() << " < " << numDim << "." << std::endl;
388  return(1);
389  }
390  std::vector<size_t> localStart(numDim,0);
391  std::vector<size_t> localSize(numDim,0);
392  for(int iDim = 0;iDim < numDim;iDim++){
393  size_t numPart = cartDims[iDim];
394  size_t intervalStart = globalInterval[iDim].first;
395  size_t intervalEnd = globalInterval[iDim].second;
396  size_t partStart = 0;
397  size_t partEnd = 0;
398  size_t partIndex = cartCoords[iDim];
399  if(Part1D(intervalStart,intervalEnd,numPart,partIndex,partStart,partEnd)){
400  messageStream << "PartitionCartesianInterval:Error: Global interval of insufficient size for number of partitions."
401  << std::endl;
402  return(1);
403  }
404  localSize[iDim] = partEnd - partStart + 1;
405  localStart[iDim] = partStart;
406  }
407  partInterval.Init(localStart,localSize);
408  return(0);
409  };
410  };
411 };
std::vector< pcpp::IndexIntervalType > UniqueUnion(const std::vector< pcpp::IndexIntervalType > &intervalSet)
int SimplePartitionInterval(const pcpp::IndexIntervalType &inInterval, std::vector< bool > partDirection, int partID, int numPart, pcpp::IndexIntervalType &outInterval, std::vector< int > &numPartitions)
Multi-dimensional interval partitioning (non-MPI)
size_t ND() const
Definition: IndexUtil.H:271
std::deque< size_t > PrimeFactors(size_t inNumber)
int Part1D(const size_t iStart, const size_t iEnd, const size_t numPart, const size_t partIndex, size_t &partStart, size_t &partEnd)
Extract a sub-interval of a 1-dimensional integer interval.
int SubIntervalFromStream(std::istream &inStream, const pcpp::IndexIntervalType &inInterval, pcpp::IndexIntervalType &subInterval)
void Copy(const sizeextent &inExtent)
Definition: IndexUtil.H:228
void Overlap(const sizeextent &inextent, sizeextent &outextent) const
Definition: IndexUtil.H:324
int PartitionCartesianExtent(const pcpp::IndexIntervalType &globalExtent, const std::vector< int > &cartDims, const std::vector< int > &cartCoords, pcpp::IndexIntervalType &partExtent, std::ostream &messageStream)
Get local sub-interval of an n-dimensional integer interval.
void Init(const ContainerType &inflatextent)
Definition: IndexUtil.H:133
int PartitionCartesianInterval(const pcpp::IndexIntervalType &globalExtent, const std::vector< int > &cartDims, const std::vector< int > &cartCoords, pcpp::IndexIntervalType &partExtent, std::ostream &messageStream)
Get local sub-interval of an n-dimensional integer interval.
void CollapseInterval(size_t &xSize, size_t &ySize, size_t &zSize, const pcpp::IndexIntervalType &inInterval, pcpp::IndexIntervalType &outInterval)
Simple Block Structured Mesh object.
Definition: IndexUtil.H:21