ExaFMM 1
Fast-multipole Method for exascale systems
|
00001 /* 00002 Copyright (C) 2011 by Rio Yokota, Simon Layton, Lorena Barba 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 #ifndef sort_h 00023 #define sort_h 00024 #include "../include/logger.h" 00025 00026 //! Custom bucket sort for body and cell structures 00027 class Sort : public Logger { 00028 private: 00029 std::vector<int> bucket; //!< Bucket for sorting 00030 00031 //! Get bucket size for sorting 00032 template<typename T> 00033 void getBucketSize(T &values, int begin, int end, bigint &Imin, int &numBucket) { 00034 typename T::iterator V0 = values.begin()+begin; // Get begin iterator 00035 typename T::iterator VN = values.begin()+end; // Get end iterator 00036 Imin = V0->ICELL; // Initialize minimum index 00037 bigint Imax = V0->ICELL; // Initialize maximum index 00038 for( typename T::iterator V=V0; V!=VN; ++V ) { // Loop over vector 00039 if ( V->ICELL < Imin ) Imin = V->ICELL; // Set minimum index 00040 else if( V->ICELL > Imax ) Imax = V->ICELL; // Set maximum index 00041 } // End loop over vector 00042 numBucket = Imax - Imin + 1; // Use range of indices as bucket size 00043 if( numBucket > int(bucket.size()) ) { // If bucket size needs to be enlarged 00044 bucket.resize(numBucket); // Resize bucket vector 00045 } // Endif for resize 00046 } 00047 00048 //! Bucket sort for small indices 00049 template<typename T> 00050 void sortICELL(T &values, T &buffer, bigint Imin, 00051 int numBucket, bool ascend, int begin, int end) { 00052 startTimer("Fill bucket "); // Start timer 00053 for( int i=0; i!=numBucket; ++i ) bucket[i] = 0; // Initialize bucket 00054 for( int i=begin; i!=end; ++i ) bucket[values[i].ICELL-Imin]++;// Fill bucket 00055 for( int i=1; i!=numBucket; ++i ) bucket[i] += bucket[i-1]; // Scan bucket 00056 stopTimer("Fill bucket "); // Stop timer 00057 startTimer("Empty bucket "); // Start timer 00058 for( int i=end-1; i>=begin; --i ) { // Loop over data backwards 00059 bucket[values[i].ICELL-Imin]--; // Empty bucket 00060 int inew = bucket[values[i].ICELL-Imin]+begin; // Permutation index 00061 buffer[inew] = values[i]; // Fill buffer 00062 } // End loop over data 00063 stopTimer("Empty bucket "); // Stop timer 00064 startTimer("Copy value "); // Start timer 00065 if( ascend ) { // If sorting in ascending order 00066 #pragma omp parallel for 00067 for( int i=begin; i<end; ++i ) values[i] = buffer[i]; // Copy back bodiess in order 00068 } else { // If sorting in descending order 00069 #pragma omp parallel for 00070 for( int i=begin; i<end; ++i ) values[end-i+begin-1] = buffer[i];// Copy back bodiess in reverse order 00071 } // Endif for sorting order 00072 stopTimer("Copy value "); // Stop timer 00073 } 00074 00075 public: 00076 //! Sort bodies accoring to cell index 00077 void sortBodies(Bodies &bodies, Bodies &buffer, bool ascend=true, int begin=0, int end=0) { 00078 startTimer("Sort bodies "); // Start timer 00079 if( bodies.size() == 0 ) return; // Don't do anything if vector is empty 00080 if( end == 0 ) end = bodies.size(); // Default range is the whole vector 00081 int numBucket = 0; // Initialize bucket size 00082 bigint Imin = 0; // Initialize minimum index 00083 getBucketSize(bodies,begin,end,Imin,numBucket); // Get bucket size for sorting 00084 stopTimer("Sort bodies "); // Stop timer 00085 sortICELL(bodies,buffer,Imin,numBucket,ascend,begin,end); // Call bucket sort for small indices 00086 } 00087 00088 //! Sort cells according to cell index 00089 void sortCells(Cells &cells, Cells &buffer, bool ascend=true, int begin=0, int end=0) { 00090 startTimer("Sort cells "); // Start timer 00091 if( cells.size() == 0 ) return; // Don't do anything if vector is empty 00092 if( end == 0 ) end = cells.size(); // Default rage is the whole vector 00093 int numBucket = 0; // Initialize bucket size 00094 bigint Imin = 0; // Initialize minimum index 00095 getBucketSize(cells,begin,end,Imin,numBucket); // Get bucket size for sorting 00096 stopTimer("Sort cells "); // Stop timer 00097 if( buffer.size() < cells.size() ) buffer.resize(cells.size());// Resize sort buffer if necessary 00098 sortICELL(cells,buffer,Imin,numBucket,ascend,begin,end); // Call bucket sort for small indices 00099 } 00100 }; 00101 00102 #endif