FreeFOAM The Cross-Platform CFD Toolkit
simpleGeomDecomp.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "simpleGeomDecomp.H"
28 #include <OpenFOAM/SortableList.H>
29 
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34  defineTypeNameAndDebug(simpleGeomDecomp, 0);
35 
37  (
38  decompositionMethod,
39  simpleGeomDecomp,
40  dictionary
41  );
42 
44  (
45  decompositionMethod,
46  simpleGeomDecomp,
47  dictionaryMesh
48  );
49 }
50 
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 
53 // assignToProcessorGroup : given nCells cells and nProcGroup processor
54 // groups to share them, how do we share them out? Answer : each group
55 // gets nCells/nProcGroup cells, and the first few get one
56 // extra to make up the numbers. This should produce almost
57 // perfect load balancing
58 
59 void Foam::simpleGeomDecomp::assignToProcessorGroup
60 (
61  labelList& processorGroup,
62  const label nProcGroup
63 )
64 {
65  label jump = processorGroup.size()/nProcGroup;
66  label jumpb = jump + 1;
67  label fstProcessorGroup = processorGroup.size() - jump*nProcGroup;
68 
69  label ind = 0;
70  label j = 0;
71 
72  // assign cells to the first few processor groups (those with
73  // one extra cell each
74  for (j=0; j<fstProcessorGroup; j++)
75  {
76  for (register label k=0; k<jumpb; k++)
77  {
78  processorGroup[ind++] = j;
79  }
80  }
81 
82  // and now to the `normal' processor groups
83  for (; j<nProcGroup; j++)
84  {
85  for (register label k=0; k<jump; k++)
86  {
87  processorGroup[ind++] = j;
88  }
89  }
90 }
91 
92 
93 void Foam::simpleGeomDecomp::assignToProcessorGroup
94 (
95  labelList& processorGroup,
96  const label nProcGroup,
97  const labelList& indices,
98  const scalarField& weights,
99  const scalar summedWeights
100 )
101 {
102  // This routine gets the sorted points.
103  // Easiest to explain with an example.
104  // E.g. 400 points, sum of weights : 513.
105  // Now with number of divisions in this direction (nProcGroup) : 4
106  // gives the split at 513/4 = 128
107  // So summed weight from 0..128 goes into bin 0,
108  // ,, 128..256 goes into bin 1
109  // etc.
110  // Finally any remaining ones go into the last bin (3).
111 
112  const scalar jump = summedWeights/nProcGroup;
113  const label nProcGroupM1 = nProcGroup - 1;
114  scalar sumWeights = 0;
115  label ind = 0;
116  label j = 0;
117 
118  // assign cells to all except last group.
119  for (j=0; j<nProcGroupM1; j++)
120  {
121  const scalar limit = jump*scalar(j + 1);
122  while (sumWeights < limit)
123  {
124  sumWeights += weights[indices[ind]];
125  processorGroup[ind++] = j;
126  }
127  }
128  // Ensure last included.
129  while (ind < processorGroup.size())
130  {
131  processorGroup[ind++] = nProcGroupM1;
132  }
133 }
134 
135 
136 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
137 
138 Foam::simpleGeomDecomp::simpleGeomDecomp(const dictionary& decompositionDict)
139 :
140  geomDecomp(decompositionDict, typeName)
141 {}
142 
143 
144 Foam::simpleGeomDecomp::simpleGeomDecomp
145 (
146  const dictionary& decompositionDict,
147  const polyMesh&
148 )
149 :
150  geomDecomp(decompositionDict, typeName)
151 {}
152 
153 
154 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
155 
157 {
158  // construct a list for the final result
159  labelList finalDecomp(points.size());
160 
161  labelList processorGroups(points.size());
162 
163  labelList pointIndices(points.size());
164  forAll(pointIndices, i)
165  {
166  pointIndices[i] = i;
167  }
168 
169  pointField rotatedPoints = rotDelta_ & points;
170 
171  // and one to take the processor group id's. For each direction.
172  // we assign the processors to groups of processors labelled
173  // 0..nX to give a banded structure on the mesh. Then we
174  // construct the actual processor number by treating this as
175  // the units part of the processor number.
176  sort
177  (
178  pointIndices,
179  UList<scalar>::less(rotatedPoints.component(vector::X))
180  );
181 
182  assignToProcessorGroup(processorGroups, n_.x());
183 
184  forAll(points, i)
185  {
186  finalDecomp[pointIndices[i]] = processorGroups[i];
187  }
188 
189 
190  // now do the same thing in the Y direction. These processor group
191  // numbers add multiples of nX to the proc. number (columns)
192  sort
193  (
194  pointIndices,
195  UList<scalar>::less(rotatedPoints.component(vector::Y))
196  );
197 
198  assignToProcessorGroup(processorGroups, n_.y());
199 
200  forAll(points, i)
201  {
202  finalDecomp[pointIndices[i]] += n_.x()*processorGroups[i];
203  }
204 
205 
206  // finally in the Z direction. Now we add multiples of nX*nY to give
207  // layers
208  sort
209  (
210  pointIndices,
211  UList<scalar>::less(rotatedPoints.component(vector::Z))
212  );
213 
214  assignToProcessorGroup(processorGroups, n_.z());
215 
216  forAll(points, i)
217  {
218  finalDecomp[pointIndices[i]] += n_.x()*n_.y()*processorGroups[i];
219  }
220 
221  return finalDecomp;
222 }
223 
224 
226 (
227  const pointField& points,
228  const scalarField& weights
229 )
230 {
231  // construct a list for the final result
232  labelList finalDecomp(points.size());
233 
234  labelList processorGroups(points.size());
235 
236  labelList pointIndices(points.size());
237  forAll(pointIndices, i)
238  {
239  pointIndices[i] = i;
240  }
241 
242  pointField rotatedPoints = rotDelta_ & points;
243 
244  // and one to take the processor group id's. For each direction.
245  // we assign the processors to groups of processors labelled
246  // 0..nX to give a banded structure on the mesh. Then we
247  // construct the actual processor number by treating this as
248  // the units part of the processor number.
249  sort
250  (
251  pointIndices,
252  UList<scalar>::less(rotatedPoints.component(vector::X))
253  );
254 
255  const scalar summedWeights = sum(weights);
256  assignToProcessorGroup
257  (
258  processorGroups,
259  n_.x(),
260  pointIndices,
261  weights,
262  summedWeights
263  );
264 
265  forAll(points, i)
266  {
267  finalDecomp[pointIndices[i]] = processorGroups[i];
268  }
269 
270 
271  // now do the same thing in the Y direction. These processor group
272  // numbers add multiples of nX to the proc. number (columns)
273  sort
274  (
275  pointIndices,
276  UList<scalar>::less(rotatedPoints.component(vector::Y))
277  );
278 
279  assignToProcessorGroup
280  (
281  processorGroups,
282  n_.y(),
283  pointIndices,
284  weights,
285  summedWeights
286  );
287 
288  forAll(points, i)
289  {
290  finalDecomp[pointIndices[i]] += n_.x()*processorGroups[i];
291  }
292 
293 
294  // finally in the Z direction. Now we add multiples of nX*nY to give
295  // layers
296  sort
297  (
298  pointIndices,
299  UList<scalar>::less(rotatedPoints.component(vector::Z))
300  );
301 
302  assignToProcessorGroup
303  (
304  processorGroups,
305  n_.z(),
306  pointIndices,
307  weights,
308  summedWeights
309  );
310 
311  forAll(points, i)
312  {
313  finalDecomp[pointIndices[i]] += n_.x()*n_.y()*processorGroups[i];
314  }
315 
316  return finalDecomp;
317 }
318 // ************************ vim: set sw=4 sts=4 et: ************************ //