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