--- trunk/src/utils/OpenMDBitSet.cpp 2010/05/10 17:28:26 1442 +++ branches/development/src/utils/OpenMDBitSet.cpp 2013/02/20 15:39:39 1850 @@ -35,16 +35,21 @@ * * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005). * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006). - * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008). - * [4] Vardeman & Gezelter, in progress (2009). + * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008). + * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010). + * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011). */ #include #include #include +#include #include "utils/OpenMDBitSet.hpp" #include "utils/Algorithm.hpp" +#ifdef IS_MPI +#include +#endif namespace OpenMD { int OpenMDBitSet::countBits() { @@ -63,8 +68,8 @@ namespace OpenMD { assert(fromIndex <= toIndex); assert(fromIndex >=0); assert(toIndex <= size()); - std::vector::iterator first = bitset_.begin() + fromIndex; - std::vector::iterator last = bitset_.begin() + toIndex; + std::vector::iterator first = bitset_.begin() + fromIndex; + std::vector::iterator last = bitset_.begin() + toIndex; std::transform(first, last, first, std::logical_not()); @@ -74,8 +79,8 @@ namespace OpenMD { assert(fromIndex <= toIndex); assert(fromIndex >=0); assert(toIndex <= size()); - std::vector::iterator first = bitset_.begin() + fromIndex; - std::vector::iterator last = bitset_.begin() + toIndex; + std::vector::iterator first = bitset_.begin() + fromIndex; + std::vector::iterator last = bitset_.begin() + toIndex; OpenMDBitSet result; std::copy(first, last, std::back_inserter(result.bitset_)); @@ -83,7 +88,7 @@ namespace OpenMD { } bool OpenMDBitSet::none() { - std::vector::iterator i = std::find(bitset_.begin(), bitset_.end(), true); + std::vector::iterator i = std::find(bitset_.begin(), bitset_.end(), true); return i == bitset_.end() ? true : false; } @@ -141,8 +146,8 @@ namespace OpenMD { assert(fromIndex <= toIndex); assert(fromIndex >=0); assert(toIndex <= size()); - std::vector::iterator first = bitset_.begin() + fromIndex; - std::vector::iterator last = bitset_.begin() + toIndex; + std::vector::iterator first = bitset_.begin() + fromIndex; + std::vector::iterator last = bitset_.begin() + toIndex; std::fill(first, last, value); } @@ -189,6 +194,34 @@ namespace OpenMD { bool operator== (const OpenMDBitSet & bs1, const OpenMDBitSet &bs2) { assert(bs1.size() == bs2.size()); return std::equal(bs1.bitset_.begin(), bs1.bitset_.end(), bs2.bitset_.begin()); + } + + OpenMDBitSet OpenMDBitSet::parallelReduce() { + OpenMDBitSet result; + +#ifdef IS_MPI + + // This is necessary because std::vector isn't really a + // std::vector, so we can't pass the address of the first element + // to the MPI call that follows. We first have to convert to a + // std::vector to do the logical_or Allreduce call, then back + // convert it into the vector. + + std::vector bsInt(bitset_.begin(), bitset_.end()); + + MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &bsInt[0], + bsInt.size(), MPI::INT, MPI::LOR); + + std::transform(bsInt.begin(), bsInt.end(), + std::back_inserter( result.bitset_ ), to_bool()); +#else + + // Not in MPI? Just return a copy of the current bitset: + std::copy(bitset_.begin(), bitset_.end(), + std::back_inserter( result.bitset_ )); +#endif + + return result; } //std::istream& operator>> ( std::istream& is, const OpenMDBitSet& bs) { @@ -197,7 +230,7 @@ namespace OpenMD { //} std::ostream& operator<< ( std::ostream& os, const OpenMDBitSet& bs) { - for (int i = 0; i < bs.bitset_.size(); ++i) { + for (unsigned int i = 0; i < bs.bitset_.size(); ++i) { std::string val = bs[i] ? "true" : "false"; os << "OpenMDBitSet[" << i <<"] = " << val << std::endl; }