Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
split.cpp
Go to the documentation of this file.
1 /* *******************************************************************
2  * Illinois Open Source License *
3  * *
4  * University of Illinois/NCSA *
5  * Open Source License *
6  * *
7  * Copyright@2008, University of Illinois. All rights reserved. *
8  * *
9  * Developed by: *
10  * *
11  * Center for Simulation of Advanced Rockets *
12  * *
13  * University of Illinois *
14  * *
15  * www.csar.uiuc.edu *
16  * *
17  * Permission is hereby granted, free of charge, to any person *
18  * obtaining a copy of this software and associated documentation *
19  * files (the "Software"), to deal with the Software without *
20  * restriction, including without limitation the rights to use, *
21  * copy, modify, merge, publish, distribute, sublicense, and/or *
22  * sell copies of the Software, and to permit persons to whom the *
23  * Software is furnished to do so, subject to the following *
24  * conditions: *
25  * *
26  * *
27  * @ Redistributions of source code must retain the above copyright *
28  * notice, this list of conditions and the following disclaimers. *
29  * *
30  * @ Redistributions in binary form must reproduce the above *
31  * copyright notice, this list of conditions and the following *
32  * disclaimers in the documentation and/or other materials *
33  * provided with the distribution. *
34  * *
35  * @ Neither the names of the Center for Simulation of Advanced *
36  * Rockets, the University of Illinois, nor the names of its *
37  * contributors may be used to endorse or promote products derived *
38  * from this Software without specific prior written permission. *
39  * *
40  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
41  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
42  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
43  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
44  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
46  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
47  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
48  *********************************************************************
49  * Please acknowledge The University of Illinois Center for *
50  * Simulation of Advanced Rockets in works and publications *
51  * resulting from this software or its derivatives. *
52  *********************************************************************/
53 /*
54 Split a set of blocks into more blocks, for
55 parallelism. The subblocks should have a reasonable
56 aspect ratio (not too thin/flat) and should all
57 be roughly the same volume (for load balance).
58 
59 Orion Sky Lawlor, olawlor@acm.org, 6/13/2001
60 */
61 #include <math.h>
62 #include "face.h"
63 #include "makeflo.h"
64 #include <algorithm>
65 using std::make_heap;
66 using std::push_heap;
67 using std::pop_heap;
68 
70  fprintf(stderr,"To be compatible with multigrid level %d, this\n"
71  "must be a multiple of %d.\n",
72  nLevels, levelBad+1);
73  exit(1);
74 }
75 
76 //Force this location in-bounds
77 blockLoc block::pin(const blockLoc &l) const
78 {
79  blockLoc ret=l;
80  for (int i=0;i<3;i++) {
81  if (ret[i]<0) ret[i]=0;
82  if (ret[i]>dim[i]) ret[i]=dim[i];
83  }
84  return ret;
85 }
86 
87 //Create a new subblock from this block
88 block *block::subBlock(const blockSpan &span) const
89 {
90  //Create the new node location array
91  blockDim ns=span.getDim();
92  vector3d *newLocs=new vector3d[ns.getSize()];
93  blockLoc i;
94  BLOCKSPAN_FOR(i,span)
95  newLocs[ns[i-span.start]]=nodeLocs[dim[i]];
96  block *ret=new block(ns,originalNo,-1,newLocs);
97 
98  //Copy over boundary conditions, remapping locations
99  for (int f=0;f<nFaces;f++)
100  for (unsigned int c=0;c<BCs[f].size();c++) {
101  const externalBCpatch &bc=BCs[f][c];
102  blockSpan bs(ret->pin(bc.srcSpan.start-span.start),
103  ret->pin(bc.srcSpan.end -span.start));
104  if (bs.hasArea())
105  //Add this boundary to the new block
106  ret->addBC(bs,bc.bcNo);
107  }
108  return ret;
109 }
110 
111 //Split this block into n subblocks,
112 // inserting the subblocks into dest.
113 void block::split(int nPieces,vector<block *> &dest)
114 {
115  if (nPieces<=0) {
116  fprintf(stderr,"Asked to split block into %d pieces!\n",
117  nPieces);
118  abort();
119  }
120  else if (nPieces==1) {
121  //Reset serial number according to new position
122  blockNo=dest.size();
123  dest.push_back(this);
124  }
125  else
126  { //Must split into several pieces
127  int splitAxis=parameters.splitAxis;
128  if (splitAxis==-1) //No axis specified--
129  { //Split on longest remaining axis
130  int splitLen=0;
131  for (int a=0;a<3;a++)
132  if (dim[a]>splitLen) {
133  splitAxis=a;
134  splitLen=dim[a];
135  }
136  }
137  int splitLen=dim[splitAxis];
138 
139  //Determine the size of each half
140  int loPieces=(int)floor(nPieces/2.0);
141  int hiPieces=nPieces-loPieces;
142  int loSize;
143  if (parameters.splitRCB) //Always cut in half
144  loSize=(int)(splitLen/2);
145  else //Adapt cut location to corresponding number of pieces
146  loSize=splitLen*loPieces/nPieces;
147  //Round cut to the multigrid:
148  loSize=parameters.levelGood&((parameters.levelBad>>1)+loSize);
149 
150  if (loSize==0)
151  { /*Asked to split too far*/
152  fprintf(stderr,"Couldn't split block %d any further-- you must:\n"
153  " -increase the input grid resolution\n"
154  " -decrease the number of requested output blocks\n"
155  "%s",
156  1+getOriginalNumber(),
157  (parameters.levelBad)?" -decrease the multigrid resolution\n":"");
158  exit(1);
159  }
160 
161  //Split this block along that axis
162  blockDim origin(0,0,0);
163  blockDim loEnd=dim; loEnd[splitAxis]=loSize+1;
164  blockDim hiStart=origin; hiStart[splitAxis]=loSize;
165  block *lo=subBlock(blockSpan(origin,loEnd));
166  block *hi=subBlock(blockSpan(hiStart,dim));
167 
168  //Remove ourselves-- we are completely
169  // replaced by our children
170  delete this;
171 
172  //Recursively split the new blocks
173  lo->split(loPieces,dest);
174  hi->split(hiPieces,dest);
175  }
176 }
177 
178 
179 //Return the "volume"-- computational effort
180 // associated with this block
181 int volume(const block *b) {
182  return b->getDim().getSize();
183 }
184 
185 //This class used only inside splitBlocks:
186 class bRec {
187 public:
188  int b;//Block number of input block
189  int vol;//Volume of input block
190  int n;//Number of pieces to split into
191  bRec() {}
192  bRec(int b_,int vol_) {
193  b=b_;
194  vol=vol_;
195  n=1;
196  }
197  //Compare vol/n for these bRecs:
198  static bool less(const bRec &a,const bRec &b) {
199  return (a.vol*b.n)<(b.vol*a.n);
200  }
201 };
202 
203 
204 //Split this list of blocks into at least n subblocks
205 const char * splitBlocks(vector<block *> &blocks,
206  int nPieces)
207 {
208  if ((int)blocks.size()>=nPieces)
209  return NULL;//Already have enough blocks
210 
211 
212 //We try to split so that the resulting blocks
213 // have about the same volume-- distribute pieces
214 // to blocks by volume
215  unsigned int b,nBlocks=blocks.size();
216 
217  int *nSplit=new int[nBlocks];
218 
219  if (parameters.splithalf == 1) {
220  // split every block in half
221  for (b=0;b<nBlocks;b++) {
222  nSplit[b]=2;
223  }
224  }
225  else { // regular split
226  //Create max-heap of blocks, ordered by output volume
227  vector<bRec> heap(nBlocks);
228  for (b=0;b<nBlocks;b++) {
229  heap[b]=bRec(b,volume(blocks[b]));
230  nSplit[b]=1;
231  }
232 
233  std::make_heap(heap.begin(),heap.end(),bRec::less);
234 
235  //Allocate remaining output blocks to the most needy
236  int nRemaining=nPieces-nBlocks;
237  while (nRemaining-->0) {
238  std::pop_heap(heap.begin(),heap.end(),bRec::less);
239  bRec &r=heap[nBlocks-1];
240  r.n=++(nSplit[r.b]);
241  std::push_heap(heap.begin(),heap.end(),bRec::less);
242  }
243  } // end of parameters.splithalf
244 
245  //Split the blocks
246  vector<block *> split;//Accumulates split blocks
247  for (b=0;b<nBlocks;b++) {
248  printf("Input block %d splits into %d pieces (%d-%d)\n",
249  b+1,nSplit[b],(int)(1+split.size()),(int)(1+split.size()+nSplit[b]-1));
250  blocks[b]->split(nSplit[b],split);
251  }
252  delete[] nSplit;
253 
254 //Check the load balance
255  double maxVol=-1e100,minVol=1e100,sumVol=0;
256  for (b=0;b<split.size();b++) {
257  double vol=volume(split[b]);
258  sumVol+=vol;
259  if (maxVol<vol) maxVol=vol;
260  if (minVol>vol) minVol=vol;
261  }
262  double avgVol=sumVol/split.size();
263  printf("Static load balance results:\n"
264  " %.2f blocks per processor, %.0f nodes per block\n"
265  " Heaviest block is %.02f times the average\n"
266  " Lightest block is %.02f times the average\n",
267  ((double)split.size())/nPieces,avgVol,
268  maxVol/avgVol,minVol/avgVol);
269 
270 //Return split blocks to caller
271  blocks=split;
272  return NULL;
273 }
274 
275 
int splithalf
Definition: makeflo.h:97
int getOriginalNumber(void) const
Definition: adj.h:220
void addBC(const blockSpan &span, int bcNo)
Definition: adj.cpp:262
int b
Definition: split.cpp:188
int blockNo
Definition: adj.h:206
vector< externalBCpatch > BCs[nFaces]
Definition: adj.h:240
int splitAxis
Definition: makeflo.h:95
block * subBlock(const blockSpan &span) const
Definition: split.cpp:88
int nLevels
Definition: makeflo.h:99
void multigridError(void)
Definition: split.cpp:69
blockSpan srcSpan
Definition: patch.h:79
bRec(int b_, int vol_)
Definition: split.cpp:192
blockDim getDim(void) const
Definition: gridutil.h:162
Definition: adj.h:203
#define BLOCKSPAN_FOR(i, span)
Definition: gridutil.h:230
int volume(const block *b)
Definition: split.cpp:181
blockLoc start
Definition: gridutil.h:155
const blockDim & getDim(void) const
Definition: adj.h:222
blockLoc i
Definition: read.cpp:79
const char * splitBlocks(vector< block * > &blocks, int nPieces)
Definition: split.cpp:205
blockLoc end
Definition: gridutil.h:156
blockLoc pin(const blockLoc &l) const
Definition: split.cpp:77
static bool less(const bRec &a, const bRec &b)
Definition: split.cpp:198
int originalNo
Definition: adj.h:205
bool blocks
Input data is block-structured grid.
Definition: hdf2pltV2.C:51
bRec()
Definition: split.cpp:191
Definition: split.cpp:186
unsigned int levelBad
Definition: makeflo.h:100
vector3d * nodeLocs
Definition: adj.h:207
makefloParam parameters
Definition: makeflo.cpp:101
int vol
Definition: split.cpp:189
block(const blockDim &dim_, int originalNo_, int blockNo_, vector3d *nodeLocs_)
Definition: adj.cpp:244
int getSize(void) const
Definition: gridutil.h:126
int n
Definition: split.cpp:190
unsigned int levelGood
Definition: makeflo.h:101
blockDim dim
Definition: adj.h:204
void split(int nPieces, vector< block * > &dest)
Definition: split.cpp:113
int splitRCB
Definition: makeflo.h:96