Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include "ParSortableList.H"
00027 #include "SortableList.H"
00028 #include <OpenFOAM/Pstream.H>
00029 #include <OpenFOAM/ListListOps.H>
00030 #include <OpenFOAM/PstreamReduceOps.H>
00031 
00032 
00033 
00034 template <class Type>
00035 void Foam::ParSortableList<Type>::write
00036 (
00037     const List<Type>& elems,
00038     Ostream& os
00039 ) const
00040 {
00041     os << '(';
00042 
00043     forAll(elems, elemI)
00044     {
00045         os << ' ' << elems[elemI];
00046     }
00047     os << ')';
00048 }
00049 
00050 
00051 
00052 template <class Type>
00053 void Foam::ParSortableList<Type>::copyInto
00054 (
00055     const List<Type>& values,
00056     const labelList& indices,
00057     const label fromProcNo,
00058     label& destI,
00059     List<taggedValue>& dest
00060 ) const
00061 {
00062     forAll(values, elemI)
00063     {
00064         taggedValue& tagVal = dest[destI];
00065 
00066         tagVal.value() = values[elemI];
00067         tagVal.index() = indices[elemI];
00068         tagVal.procID() = fromProcNo;
00069 
00070         destI++;
00071     }
00072 }
00073 
00074 
00075 template <class Type>
00076 void Foam::ParSortableList<Type>::getPivots
00077 (
00078     const List<Type>& elems,
00079     List<Type>& pivots
00080 ) const
00081 {
00082     pivots.setSize(Pstream::nProcs());
00083 
00084     label pivotPos = 0;
00085 
00086     forAll(pivots, pivotI)
00087     {
00088         pivots[pivotI] = elems[pivotPos];
00089 
00090         pivotPos += elems.size()/Pstream::nProcs();
00091     }
00092 }
00093 
00094 
00095 template <class Type>
00096 void Foam::ParSortableList<Type>::checkAndSend
00097 (
00098     List<Type>& values,
00099     labelList& indices,
00100     const label bufSize,
00101     const label destProcI
00102 ) const
00103 {
00104     if (destProcI != Pstream::myProcNo())
00105     {
00106         values.setSize(bufSize);
00107         indices.setSize(bufSize);
00108 
00109         if (debug)
00110         {
00111             Pout<<  "Sending to " << destProcI << " elements:" << values
00112                 << endl;
00113         }
00114 
00115         {
00116             OPstream toSlave(Pstream::blocking, destProcI);
00117             toSlave << values << indices;
00118         }
00119     }
00120 }
00121 
00122 
00123 
00124 
00125 
00126 template <class Type>
00127 Foam::ParSortableList<Type>::ParSortableList(const UList<Type>& values)
00128 :
00129     List<Type>(values),
00130     indices_(0),
00131     procs_(0)
00132 {
00133     sort();
00134 }
00135 
00136 
00137 
00138 template <class Type>
00139 Foam::ParSortableList<Type>::ParSortableList(const label size)
00140 :
00141     List<Type>(size),
00142     indices_(0),
00143     procs_(0)
00144 {}
00145 
00146 
00147 
00148 
00149 
00150 template <class Type>
00151 void Foam::ParSortableList<Type>::sort()
00152 {
00153     
00154     
00155     
00156 
00157     label n = this->size();
00158 
00159     reduce(n, sumOp<label>());
00160 
00161 
00162     
00163     SortableList<Type> sorted(*this);
00164 
00165     
00166     labelListList sortedGatherList(Pstream::nProcs());
00167 
00168     labelList& pivots = sortedGatherList[Pstream::myProcNo()];
00169 
00170     getPivots(sorted, pivots);
00171 
00172     if (debug)
00173     {
00174         Pout<< "pivots:";
00175         write(pivots, Pout);
00176         Pout<< endl;
00177     }
00178 
00179 
00180     
00181     
00182     
00183 
00184     Pstream::gatherList(sortedGatherList);
00185 
00186     if (Pstream::master())
00187     {
00188         labelList allPivots =
00189             ListListOps::combine<labelList>
00190             (
00191                 sortedGatherList,
00192                 accessOp<labelList>()
00193             );
00194 
00195         SortableList<Type> sortedPivots(allPivots);
00196 
00197         if (debug)
00198         {
00199             Pout<< "allPivots:";
00200             write(allPivots, Pout);
00201             Pout<< endl;
00202         }
00203 
00204         getPivots(sortedPivots, pivots);
00205     }
00206     Pstream::scatter(pivots);
00207 
00208     if (debug)
00209     {
00210         Pout<< "new pivots:";
00211         write(pivots, Pout);
00212         Pout<< endl;
00213     }
00214 
00215 
00216     
00217     
00218     
00219 
00220     label pivotI = 1;
00221     label destProcI = 0;
00222 
00223     
00224     labelList ownValues(sorted.size());
00225     labelList ownIndices(sorted.size());
00226     label ownI = 0;
00227 
00228     
00229     labelList sendValues(sorted.size());
00230     labelList sendIndices(sorted.size());
00231     label sendI = 0;
00232 
00233     forAll(sorted, sortedI)
00234     {
00235         if ((pivotI < Pstream::nProcs()) && (sorted[sortedI] > pivots[pivotI]))
00236         {
00237             checkAndSend(sendValues, sendIndices, sendI, destProcI);
00238 
00239             
00240             sendValues.setSize(sorted.size());
00241             sendIndices.setSize(sorted.size());
00242             sendI = 0;
00243 
00244             pivotI++;
00245             destProcI++;
00246         }
00247 
00248         if (destProcI != Pstream::myProcNo())
00249         {
00250             sendValues[sendI] = sorted[sortedI];
00251             sendIndices[sendI] = sorted.indices()[sortedI];
00252             sendI++;
00253         }
00254         else
00255         {
00256             ownValues[ownI] = sorted[sortedI];
00257             ownIndices[ownI] = sorted.indices()[sortedI];
00258             ownI++;
00259         }
00260     }
00261 
00262 
00263     
00264     if (sendI != 0)
00265     {
00266         checkAndSend(sendValues, sendIndices, sendI, destProcI);
00267     }
00268 
00269     
00270     ownValues.setSize(ownI);
00271     ownIndices.setSize(ownI);
00272 
00273     if (debug & 2)
00274     {
00275         Pout<< "Not sending (to myself) elements "
00276             << ownValues << endl;
00277     }
00278 
00279     
00280     
00281     
00282     
00283 
00284     
00285     
00286     List<taggedValue> combinedValues(2 * n/Pstream::nProcs());
00287 
00288     label combinedI = 0;
00289 
00290     for (label procI = 0; procI < Pstream::nProcs(); procI++)
00291     {
00292         if (procI == Pstream::myProcNo())
00293         {
00294             if (debug & 2)
00295             {
00296                 Pout<< "Copying from own:" << ownValues << endl;
00297             }
00298 
00299             
00300             copyInto(ownValues, ownIndices, procI, combinedI, combinedValues);
00301         }
00302         else
00303         {
00304             labelList recValues;
00305             labelList recIndices;
00306 
00307             {
00308                 if (debug)
00309                 {
00310                     Pout<< "Receiving from " << procI << endl;
00311                 }
00312 
00313                 IPstream fromSlave(Pstream::blocking, procI);
00314 
00315                 fromSlave >> recValues >> recIndices;
00316 
00317                 if (debug & 2)
00318                 {
00319                     Pout<< "Received from " << procI
00320                         << " elements:" << recValues << endl;
00321                 }
00322             }
00323 
00324             if (debug)
00325             {
00326                 Pout<< "Copying starting at:" << combinedI << endl;
00327             }
00328             copyInto(recValues, recIndices, procI, combinedI, combinedValues);
00329         }
00330     }
00331     combinedValues.setSize(combinedI);
00332 
00333     
00334     Foam::sort(combinedValues);
00335 
00336     
00337     this->setSize(combinedI);
00338     indices_.setSize(combinedI);
00339     procs_.setSize(combinedI);
00340 
00341     forAll(combinedValues, elemI)
00342     {
00343         this->operator[](elemI) = combinedValues[elemI].value();
00344         indices_[elemI] = combinedValues[elemI].index();
00345         procs_[elemI] = combinedValues[elemI].procID();
00346     }
00347 }
00348 
00349 
00350