1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "hierarchGeomDecomp.H"
28 #include "addToRunTimeSelectionTable.H"
29 #include "PstreamReduceOps.H"
30 #include "SortableList.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 defineTypeNameAndDebug(hierarchGeomDecomp, 0);
38 addToRunTimeSelectionTable
45 addToRunTimeSelectionTable
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
55 void Foam::hierarchGeomDecomp::setDecompOrder()
57 word order(geomDecomDict_.lookup("order"));
59 if (order.size() != 3)
63 "hierarchGeomDecomp::hierarchGeomDecomp"
64 "(const dictionary& decompositionDict)",
66 ) << "number of characters in order (" << order << ") != 3"
67 << exit(FatalIOError);
70 for (label i = 0; i < 3; i++)
76 else if (order[i] == 'y')
80 else if (order[i] == 'z')
88 "hierarchGeomDecomp::hierarchGeomDecomp"
89 "(const dictionary& decompositionDict)",
91 ) << "Illegal decomposition order " << order << endl
92 << "It should only contain x, y or z" << exit(FatalError);
98 Foam::label Foam::hierarchGeomDecomp::findLower
100 const List<scalar>& l,
106 if (initHigh <= initLow)
112 label high = initHigh;
114 while ((high - low) > 1)
116 label mid = (low + high)/2;
128 // high and low can still differ by one. Choose best.
145 // Find position in values so between minIndex and this position there
146 // are wantedSize elements.
147 void Foam::hierarchGeomDecomp::findBinary
150 const List<scalar>& values,
151 const label minIndex, // index of previous value
152 const scalar minValue, // value at minIndex
153 const scalar maxValue, // global max of values
154 const scalar wantedSize, // wanted size
156 label& mid, // index where size of bin is
157 // wantedSize (to within sizeTol)
158 scalar& midValue // value at mid
161 label low = minIndex;
162 scalar lowValue = minValue;
164 scalar highValue = maxValue;
165 // (one beyond) index of highValue
166 label high = values.size();
168 // Safeguards to avoid infinite loop.
173 //while (low <= high)
176 label size = returnReduce(mid-minIndex, sumOp<label>());
180 Pout<< "low:" << low << " lowValue:" << lowValue
181 << " high:" << high << " highValue:" << highValue
182 << " mid:" << mid << " midValue:" << midValue << nl
183 << "globalSize:" << size << " wantedSize:" << wantedSize
184 << " sizeTol:" << sizeTol << endl;
187 if (wantedSize < size - sizeTol)
190 highValue = midValue;
192 else if (wantedSize > size + sizeTol)
202 // Update mid, midValue
203 midValue = 0.5*(lowValue+highValue);
204 mid = findLower(values, midValue, low, high);
206 // Safeguard if same as previous.
207 bool hasNotChanged = (mid == midPrev) && (low == lowPrev) && (high == highPrev);
208 if (returnReduce(hasNotChanged, andOp<bool>()))
210 WarningIn("hierarchGeomDecomp::findBinary(..)")
211 << "unable to find desired deomposition split, making do!"
223 // Sort points into bins according to one component. Recurses to next component.
224 void Foam::hierarchGeomDecomp::sortComponent
227 const pointField& points,
228 const labelList& current, // slice of points to decompose
229 const direction componentIndex, // index in decompOrder_
230 const label mult, // multiplication factor for finalDecomp
231 labelList& finalDecomp
235 label compI = decompOrder_[componentIndex];
239 Pout<< "sortComponent : Sorting slice of size " << current.size()
240 << " in component " << compI << endl;
243 // Storage for sorted component compI
244 SortableList<scalar> sortedCoord(current.size());
248 label pointI = current[i];
250 sortedCoord[i] = points[pointI][compI];
254 label globalCurrentSize = returnReduce(current.size(), sumOp<label>());
256 scalar minCoord = returnReduce
266 scalar maxCoord = returnReduce
270 ? sortedCoord[sortedCoord.size()-1]
278 Pout<< "sortComponent : minCoord:" << minCoord
279 << " maxCoord:" << maxCoord << endl;
282 // starting index (in sortedCoord) of bin (= local)
284 // starting value of bin (= global since coordinate)
285 scalar leftCoord = minCoord;
287 // Sort bins of size n
288 for (label bin = 0; bin < n_[compI]; bin++)
290 // Now we need to determine the size of the bin (dx). This is
291 // determined by the 'pivot' values - everything to the left of this
292 // value goes in the current bin, everything to the right into the next
295 // Local number of elements
296 label localSize = -1; // offset from leftOffset
298 // Value at right of bin (leftIndex+localSize-1)
299 scalar rightCoord = -GREAT;
301 if (bin == n_[compI]-1)
303 // Last bin. Copy all.
304 localSize = current.size()-leftIndex;
305 rightCoord = maxCoord; // note: not used anymore
307 else if (Pstream::nProcs() == 1)
309 // No need for binary searching of bin size
310 localSize = label(current.size()/n_[compI]);
311 rightCoord = sortedCoord[leftIndex+localSize];
315 // For the current bin (starting at leftCoord) we want a rightCoord
316 // such that the sum of all sizes are globalCurrentSize/n_[compI].
317 // We have to iterate to obtain this.
319 label rightIndex = current.size();
320 rightCoord = maxCoord;
322 // Calculate rightIndex/rightCoord to have wanted size
330 globalCurrentSize/n_[compI], // wanted size
335 localSize = rightIndex - leftIndex;
340 Pout<< "For component " << compI << ", bin " << bin
342 << "from " << leftCoord << " at local index "
344 << "to " << rightCoord << " localSize:"
350 // Copy localSize elements starting from leftIndex.
351 labelList slice(localSize);
355 label pointI = current[sortedCoord.indices()[leftIndex+i]];
357 // Mark point into correct bin
358 finalDecomp[pointI] += bin*mult;
360 // And collect for next sorting action
364 // Sort slice in next component
365 if (componentIndex < 2)
370 oldPrefix = Pout.prefix();
371 Pout.prefix() = " " + oldPrefix;
380 mult*n_[compI], // Multiplier to apply to decomposition.
386 Pout.prefix() = oldPrefix;
391 leftIndex += localSize;
392 leftCoord = rightCoord;
397 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
399 Foam::hierarchGeomDecomp::hierarchGeomDecomp
401 const dictionary& decompositionDict
404 geomDecomp(decompositionDict, typeName),
411 Foam::hierarchGeomDecomp::hierarchGeomDecomp
413 const dictionary& decompositionDict,
417 geomDecomp(decompositionDict, hierarchGeomDecomp::typeName),
424 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
426 Foam::labelList Foam::hierarchGeomDecomp::decompose
428 const pointField& points
431 // construct a list for the final result
432 labelList finalDecomp(points.size(), 0);
434 // Start off with every point sorted onto itself.
435 labelList slice(points.size());
441 pointField rotatedPoints = rotDelta_ & points;
444 // Calculate tolerance of cell distribution. For large cases finding
445 // distibution to the cell exact would cause too many iterations so allow
447 label allSize = points.size();
448 reduce(allSize, sumOp<label>());
450 const label sizeTol = max(1, label(1E-3*allSize/nProcessors_));
458 0, // Sort first component in decompOrder.
459 1, // Offset for different x bins.
467 // ************************************************************************* //