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 "hierarchGeomDecomp.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <OpenFOAM/PstreamReduceOps.H>
00029 #include <OpenFOAM/SortableList.H>
00030 
00031 
00032 
00033 namespace Foam
00034 {
00035     defineTypeNameAndDebug(hierarchGeomDecomp, 0);
00036 
00037     addToRunTimeSelectionTable
00038     (
00039         decompositionMethod,
00040         hierarchGeomDecomp,
00041         dictionary
00042     );
00043 
00044     addToRunTimeSelectionTable
00045     (
00046         decompositionMethod,
00047         hierarchGeomDecomp,
00048         dictionaryMesh
00049     );
00050 }
00051 
00052 
00053 
00054 void Foam::hierarchGeomDecomp::setDecompOrder()
00055 {
00056     word order(geomDecomDict_.lookup("order"));
00057 
00058     if (order.size() != 3)
00059     {
00060         FatalIOErrorIn
00061         (
00062             "hierarchGeomDecomp::hierarchGeomDecomp"
00063             "(const dictionary& decompositionDict)",
00064             decompositionDict_
00065         )   << "number of characters in order (" << order << ") != 3"
00066             << exit(FatalIOError);
00067     }
00068 
00069     for (label i = 0; i < 3; i++)
00070     {
00071         if (order[i] == 'x')
00072         {
00073             decompOrder_[i] = 0;
00074         }
00075         else if (order[i] == 'y')
00076         {
00077             decompOrder_[i] = 1;
00078         }
00079         else if (order[i] == 'z')
00080         {
00081             decompOrder_[i] = 2;
00082         }
00083         else
00084         {
00085             FatalIOErrorIn
00086             (
00087                 "hierarchGeomDecomp::hierarchGeomDecomp"
00088                 "(const dictionary& decompositionDict)",
00089                 decompositionDict_
00090             )   << "Illegal decomposition order " << order << endl
00091                 << "It should only contain x, y or z" << exit(FatalError);
00092         }
00093     }
00094 }
00095 
00096 
00097 Foam::label Foam::hierarchGeomDecomp::findLower
00098 (
00099     const List<scalar>& l,
00100     const scalar t,
00101     const label initLow,
00102     const label initHigh
00103 )
00104 {
00105     if (initHigh <= initLow)
00106     {
00107         return initLow;
00108     }
00109 
00110     label low = initLow;
00111     label high = initHigh;
00112 
00113     while ((high - low) > 1)
00114     {
00115         label mid = (low + high)/2;
00116 
00117         if (l[mid] < t)
00118         {
00119             low = mid;
00120         }
00121         else
00122         {
00123             high = mid;
00124         }
00125     }
00126 
00127     
00128 
00129     label tIndex = -1;
00130 
00131     if (l[high-1] < t)
00132     {
00133         tIndex = high;
00134     }
00135     else
00136     {
00137         tIndex = low;
00138     }
00139 
00140     return tIndex;
00141 }
00142 
00143 
00144 
00145 
00146 
00147 void Foam::hierarchGeomDecomp::calculateSortedWeightedSizes
00148 (
00149     const labelList& current,
00150     const labelList& indices,
00151     const scalarField& weights,
00152     const label globalCurrentSize,
00153 
00154     scalarField& sortedWeightedSizes
00155 )
00156 {
00157     
00158     sortedWeightedSizes[0] = 0;
00159     forAll(current, i)
00160     {
00161         label pointI = current[indices[i]];
00162         sortedWeightedSizes[i + 1] = sortedWeightedSizes[i] + weights[pointI];
00163     }
00164     
00165     scalar globalCurrentLength = returnReduce
00166     (
00167         sortedWeightedSizes[current.size()],
00168         sumOp<scalar>()
00169     );
00170     
00171     
00172     sortedWeightedSizes *= (globalCurrentSize/globalCurrentLength);
00173 }
00174 
00175 
00176 
00177 
00178 void Foam::hierarchGeomDecomp::findBinary
00179 (
00180     const label sizeTol,
00181     const List<scalar>& values,
00182     const label minIndex,       
00183     const scalar minValue,      
00184     const scalar maxValue,      
00185     const scalar wantedSize,    
00186 
00187     label& mid,                 
00188                                 
00189     scalar& midValue            
00190 )
00191 {
00192     label low = minIndex;
00193     scalar lowValue = minValue;
00194 
00195     scalar highValue = maxValue;
00196     
00197     label high = values.size();
00198 
00199     
00200     scalar midValuePrev = VGREAT;
00201 
00202     while (true)
00203     {
00204         label size = returnReduce(mid-minIndex, sumOp<label>());
00205 
00206         if (debug)
00207         {
00208             Pout<< "    low:" << low << " lowValue:" << lowValue
00209                 << " high:" << high << " highValue:" << highValue
00210                 << " mid:" << mid << " midValue:" << midValue << endl
00211                 << "    globalSize:" << size << " wantedSize:" << wantedSize
00212                 << " sizeTol:" << sizeTol << endl;
00213         }
00214 
00215         if (wantedSize < size - sizeTol)
00216         {
00217             high = mid;
00218             highValue = midValue;
00219         }
00220         else if (wantedSize > size + sizeTol)
00221         {
00222             low = mid;
00223             lowValue = midValue;
00224         }
00225         else
00226         {
00227             break;
00228         }
00229 
00230         
00231         midValue = 0.5*(lowValue+highValue);
00232         mid = findLower(values, midValue, low, high);
00233 
00234         
00235         bool hasNotChanged = (mag(midValue-midValuePrev) < SMALL);
00236 
00237         if (returnReduce(hasNotChanged, andOp<bool>()))
00238         {
00239             WarningIn("hierarchGeomDecomp::findBinary(..)")
00240                 << "unable to find desired deomposition split, making do!"
00241                 << endl;
00242             break;
00243         }
00244 
00245         midValuePrev = midValue;
00246     }
00247 }
00248 
00249 
00250 
00251 
00252 void Foam::hierarchGeomDecomp::findBinary
00253 (
00254     const label sizeTol,
00255     const List<scalar>& sortedWeightedSizes,
00256     const List<scalar>& values,
00257     const label minIndex,       
00258     const scalar minValue,      
00259     const scalar maxValue,      
00260     const scalar wantedSize,    
00261 
00262     label& mid,                 
00263                                 
00264     scalar& midValue            
00265 )
00266 {
00267     label low = minIndex;
00268     scalar lowValue = minValue;
00269 
00270     scalar highValue = maxValue;
00271     
00272     label high = values.size();
00273 
00274     
00275     scalar midValuePrev = VGREAT;
00276 
00277     while (true)
00278     {
00279         scalar weightedSize = returnReduce
00280         (
00281             sortedWeightedSizes[mid] - sortedWeightedSizes[minIndex],
00282             sumOp<scalar>()
00283         );
00284 
00285         if (debug)
00286         {
00287             Pout<< "    low:" << low << " lowValue:" << lowValue
00288                 << " high:" << high << " highValue:" << highValue
00289                 << " mid:" << mid << " midValue:" << midValue << endl
00290                 << "    globalSize:" << weightedSize
00291                 << " wantedSize:" << wantedSize
00292                 << " sizeTol:" << sizeTol << endl;
00293         }
00294 
00295         if (wantedSize < weightedSize - sizeTol)
00296         {
00297             high = mid;
00298             highValue = midValue;
00299         }
00300         else if (wantedSize > weightedSize + sizeTol)
00301         {
00302             low = mid;
00303             lowValue = midValue;
00304         }
00305         else
00306         {
00307             break;
00308         }
00309 
00310         
00311         midValue = 0.5*(lowValue+highValue);
00312         mid = findLower(values, midValue, low, high);
00313 
00314         
00315         bool hasNotChanged = (mag(midValue-midValuePrev) < SMALL);
00316 
00317         if (returnReduce(hasNotChanged, andOp<bool>()))
00318         {
00319             WarningIn("hierarchGeomDecomp::findBinary(..)")
00320                 << "unable to find desired deomposition split, making do!"
00321                 << endl;
00322             break;
00323         }
00324 
00325         midValuePrev = midValue;
00326     }
00327 }
00328 
00329 
00330 
00331 void Foam::hierarchGeomDecomp::sortComponent
00332 (
00333     const label sizeTol,
00334     const pointField& points,
00335     const labelList& current,       
00336     const direction componentIndex, 
00337     const label mult,               
00338     labelList& finalDecomp
00339 )
00340 {
00341     
00342     label compI = decompOrder_[componentIndex];
00343 
00344     if (debug)
00345     {
00346         Pout<< "sortComponent : Sorting slice of size " << current.size()
00347             << " in component " << compI << endl;
00348     }
00349 
00350     
00351     SortableList<scalar> sortedCoord(current.size());
00352 
00353     forAll(current, i)
00354     {
00355         label pointI = current[i];
00356 
00357         sortedCoord[i] = points[pointI][compI];
00358     }
00359     sortedCoord.sort();
00360 
00361     label globalCurrentSize = returnReduce(current.size(), sumOp<label>());
00362 
00363     scalar minCoord = returnReduce
00364     (
00365         (
00366             sortedCoord.size()
00367           ? sortedCoord[0]
00368           : GREAT
00369         ),
00370         minOp<scalar>()
00371     );
00372 
00373     scalar maxCoord = returnReduce
00374     (
00375         (
00376             sortedCoord.size()
00377           ? sortedCoord[sortedCoord.size()-1]
00378           : -GREAT
00379         ),
00380         maxOp<scalar>()
00381     );
00382 
00383     if (debug)
00384     {
00385         Pout<< "sortComponent : minCoord:" << minCoord
00386             << " maxCoord:" << maxCoord << endl;
00387     }
00388 
00389     
00390     label leftIndex = 0;
00391     
00392     scalar leftCoord = minCoord;
00393 
00394     
00395     for (label bin = 0; bin < n_[compI]; bin++)
00396     {
00397         
00398         
00399         
00400         
00401 
00402         
00403         label localSize = -1;     
00404 
00405         
00406         scalar rightCoord = -GREAT;
00407 
00408         if (bin == n_[compI]-1)
00409         {
00410             
00411             localSize = current.size()-leftIndex;
00412             rightCoord = maxCoord;                  
00413         }
00414         else if (Pstream::nProcs() == 1)
00415         {
00416             
00417             localSize = label(current.size()/n_[compI]);
00418             rightCoord = sortedCoord[leftIndex+localSize];
00419         }
00420         else
00421         {
00422             
00423             
00424             
00425 
00426             label rightIndex = current.size();
00427             rightCoord = maxCoord;
00428 
00429             
00430             findBinary
00431             (
00432                 sizeTol,
00433                 sortedCoord,
00434                 leftIndex,
00435                 leftCoord,
00436                 maxCoord,
00437                 globalCurrentSize/n_[compI],  
00438 
00439                 rightIndex,
00440                 rightCoord
00441             );
00442             localSize = rightIndex - leftIndex;
00443         }
00444 
00445         if (debug)
00446         {
00447             Pout<< "For component " << compI << ", bin " << bin
00448                 << " copying" << endl
00449                 << "from " << leftCoord << " at local index "
00450                 << leftIndex << endl
00451                 << "to " << rightCoord << " localSize:"
00452                 << localSize << endl
00453                 << endl;
00454         }
00455 
00456 
00457         
00458         labelList slice(localSize);
00459 
00460         forAll(slice, i)
00461         {
00462             label pointI = current[sortedCoord.indices()[leftIndex+i]];
00463 
00464             
00465             finalDecomp[pointI] += bin*mult;
00466 
00467             
00468             slice[i] = pointI;
00469         }
00470 
00471         
00472         if (componentIndex < 2)
00473         {
00474             string oldPrefix;
00475             if (debug)
00476             {
00477                 oldPrefix = Pout.prefix();
00478                 Pout.prefix() = "  " + oldPrefix;
00479             }
00480 
00481             sortComponent
00482             (
00483                 sizeTol,
00484                 points,
00485                 slice,
00486                 componentIndex+1,
00487                 mult*n_[compI],     
00488                 finalDecomp
00489             );
00490 
00491             if (debug)
00492             {
00493                 Pout.prefix() = oldPrefix;
00494             }
00495         }
00496 
00497         
00498         leftIndex += localSize;
00499         leftCoord = rightCoord;
00500     }
00501 }
00502 
00503 
00504 
00505 void Foam::hierarchGeomDecomp::sortComponent
00506 (
00507     const label sizeTol,
00508     const scalarField& weights,
00509     const pointField& points,
00510     const labelList& current,       
00511     const direction componentIndex, 
00512     const label mult,               
00513     labelList& finalDecomp
00514 )
00515 {
00516     
00517     label compI = decompOrder_[componentIndex];
00518 
00519     if (debug)
00520     {
00521         Pout<< "sortComponent : Sorting slice of size " << current.size()
00522             << " in component " << compI << endl;
00523     }
00524 
00525     
00526     SortableList<scalar> sortedCoord(current.size());
00527 
00528     forAll(current, i)
00529     {
00530         label pointI = current[i];
00531 
00532         sortedCoord[i] = points[pointI][compI];
00533     }
00534     sortedCoord.sort();
00535 
00536     label globalCurrentSize = returnReduce(current.size(), sumOp<label>());
00537 
00538     
00539     
00540     scalarField sortedWeightedSizes(current.size()+1, 0);
00541     calculateSortedWeightedSizes
00542     (
00543         current,
00544         sortedCoord.indices(),
00545         weights,
00546         globalCurrentSize,
00547         sortedWeightedSizes
00548     );
00549 
00550     scalar minCoord = returnReduce
00551     (
00552         (
00553             sortedCoord.size()
00554           ? sortedCoord[0]
00555           : GREAT
00556         ),
00557         minOp<scalar>()
00558     );
00559 
00560     scalar maxCoord = returnReduce
00561     (
00562         (
00563             sortedCoord.size()
00564           ? sortedCoord[sortedCoord.size()-1]
00565           : -GREAT
00566         ),
00567         maxOp<scalar>()
00568     );
00569 
00570     if (debug)
00571     {
00572         Pout<< "sortComponent : minCoord:" << minCoord
00573             << " maxCoord:" << maxCoord << endl;
00574     }
00575 
00576     
00577     label leftIndex = 0;
00578     
00579     scalar leftCoord = minCoord;
00580 
00581     
00582     for (label bin = 0; bin < n_[compI]; bin++)
00583     {
00584         
00585         
00586         
00587         
00588 
00589         
00590         label localSize = -1;     
00591 
00592         
00593         scalar rightCoord = -GREAT;
00594 
00595         if (bin == n_[compI]-1)
00596         {
00597             
00598             localSize = current.size()-leftIndex;
00599             rightCoord = maxCoord;                  
00600         }
00601         else
00602         {
00603             
00604             
00605             
00606             
00607 
00608             label rightIndex = current.size();
00609             rightCoord = maxCoord;
00610 
00611             
00612             findBinary
00613             (
00614                 sizeTol,
00615                 sortedWeightedSizes,
00616                 sortedCoord,
00617                 leftIndex,
00618                 leftCoord,
00619                 maxCoord,
00620                 globalCurrentSize/n_[compI],  
00621 
00622                 rightIndex,
00623                 rightCoord
00624             );
00625             localSize = rightIndex - leftIndex;
00626         }
00627 
00628         if (debug)
00629         {
00630             Pout<< "For component " << compI << ", bin " << bin
00631                 << " copying" << endl
00632                 << "from " << leftCoord << " at local index "
00633                 << leftIndex << endl
00634                 << "to " << rightCoord << " localSize:"
00635                 << localSize << endl
00636                 << endl;
00637         }
00638 
00639 
00640         
00641         labelList slice(localSize);
00642 
00643         forAll(slice, i)
00644         {
00645             label pointI = current[sortedCoord.indices()[leftIndex+i]];
00646 
00647             
00648             finalDecomp[pointI] += bin*mult;
00649 
00650             
00651             slice[i] = pointI;
00652         }
00653 
00654         
00655         if (componentIndex < 2)
00656         {
00657             string oldPrefix;
00658             if (debug)
00659             {
00660                 oldPrefix = Pout.prefix();
00661                 Pout.prefix() = "  " + oldPrefix;
00662             }
00663 
00664             sortComponent
00665             (
00666                 sizeTol,
00667                 weights,
00668                 points,
00669                 slice,
00670                 componentIndex+1,
00671                 mult*n_[compI],     
00672                 finalDecomp
00673             );
00674 
00675             if (debug)
00676             {
00677                 Pout.prefix() = oldPrefix;
00678             }
00679         }
00680 
00681         
00682         leftIndex += localSize;
00683         leftCoord = rightCoord;
00684     }
00685 }
00686 
00687 
00688 
00689 
00690 Foam::hierarchGeomDecomp::hierarchGeomDecomp
00691 (
00692     const dictionary& decompositionDict
00693 )
00694 :
00695     geomDecomp(decompositionDict, typeName),
00696     decompOrder_()
00697 {
00698     setDecompOrder();
00699 }
00700 
00701 
00702 Foam::hierarchGeomDecomp::hierarchGeomDecomp
00703 (
00704     const dictionary& decompositionDict,
00705     const polyMesh&
00706 )
00707 :
00708     geomDecomp(decompositionDict, hierarchGeomDecomp::typeName),
00709     decompOrder_()
00710 {
00711     setDecompOrder();
00712 }
00713 
00714 
00715 
00716 
00717 Foam::labelList Foam::hierarchGeomDecomp::decompose
00718 (
00719     const pointField& points
00720 )
00721 {
00722     
00723     labelList finalDecomp(points.size(), 0);
00724 
00725     
00726     labelList slice(points.size());
00727     forAll(slice, i)
00728     {
00729         slice[i] = i;
00730     }
00731 
00732     pointField rotatedPoints = rotDelta_ & points;
00733 
00734 
00735     
00736     
00737     
00738     label allSize = points.size();
00739     reduce(allSize, sumOp<label>());
00740 
00741     const label sizeTol = max(1, label(1E-3*allSize/nProcessors_));
00742 
00743     
00744     sortComponent
00745     (
00746         sizeTol,
00747         rotatedPoints,
00748         slice,
00749         0,              
00750         1,              
00751         finalDecomp
00752     );
00753 
00754     return finalDecomp;
00755 }
00756 
00757 
00758 Foam::labelList Foam::hierarchGeomDecomp::decompose
00759 (
00760     const pointField& points,
00761     const scalarField& weights
00762 )
00763 {
00764     
00765     labelList finalDecomp(points.size(), 0);
00766 
00767     
00768     labelList slice(points.size());
00769     forAll(slice, i)
00770     {
00771         slice[i] = i;
00772     }
00773 
00774     pointField rotatedPoints = rotDelta_ & points;
00775 
00776     
00777     
00778     
00779     label allSize = points.size();
00780     reduce(allSize, sumOp<label>());
00781 
00782     const label sizeTol = max(1, label(1E-3*allSize/nProcessors_));
00783 
00784     
00785     sortComponent
00786     (
00787         sizeTol,
00788         weights,
00789         rotatedPoints,
00790         slice,
00791         0,              
00792         1,              
00793         finalDecomp
00794     );
00795 
00796     return finalDecomp;
00797 }
00798 
00799 
00800