1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 "ParSortableList.H"
28 #include "SortableList.H"
30 #include "ListListOps.H"
31 #include "PstreamReduceOps.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 void Foam::ParSortableList<Type>::write
38 const List<Type>& elems,
46 os << ' ' << elems[elemI];
52 // Copy src, starting at destI into dest.
54 void Foam::ParSortableList<Type>::copyInto
56 const List<Type>& values,
57 const labelList& indices,
58 const label fromProcNo,
60 List<taggedValue>& dest
65 taggedValue& tagVal = dest[destI];
67 tagVal.value() = values[elemI];
68 tagVal.index() = indices[elemI];
69 tagVal.procID() = fromProcNo;
77 void Foam::ParSortableList<Type>::getPivots
79 const List<Type>& elems,
83 pivots.setSize(Pstream::nProcs());
87 forAll(pivots, pivotI)
89 pivots[pivotI] = elems[pivotPos];
91 pivotPos += elems.size()/Pstream::nProcs();
97 void Foam::ParSortableList<Type>::checkAndSend
102 const label destProcI
105 if (destProcI != Pstream::myProcNo())
107 values.setSize(bufSize);
108 indices.setSize(bufSize);
112 Pout<< "Sending to " << destProcI << " elements:" << values
117 OPstream toSlave(destProcI);
118 toSlave << values << indices;
124 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
126 // Construct from List, sorting the elements
127 template <class Type>
128 Foam::ParSortableList<Type>::ParSortableList(const List<Type>& values)
138 // Construct given size. Sort later on.
139 template <class Type>
140 Foam::ParSortableList<Type>::ParSortableList(const label size)
148 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
151 template <class Type>
152 void Foam::ParSortableList<Type>::sort()
155 // 0. Get total size of dataset.
158 label n = this->size();
160 reduce(n, sumOp<label>());
163 // 1. Sort list locally
164 SortableList<Type> sorted(*this);
166 // Collect elements at pivot points
167 labelListList sortedGatherList(Pstream::nProcs());
169 labelList& pivots = sortedGatherList[Pstream::myProcNo()];
171 getPivots(sorted, pivots);
182 // 2. Combine pivotlist per processor onto master, sort, get pivots.
185 Pstream::gatherList(sortedGatherList);
187 if (Pstream::master())
189 labelList allPivots =
190 ListListOps::combine<labelList>
193 accessOp<labelList>()
196 SortableList<Type> sortedPivots(allPivots);
201 write(allPivots, Pout);
205 getPivots(sortedPivots, pivots);
207 Pstream::scatter(pivots);
211 Pout<< "new pivots:";
218 // 3. Distribute pivots & distribute.
224 // Buffer for my own data. Keep original index together with value.
225 labelList ownValues(sorted.size());
226 labelList ownIndices(sorted.size());
229 // Buffer for sending data
230 labelList sendValues(sorted.size());
231 labelList sendIndices(sorted.size());
234 forAll(sorted, sortedI)
236 if ((pivotI < Pstream::nProcs()) && (sorted[sortedI] > pivots[pivotI]))
238 checkAndSend(sendValues, sendIndices, sendI, destProcI);
241 sendValues.setSize(sorted.size());
242 sendIndices.setSize(sorted.size());
249 if (destProcI != Pstream::myProcNo())
251 sendValues[sendI] = sorted[sortedI];
252 sendIndices[sendI] = sorted.indices()[sortedI];
257 ownValues[ownI] = sorted[sortedI];
258 ownIndices[ownI] = sorted.indices()[sortedI];
264 // Handle trailing send buffer
267 checkAndSend(sendValues, sendIndices, sendI, destProcI);
271 ownValues.setSize(ownI);
272 ownIndices.setSize(ownI);
276 Pout<< "Not sending (to myself) elements "
277 << ownValues << endl;
281 // 4. Combine pieces from all processors & sort. Use indices() from
282 // SortableList to remember source processor number.
285 // Allocate receive buffer. Acc. to paper upper bound is 2*n/p
286 // (n=total size, p=nProcs). Resize later on.
287 List<taggedValue> combinedValues(2 * n/Pstream::nProcs());
291 for (label procI = 0; procI < Pstream::nProcs(); procI++)
293 if (procI == Pstream::myProcNo())
297 Pout<< "Copying from own:" << ownValues << endl;
300 // Copy ownValues,ownIndices into combined buffer
301 copyInto(ownValues, ownIndices, procI, combinedI, combinedValues);
306 labelList recIndices;
311 Pout<< "Receiving from " << procI << endl;
314 IPstream fromSlave(procI);
316 fromSlave >> recValues >> recIndices;
320 Pout<< "Received from " << procI
321 << " elements:" << recValues << endl;
327 Pout<< "Copying starting at:" << combinedI << endl;
329 copyInto(recValues, recIndices, procI, combinedI, combinedValues);
332 combinedValues.setSize(combinedI);
334 // Sort according to values
335 Foam::sort(combinedValues);
338 this->setSize(combinedI);
339 indices_.setSize(combinedI);
340 procs_.setSize(combinedI);
342 forAll(combinedValues, elemI)
344 this->operator[](elemI) = combinedValues[elemI].value();
345 indices_[elemI] = combinedValues[elemI].index();
346 procs_[elemI] = combinedValues[elemI].procID();
351 // ************************************************************************* //