OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
OpenMDBitSet.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "utils/OpenMDBitSet.hpp"
49
50#include <algorithm>
51#include <cassert>
52#include <functional>
53#include <iterator>
54#include <string>
55
56#ifdef IS_MPI
57#include <mpi.h>
58#endif
59
60namespace OpenMD {
61
63 return std::count(bitset_.begin(), bitset_.end(), true);
64 }
65
66 void OpenMDBitSet::flip(size_t fromIndex, size_t toIndex) {
67 assert(fromIndex <= toIndex);
68 assert(fromIndex >= 0);
69 assert(toIndex <= size());
70 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
71 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
72
73 std::transform(first, last, first, std::logical_not<bool>());
74 }
75
76 OpenMDBitSet OpenMDBitSet::get(size_t fromIndex, size_t toIndex) {
77 assert(fromIndex <= toIndex);
78 assert(fromIndex >= 0);
79 assert(toIndex <= size());
80 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
81 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
82
83 OpenMDBitSet result;
84 std::copy(first, last, std::back_inserter(result.bitset_));
85 return result;
86 }
87
89 std::vector<bool>::iterator i =
90 std::find(bitset_.begin(), bitset_.end(), true);
91 return i == bitset_.end() ? true : false;
92 }
93
94 int OpenMDBitSet::nextOffBit(int fromIndex) const {
95 if (fromIndex <= -1) {
96 // in case -1 or other negative number is passed to this function
97 return -1;
98 }
99
100 ++fromIndex;
101 while (fromIndex < static_cast<int>(size())) {
102 if (!bitset_[fromIndex]) { return fromIndex; }
103 ++fromIndex;
104 }
105
106 return -1;
107 }
108
109 int OpenMDBitSet::nthOffBit(unsigned long int n) const {
110 std::vector<int> indices;
111 for (int i = firstOffBit(); i != -1; i = nextOffBit(i)) {
112 indices.push_back(i);
113 }
114
115 if (n < indices.size()) return indices[n];
116 return -1;
117 }
118
119 int OpenMDBitSet::nextOnBit(int fromIndex) const {
120 if (fromIndex <= -1) {
121 // in case -1 or other negative number is passed to this function
122 return -1;
123 }
124
125 ++fromIndex;
126 while (fromIndex < static_cast<int>(size())) {
127 if (bitset_[fromIndex]) { return fromIndex; }
128 ++fromIndex;
129 }
130
131 return -1;
132 }
133
134 int OpenMDBitSet::nthOnBit(unsigned long int n) const {
135 std::vector<int> indices;
136 for (int i = firstOnBit(); i != -1; i = nextOnBit(i)) {
137 indices.push_back(i);
138 }
139
140 if (n < indices.size()) return indices[n];
141 return -1;
142 }
143
144 void OpenMDBitSet::andOperator(const OpenMDBitSet& bs) {
145 assert(size() == bs.size());
146
147 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
148 bitset_.begin(), std::logical_and<bool>());
149 }
150
151 void OpenMDBitSet::orOperator(const OpenMDBitSet& bs) {
152 assert(size() == bs.size());
153 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
154 bitset_.begin(), std::logical_or<bool>());
155 }
156
157 void OpenMDBitSet::xorOperator(const OpenMDBitSet& bs) {
158 assert(size() == bs.size());
159 std::transform(bs.bitset_.begin(), bs.bitset_.end(), bitset_.begin(),
160 bitset_.begin(), std::bit_xor<bool>());
161 }
162
163 void OpenMDBitSet::setBits(size_t fromIndex, size_t toIndex, bool value) {
164 assert(fromIndex <= toIndex);
165 assert(fromIndex >= 0);
166 assert(toIndex <= size());
167 std::vector<bool>::iterator first = bitset_.begin() + fromIndex;
168 std::vector<bool>::iterator last = bitset_.begin() + toIndex;
169 std::fill(first, last, value);
170 }
171
172 void OpenMDBitSet::resize(size_t nbits) {
173 size_t oldSize = size();
174 bitset_.resize(nbits);
175 if (nbits > oldSize) {
176 std::fill(bitset_.begin() + oldSize, bitset_.end(), false);
177 }
178 }
179
180 OpenMDBitSet operator|(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
181 assert(bs1.size() == bs2.size());
182
183 OpenMDBitSet result(bs1);
184 result |= bs2;
185 return result;
186 }
187
188 OpenMDBitSet operator&(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
189 assert(bs1.size() == bs2.size());
190
191 OpenMDBitSet result(bs1);
192 result &= bs2;
193 return result;
194 }
195
196 OpenMDBitSet operator^(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
197 assert(bs1.size() == bs2.size());
198
199 OpenMDBitSet result(bs1);
200 result ^= bs2;
201 return result;
202 }
203
204 OpenMDBitSet operator-(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
205 assert(bs1.size() == bs2.size());
206
207 OpenMDBitSet result(bs1);
208 result -= bs2;
209 return result;
210 }
211
212 bool operator==(const OpenMDBitSet& bs1, const OpenMDBitSet& bs2) {
213 assert(bs1.size() == bs2.size());
214 return std::equal(bs1.bitset_.begin(), bs1.bitset_.end(),
215 bs2.bitset_.begin());
216 }
217
218 OpenMDBitSet OpenMDBitSet::parallelReduce() {
219 OpenMDBitSet result;
220
221#ifdef IS_MPI
222
223 // This is necessary because std::vector<bool> isn't really a
224 // std::vector, so we can't pass the address of the first element
225 // to the MPI call that follows. We first have to convert to a
226 // std::vector<int> to do the logical_or Allreduce call, then back
227 // convert it into the vector<bool>.
228
229 std::vector<int> bsInt(bitset_.begin(), bitset_.end());
230
231 MPI_Allreduce(MPI_IN_PLACE, &bsInt[0], bsInt.size(), MPI_INT, MPI_LOR,
232 MPI_COMM_WORLD);
233
234 std::transform(bsInt.begin(), bsInt.end(),
235 std::back_inserter(result.bitset_),
236 [](int val) { return val != 0; });
237#else
238 // Not in MPI? Just return a copy of the current bitset:
239 std::copy(bitset_.begin(), bitset_.end(),
240 std::back_inserter(result.bitset_));
241#endif
242
243 return result;
244 }
245
246 // std::istream& operator>> ( std::istream& is, const OpenMDBitSet& bs) {
247 //
248 // return is;
249 //}
250
251 std::ostream& operator<<(std::ostream& os, const OpenMDBitSet& bs) {
252 for (size_t i = 0; i < bs.bitset_.size(); ++i) {
253 std::string val = bs[i] ? "true" : "false";
254 os << "OpenMDBitSet[" << i << "] = " << val << std::endl;
255 }
256
257 return os;
258 }
259
260} // namespace OpenMD
OpenMDBitSet is a wrapper class of std::vector<bool> to act as a growable std::bitset.
void andOperator(const OpenMDBitSet &bs)
Performs a logical AND of this target bit set with the argument bit set.
void flip()
Sets each bit to the complement of its current value.
bool none()
Returns true if no bits are set to true.
void resize(size_t nbits)
Changes the size of OpenMDBitSet.
int countBits()
Returns the number of bits set to true in this OpenMDBitSet.
size_t size() const
Returns the number of bits of space actually in use by this OpenMDBitSet to represent bit values.
int nextOnBit(int fromIndex) const
Returns the index of the first bit that is set to true that occurs on or after the specified starting...
bool get(size_t bitIndex)
Returns the value of the bit with the specified index.
void xorOperator(const OpenMDBitSet &bs)
Performs a logical XOR of this bit set with the bit set argument.
int nthOffBit(unsigned long int n) const
Returns the index of the n^th bit that is set to false.
int nextOffBit(int fromIndex) const
Returns the index of the first bit that is set to false that occurs on or after the specified startin...
void orOperator(const OpenMDBitSet &bs)
Performs a logical OR of this bit set with the bit set argument.
int nthOnBit(unsigned long int n) const
Returns the index of the n^th bit that is set to true.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
DynamicRectMatrix< Real > operator-(const DynamicRectMatrix< Real > &m)
Negate the value of every element of this matrix.