OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
DynamicVector.hpp
Go to the documentation of this file.
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/**
49 * @file DynamicVector.hpp
50 * @author Teng Lin
51 * @date 09/14/2004
52 * @version 1.0
53 */
54
55#ifndef MATH_DYNAMICVECTOR_HPP
56#define MATH_DYNAMICVECTOR_HPP
57
58#include <algorithm>
59#include <cassert>
60#include <cmath>
61#include <initializer_list>
62#include <iostream>
63#include <vector>
64
65#include "math/Vector.hpp"
66
67namespace OpenMD {
68
69 /**
70 * @class DynamicVector DynamicVector.hpp "math/DynamicVector.hpp"
71 * @brief Dynamically-sized vector class
72 */
73 template<typename Real, typename Alloc = std::allocator<Real>>
75 public:
76 using value_type = Real;
77 using allocator_type = Alloc;
78 using VectorType = std::vector<Real, Alloc>;
79 using size_type = typename VectorType::size_type;
80 using difference_type = typename VectorType::difference_type;
81 using reference = typename VectorType::reference;
82 using const_reference = typename VectorType::const_reference;
83 using pointer = typename VectorType::pointer;
84 using const_pointer = typename VectorType::const_pointer;
85 using iterator = typename VectorType::iterator;
86 using const_iterator = typename VectorType::const_iterator;
87 using reverse_iterator = typename VectorType::reverse_iterator;
88 using const_reverse_iterator = typename VectorType::const_reverse_iterator;
89
90 /**
91 * @brief Default constructor creates no elements.
92 * @param alloc The allocator_type to use
93 */
94 explicit DynamicVector(const allocator_type& alloc = allocator_type()) :
95 data_(alloc) {}
96
97 /**
98 * @brief Create a %DynamicVector with copies of an exemplar element.
99 * @param n The number of elements to initially create.
100 * @param value An element to copy.
101 * @param alloc The allocator_type to use
102 *
103 * This constructor fills the %DynamicVector with @a n copies of @a value.
104 */
105 DynamicVector(size_type n, const value_type& value,
106 const allocator_type& alloc = allocator_type()) :
107 data_(n, value, alloc) {}
108
109 /**
110 * @brief Create a %DynamicVector with default elements.
111 * @param n The number of elements to initially create.
112 * @param alloc The allocator_type to use
113 *
114 * This constructor fills the %DynamicVector with @a n copies of a
115 * default-constructed element.
116 */
117 explicit DynamicVector(size_type n,
118 const allocator_type& alloc = allocator_type()) :
119 data_(n, alloc) {}
120
121 /**
122 * @brief Create a %DynamicVector using an iterator range
123 * @param first The beginning of the range to copy the elements from
124 * @param last The end of the range to copy the elements from
125 * @param alloc The allocator_type to use
126 */
127 template<typename InputIterator>
128 DynamicVector(InputIterator first, InputIterator last,
129 const allocator_type& alloc = allocator_type()) :
130 data_(first, last, alloc) {}
131
132 /**
133 * @brief Create a %DynamicVector with the contents of an initializer_list
134 * @param init Initializer list to initialize the elements with
135 * @param alloc The allocator_type to use
136 */
137 DynamicVector(std::initializer_list<value_type> init,
138 const allocator_type& alloc = allocator_type()) :
139 data_(init, alloc) {}
140
141 // Element access functions
142 reference operator[](size_type i) { return data_[i]; }
143 const_reference operator[](size_type i) const { return data_[i]; }
144
145 reference operator()(size_type i) { return data_[i]; }
146 const_reference operator()(size_type i) const { return data_[i]; }
147
148 // Iterator functions
149 iterator begin() noexcept { return data_.begin(); }
150 const_iterator begin() const noexcept { return data_.begin(); }
151 const_iterator cbegin() const noexcept { return data_.cbegin(); }
152
153 iterator end() noexcept { return data_.end(); }
154 const_iterator end() const noexcept { return data_.end(); }
155 const_iterator cend() const noexcept { return data_.cend(); }
156
157 // Capacity functions
158 bool empty() const noexcept { return data_.empty(); }
159 size_type size() const noexcept { return data_.size(); }
160
161 // Modifier functions
162 void resize(size_type n) { return data_.resize(n); }
163 void resize(size_type n, const value_type& value) {
164 data_.resize(n, value);
165 }
166
167 void reserve(size_type new_cap) { data_.reserve(new_cap); }
168
169 /**
170 * Tests if this vetor is equal to other vector
171 * @return true if equal, otherwise return false
172 * @param v vector to be compared
173 */
175 if (this->size() != v.size()) return false;
176
177 return std::equal(
178 this->begin(), this->end(), v.begin(),
179 [](Real val1, Real val2) { return OpenMD::equal(val1, val2); });
180 }
181
182 /**
183 * Tests if this vetor is not equal to other vector
184 * @return true if equal, otherwise return false
185 * @param v vector to be compared
186 */
187 bool operator!=(const DynamicVector<Real>& v) { return !(*this == v); }
188
189 /** Negates the value of this vector in place. */
190 void negate() {
191 std::transform(this->begin(), this->end(), this->begin(),
192 [](Real val) { return -val; });
193 }
194
195 /**
196 * Sets the value of this vector to the negation of vector v1.
197 * @param v1 the source vector
198 */
199 void negate(const DynamicVector<Real>& v1) {
200 std::transform(v1.begin(), v1.end(), this->begin(),
201 [](Real val) { return -val; });
202 }
203
204 /**
205 * Sets the value of this vector to the sum of itself and v1 (*this += v1).
206 * @param v1 the other vector
207 */
208 void add(const DynamicVector<Real>& v1) {
209 std::transform(this->begin(), this->end(), v1.begin(), this->begin(),
210 [](Real val1, Real val2) { return val1 + val2; });
211 }
212
213 /**
214 * Sets the value of this vector to the sum of v1 and v2 (*this = v1 + v2).
215 * @param v1 the first vector
216 * @param v2 the second vector
217 */
218 void add(const DynamicVector<Real>& v1, const DynamicVector<Real>& v2) {
219 std::transform(v1.begin(), v1.end(), v2.begin(), this->begin(),
220 [](Real val1, Real val2) { return val1 + val2; });
221 }
222
223 /**
224 * Sets the value of this vector to the difference of itself and v1 (*this
225 * -= v1).
226 * @param v1 the other vector
227 */
228 void sub(const DynamicVector<Real>& v1) {
229 std::transform(this->begin(), this->end(), v1.begin(), this->begin(),
230 [](Real val1, Real val2) { return val1 - val2; });
231 }
232
233 /**
234 * Sets the value of this vector to the difference of vector v1 and v2
235 * (*this = v1 - v2).
236 * @param v1 the first vector
237 * @param v2 the second vector
238 */
239 void sub(const DynamicVector<Real>& v1, const DynamicVector<Real>& v2) {
240 std::transform(v1.begin(), v1.end(), v2.begin(), this->begin(),
241 [](Real val1, Real val2) { return val1 - val2; });
242 }
243
244 /**
245 * Sets the value of this vector to the scalar multiplication of itself
246 * (*this *= s).
247 * @param s the scalar value
248 */
249 void mul(Real s) {
250 std::transform(this->begin(), this->end(), this->begin(),
251 [s](Real val) { return val * s; });
252 }
253
254 /**
255 * Sets the value of this vector to the scalar multiplication of vector v1
256 * (*this = s * v1).
257 * @param v1 the vector
258 * @param s the scalar value
259 */
260 void mul(const DynamicVector<Real>& v1, Real s) {
261 if (this->size() != v1.size()) this->resize(v1.size());
262
263 std::transform(v1.begin(), v1.end(), this->begin(),
264 [s](Real val) { return val * s; });
265 }
266
267 /**
268 * Sets the value of this vector to the scalar division of itself
269 * (*this /= s).
270 * @param s the scalar value
271 */
272 void div(Real s) {
273 std::transform(this->begin(), this->end(), this->begin(),
274 [s](Real val) { return val / s; });
275 }
276
277 /**
278 * Sets the value of this vector to the scalar division of vector v1
279 * (*this = v1 / s).
280 * @param v1 the source vector
281 * @param s the scalar value
282 */
283 void div(const DynamicVector<Real>& v1, Real s) {
284 if (this->size() != v1.size()) this->resize(v1.size());
285
286 std::transform(v1.begin(), v1.end(), this->begin(),
287 [s](Real val) { return val / s; });
288 }
289
290 /** @see #add */
292 add(v1);
293 return *this;
294 }
295
296 /** @see #sub */
298 sub(v1);
299 return *this;
300 }
301
302 /** @see #mul */
304 mul(s);
305 return *this;
306 }
307
308 /** @see #div */
310 div(s);
311 return *this;
312 }
313
314 /** zero out the vector */
315 void setZero() { std::fill(this->begin(), this->end(), 0); }
316
317 /**
318 * Returns the length of this vector.
319 * @return the length of this vector
320 */
321 Real length() { return std::sqrt(lengthSquare()); }
322
323 /**
324 * Returns the squared length of this vector.
325 * @return the squared length of this vector
326 */
327 Real lengthSquare() { return dot(*this, *this); }
328
329 /** Returns a vector containing the absolute value of each element. */
331 DynamicVector<Real> result(this->size());
332 std::transform(this->begin(), this->end(), result.begin(),
333 [](Real val) { return std::abs(val); });
334 return result;
335 }
336
337 /** Returns the largest element of this vector. */
338 Real max() const { return *std::max_element(this->begin(), this->end()); }
339
340 /** Normalizes this vector in place */
341 void normalize() {
342 Real len = length();
343
344 // if (len < OpenMD::Constants::epsilon)
345 // throw();
346
347 *this /= len;
348 }
349
350 /**
351 * Tests if this vector is normalized
352 * @return true if this vector is normalized, otherwise return false
353 */
354 bool isNormalized() { return OpenMD::equal(lengthSquare(), 1.0); }
355
356 template<class VectorType>
357 void getSubVector(size_type beginning, VectorType& v) {
358 assert(beginning + v.size() - 1 <= this->size());
359
360 for (size_type i {}; i < v.size(); ++i)
361 v(i) = (*this)[beginning + i];
362 }
363
364 private:
365 std::vector<Real, Alloc> data_;
366 };
367
368 /** unary minus*/
369 template<typename Real>
371 DynamicVector<Real> tmp(v1);
372 tmp.negate();
373 return tmp;
374 }
375
376 /**
377 * Return the sum of two vectors (v1 - v2).
378 * @return the sum of two vectors
379 * @param v1 the first vector
380 * @param v2 the second vector
381 */
382 template<typename Real>
383 inline DynamicVector<Real> operator+(const DynamicVector<Real>& v1,
384 const DynamicVector<Real>& v2) {
385 assert(v1.size() == v2.size());
386 DynamicVector<Real> result(v1.size());
387 result.add(v1, v2);
388 return result;
389 }
390
391 /**
392 * Return the difference of two vectors (v1 - v2).
393 * @return the difference of two vectors
394 * @param v1 the first vector
395 * @param v2 the second vector
396 */
397 template<typename Real>
399 const DynamicVector<Real>& v2) {
400 assert(v1.size() == v2.size());
401 DynamicVector<Real> result(v1.size());
402 result.sub(v1, v2);
403 return result;
404 }
405
406 /**
407 * Returns the vaule of scalar multiplication of this vector v1 (v1 * r).
408 * @return the vaule of scalar multiplication of this vector
409 * @param v1 the source vector
410 * @param s the scalar value
411 */
412 template<typename Real>
414 DynamicVector<Real> result(v1.size());
415 result.mul(v1, s);
416 return result;
417 }
418
419 /**
420 * Returns the vaule of scalar multiplication of this vector v1 (v1 * r).
421 * @return the vaule of scalar multiplication of this vector
422 * @param s the scalar value
423 * @param v1 the source vector
424 */
425 template<typename Real>
427 DynamicVector<Real> result(v1.size());
428 result.mul(v1, s);
429 return result;
430 }
431
432 /**
433 * Returns the value of division of a vector by a scalar.
434 * @return the vaule of scalar division of this vector
435 * @param v1 the source vector
436 * @param s the scalar value
437 */
438 template<typename Real>
440 DynamicVector<Real> result(v1.size());
441 result.div(v1, s);
442 return result;
443 }
444
445 /**
446 * Returns the dot product of two DynamicVectors
447 * @param v1 first vector
448 * @param v2 second vector
449 * @return the dot product of v1 and v2
450 */
451 template<typename Real>
452 inline Real dot(const DynamicVector<Real>& v1,
453 const DynamicVector<Real>& v2) {
454 Real tmp;
455 tmp = 0;
456 assert(v1.size() == v2.size());
457 for (typename DynamicVector<Real>::size_type i {}; i < v1.size(); i++)
458 tmp += v1[i] * v2[i];
459
460 return tmp;
461 }
462
463 /**
464 * Returns the distance between two DynamicVectors
465 * @param v1 first vector
466 * @param v2 second vector
467 * @return the distance between v1 and v2
468 */
469 template<typename Real>
470 inline Real distance(const DynamicVector<Real>& v1,
471 const DynamicVector<Real>& v2) {
472 DynamicVector<Real> tempDynamicVector = v1 - v2;
473 return tempDynamicVector.length();
474 }
475
476 /**
477 * Returns the squared distance between two DynamicVectors
478 * @param v1 first vector
479 * @param v2 second vector
480 * @return the squared distance between v1 and v2
481 */
482 template<typename Real>
483 inline Real distanceSquare(const DynamicVector<Real>& v1,
484 const DynamicVector<Real>& v2) {
485 DynamicVector<Real> tempDynamicVector = v1 - v2;
486 return tempDynamicVector.lengthSquare();
487 }
488
489 /**
490 * Write to an output stream
491 */
492 template<typename Real>
493 std::ostream& operator<<(std::ostream& strm, const DynamicVector<Real>& v) {
494 strm << "[ ";
495
496 std::for_each(v.begin(), v.end() - 1,
497 [&strm](auto elem) { strm << elem << ", "; });
498
499 strm << *(v.end() - 1) << " ]";
500
501 return strm;
502 }
503} // namespace OpenMD
504
505#endif
DynamicVector(const allocator_type &alloc=allocator_type())
Default constructor creates no elements.
Dynamically-sized vector class.
DynamicVector< Real > & operator-=(const DynamicVector< Real > &v1)
DynamicVector< Real > abs() const
Returns a vector containing the absolute value of each element.
void setZero()
zero out the vector
Real max() const
Returns the largest element of this vector.
DynamicVector(size_type n, const value_type &value, const allocator_type &alloc=allocator_type())
Create a DynamicVector with copies of an exemplar element.
void negate(const DynamicVector< Real > &v1)
Sets the value of this vector to the negation of vector v1.
DynamicVector(const allocator_type &alloc=allocator_type())
Default constructor creates no elements.
void negate()
Negates the value of this vector in place.
void normalize()
Normalizes this vector in place.
void add(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Sets the value of this vector to the sum of v1 and v2 (*this = v1 + v2).
DynamicVector< Real > & operator+=(const DynamicVector< Real > &v1)
void sub(const DynamicVector< Real > &v1)
Sets the value of this vector to the difference of itself and v1 (*this -= v1).
DynamicVector(InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())
Create a DynamicVector using an iterator range.
void sub(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Sets the value of this vector to the difference of vector v1 and v2 (*this = v1 - v2).
void mul(Real s)
Sets the value of this vector to the scalar multiplication of itself (*this *= s).
DynamicVector(size_type n, const allocator_type &alloc=allocator_type())
Create a DynamicVector with default elements.
void div(Real s)
Sets the value of this vector to the scalar division of itself (*this /= s).
bool operator==(const DynamicVector< Real > &v)
Tests if this vetor is equal to other vector.
void div(const DynamicVector< Real > &v1, Real s)
Sets the value of this vector to the scalar division of vector v1 (*this = v1 / s).
DynamicVector(std::initializer_list< value_type > init, const allocator_type &alloc=allocator_type())
Create a DynamicVector with the contents of an initializer_list.
Real lengthSquare()
Returns the squared length of this vector.
DynamicVector< Real > & operator*=(Real s)
Real length()
Returns the length of this vector.
bool isNormalized()
Tests if this vector is normalized.
void mul(const DynamicVector< Real > &v1, Real s)
Sets the value of this vector to the scalar multiplication of vector v1 (*this = s * v1).
void add(const DynamicVector< Real > &v1)
Sets the value of this vector to the sum of itself and v1 (*this += v1).
bool operator!=(const DynamicVector< Real > &v)
Tests if this vetor is not equal to other vector.
DynamicVector< Real > & operator/=(Real s)
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.
bool equal(const Polynomial< Real > &p1, const Polynomial< Real > &p2)
Tests if two polynomial have the same exponents.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).
Real distanceSquare(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the squared distance between two DynamicVectors.
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.
DynamicRectMatrix< Real > operator/(const DynamicRectMatrix< Real > &m, Real s)
Return the scalar division of matrix (m / s).