OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
DynamicRectMatrix.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 DynamicRectMatrix.hpp
50 * @author Teng Lin
51 * @date 10/11/2004
52 * @version 2.0
53 */
54
55#ifndef MATH_DYNAMICRECTMATRIX_HPP
56#define MATH_DYNAMICRECTMATRIX_HPP
57
58#include <cassert>
59#include <cmath>
60#include <iostream>
61#include <vector>
62
64#include "math/RectMatrix.hpp"
65
66namespace OpenMD {
67
68 /**
69 * @class DynamicRectMatrix DynamicRectMatrix.hpp "math/DynamicRectMatrix.hpp"
70 * @brief Rectangular matrix class with contiguous flat storage.
71 *
72 * Elements are stored in row-major order in a single contiguous
73 * std::vector<Real>. Element (i,j) is at data_[i*ncol_ + j].
74 * The contiguous layout allows direct interop with BLAS/LAPACK
75 * (via getArrayPointer()) without an intermediate copy.
76 */
77 template<typename Real>
79 public:
80 using ElemType = Real;
81 using ElemPoinerType = Real*;
82 using SelfType = DynamicRectMatrix<Real>;
83
84 /** default constructor */
85 DynamicRectMatrix() : nrow_(0), ncol_(0) {}
86
87 DynamicRectMatrix(unsigned int nrow, unsigned int ncol) :
88 nrow_(nrow), ncol_(ncol), data_(nrow * ncol, Real(0)) {}
89
90 /** Constructs and initializes every element of this matrix to a scalar */
91 DynamicRectMatrix(unsigned int nrow, unsigned int ncol, Real s) :
92 nrow_(nrow), ncol_(ncol), data_(nrow * ncol, s) {}
93
94 DynamicRectMatrix(unsigned int nrow, unsigned int ncol, Real* array) :
95 nrow_(nrow), ncol_(ncol), data_(array, array + nrow * ncol) {}
96
97 /** copy constructor */
98 DynamicRectMatrix(const SelfType& m) = default;
99
100 /** destructor */
102
103 /** copy assignment operator */
105
106 /** move constructor */
107 DynamicRectMatrix(SelfType&& m) noexcept = default;
108
109 /** move assignment operator */
111
112 /**
113 * Returns the reference of a single element of this matrix.
114 * @param i row index
115 * @param j column index
116 */
117 Real& operator()(unsigned int i, unsigned int j) {
118 return data_[i * ncol_ + j];
119 }
120
121 /**
122 * Returns the value of a single element of this matrix.
123 * @param i row index
124 * @param j column index
125 */
126 Real operator()(unsigned int i, unsigned int j) const {
127 return data_[i * ncol_ + j];
128 }
129
130 /**
131 * Copies the internal data to an array (row-major order).
132 * @param array the pointer of destination array
133 */
134 void getArray(Real* array) const {
135 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
136 array[i] = data_[i];
137 }
138
139 /** Returns a pointer to the contiguous internal storage (row-major). */
140 Real* getArrayPointer() { return data_.data(); }
141 const Real* getArrayPointer() const { return data_.data(); }
142
143 /**
144 * Returns a row of this matrix as a vector.
145 * @param row the row index
146 */
147 DynamicVector<Real> getRow(unsigned int row) {
148 DynamicVector<Real> v(ncol_);
149 for (unsigned int i = 0; i < ncol_; i++)
150 v[i] = data_[row * ncol_ + i];
151 return v;
152 }
153
154 /**
155 * Sets a row of this matrix
156 * @param row the row index
157 * @param v the vector to be set
158 */
159 void setRow(unsigned int row, const DynamicVector<Real>& v) {
160 assert(v.size() == ncol_);
161 for (unsigned int i = 0; i < ncol_; i++)
162 data_[row * ncol_ + i] = v[i];
163 }
164
165 /**
166 * Returns a column of this matrix as a vector.
167 * @param col the column index
168 */
169 DynamicVector<Real> getColumn(unsigned int col) {
170 DynamicVector<Real> v(nrow_);
171 for (unsigned int j = 0; j < nrow_; j++)
172 v[j] = data_[j * ncol_ + col];
173 return v;
174 }
175
176 /**
177 * Sets a column of this matrix
178 * @param col the column index
179 * @param v the vector to be set
180 */
181 void setColumn(unsigned int col, const DynamicVector<Real>& v) {
182 for (unsigned int j = 0; j < nrow_; j++)
183 data_[j * ncol_ + col] = v[j];
184 }
185
186 /**
187 * swap two rows of this matrix
188 * @param i the first row
189 * @param j the second row
190 */
191 void swapRow(unsigned int i, unsigned int j) {
192 assert(i < nrow_ && j < nrow_);
193 for (unsigned int k = 0; k < ncol_; k++)
194 std::swap(data_[i * ncol_ + k], data_[j * ncol_ + k]);
195 }
196
197 /**
198 * swap two columns of this matrix
199 * @param i the first column
200 * @param j the second column
201 */
202 void swapColumn(unsigned int i, unsigned int j) {
203 assert(i < ncol_ && j < ncol_);
204 for (unsigned int k = 0; k < nrow_; k++)
205 std::swap(data_[k * ncol_ + i], data_[k * ncol_ + j]);
206 }
207
208 /** Returns a DynamicVector of the diagonal elements. */
210 unsigned int dim = (nrow_ < ncol_) ? nrow_ : ncol_;
211 DynamicVector<Real> result(dim);
212 for (unsigned int i = 0; i < dim; ++i)
213 result(i) = data_[i * ncol_ + i];
214 return result;
215 }
216
217 /**
218 * Tests if this matrix is identical to matrix m
219 * @param m matrix to be compared
220 */
221 bool operator==(const DynamicRectMatrix<Real>& m) const {
222 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
223 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
224 if (!equal(data_[i], m.data_[i])) return false;
225 return true;
226 }
227
228 /**
229 * Tests if this matrix is not equal to matrix m
230 * @param m matrix to be compared
231 */
232 bool operator!=(const DynamicRectMatrix<Real>& m) const {
233 return !(*this == m);
234 }
235
236 /** Negates the value of this matrix in place. */
237 inline void negate() {
238 for (auto& v : data_) v = -v;
239 }
240
241 /**
242 * Sets the value of this matrix to the negation of matrix m.
243 * @param m the source matrix
244 */
245 inline void negate(const DynamicRectMatrix<Real>& m) {
246 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
247 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
248 data_[i] = -m.data_[i];
249 }
250
251 /**
252 * Sets the value of this matrix to the sum of itself and m (*this += m).
253 * @param m the other matrix
254 */
255 inline void add(const DynamicRectMatrix<Real>& m) {
256 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
257 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
258 data_[i] += m.data_[i];
259 }
260
261 /**
262 * Sets the value of this matrix to the sum of m1 and m2 (*this = m1 + m2).
263 * @param m1 the first matrix
264 * @param m2 the second matrix
265 */
266 inline void add(const DynamicRectMatrix<Real>& m1,
267 const DynamicRectMatrix<Real>& m2) {
268 assert(m1.nrow_ == m2.nrow_ && m1.ncol_ == m2.ncol_);
269 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
270 data_[i] = m1.data_[i] + m2.data_[i];
271 }
272
273 /**
274 * Sets the value of this matrix to the difference of itself and m
275 * (*this -= m).
276 * @param m the other matrix
277 */
278 inline void sub(const DynamicRectMatrix<Real>& m) {
279 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
280 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
281 data_[i] -= m.data_[i];
282 }
283
284 /**
285 * Sets the value of this matrix to the difference of matrix m1 and m2
286 * (*this = m1 - m2).
287 * @param m1 the first matrix
288 * @param m2 the second matrix
289 */
290 inline void sub(const DynamicRectMatrix<Real>& m1,
291 const DynamicRectMatrix<Real>& m2) {
292 assert(m1.nrow_ == m2.nrow_ && m1.ncol_ == m2.ncol_);
293 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
294 data_[i] = m1.data_[i] - m2.data_[i];
295 }
296
297 /**
298 * Sets the value of this matrix to the scalar multiplication of itself
299 * (*this *= s).
300 * @param s the scalar value
301 */
302 inline void mul(Real s) {
303 for (auto& v : data_) v *= s;
304 }
305
306 /**
307 * Sets the value of this matrix to the scalar multiplication of matrix m
308 * (*this = s * m).
309 * @param s the scalar value
310 * @param m the matrix
311 */
312 inline void mul(Real s, const DynamicRectMatrix<Real>& m) {
313 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
314 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
315 data_[i] = s * m.data_[i];
316 }
317
318 /**
319 * Sets the value of this matrix to the scalar division of itself
320 * (*this /= s).
321 * @param s the scalar value
322 */
323 inline void div(Real s) {
324 for (auto& v : data_) v /= s;
325 }
326
327 /**
328 * Sets the value of this matrix to the scalar division of matrix m
329 * (*this = m / s).
330 * @param s the scalar value
331 * @param m the matrix
332 */
333 inline void div(Real s, const DynamicRectMatrix<Real>& m) {
334 assert(nrow_ == m.nrow_ && ncol_ == m.ncol_);
335 for (unsigned int i = 0; i < nrow_ * ncol_; i++)
336 data_[i] = m.data_[i] / s;
337 }
338
339 /**
340 * Multiples a scalar onto every element of this matrix.
341 * @param s the scalar value
342 */
344 this->mul(s);
345 return *this;
346 }
347
348 /**
349 * Divides every element of this matrix by a scalar.
350 * @param s the scalar value
351 */
353 this->div(s);
354 return *this;
355 }
356
357 /**
358 * Sets the value of this matrix to the sum of the other matrix and itself
359 * (*this += m).
360 * @param m the other matrix
361 */
363 add(m);
364 return *this;
365 }
366
367 /**
368 * Sets the value of this matrix to the difference of itself and the other
369 * matrix (*this -= m).
370 * @param m the other matrix
371 */
373 sub(m);
374 return *this;
375 }
376
377 /** Return the transpose of this matrix */
379 DynamicRectMatrix<Real> result(ncol_, nrow_);
380 for (unsigned int i = 0; i < nrow_; i++)
381 for (unsigned int j = 0; j < ncol_; j++)
382 result(j, i) = data_[i * ncol_ + j];
383 return result;
384 }
385
386 unsigned int getNRow() const { return nrow_; }
387 unsigned int getNCol() const { return ncol_; }
388
389 template<class MatrixType>
390 void setSubMatrix(unsigned int beginRow, unsigned int beginCol,
391 const MatrixType& m) {
392 assert(beginRow + m.getNRow() - 1 <= nrow_);
393 assert(beginCol + m.getNCol() - 1 <= ncol_);
394 for (unsigned int i = 0; i < m.getNRow(); ++i)
395 for (unsigned int j = 0; j < m.getNCol(); ++j)
396 data_[(beginRow + i) * ncol_ + (beginCol + j)] = m(i, j);
397 }
398
399 template<class MatrixType>
400 void getSubMatrix(unsigned int beginRow, unsigned int beginCol,
401 MatrixType& m) {
402 assert(beginRow + m.getNRow() - 1 <= nrow_);
403 assert(beginCol + m.getNCol() - 1 <= ncol_);
404 for (unsigned int i = 0; i < m.getNRow(); ++i)
405 for (unsigned int j = 0; j < m.getNCol(); ++j)
406 m(i, j) = data_[(beginRow + i) * ncol_ + (beginCol + j)];
407 }
408
409 protected:
410 unsigned int nrow_;
411 unsigned int ncol_;
412 std::vector<Real> data_;
413 };
414
415 /** Negate the value of every element of this matrix. */
416 template<typename Real>
418 DynamicRectMatrix<Real> result(m);
419 result.negate();
420 return result;
421 }
422
423 /**
424 * Return the sum of two matrices (m1 + m2).
425 * @param m1 the first matrix
426 * @param m2 the second matrix
427 */
428 template<typename Real>
430 const DynamicRectMatrix<Real>& m2) {
431 DynamicRectMatrix<Real> result(m1.getNRow(), m1.getNCol());
432 result.add(m1, m2);
433 return result;
434 }
435
436 /**
437 * Return the difference of two matrices (m1 - m2).
438 * @param m1 the first matrix
439 * @param m2 the second matrix
440 */
441 template<typename Real>
443 const DynamicRectMatrix<Real>& m2) {
444 DynamicRectMatrix<Real> result(m1.getNRow(), m1.getNCol());
445 result.sub(m1, m2);
446 return result;
447 }
448
449 /**
450 * Return the multiplication of scalar and matrix (m * s).
451 * @param m the matrix
452 * @param s the scalar
453 */
454 template<typename Real>
456 Real s) {
457 DynamicRectMatrix<Real> result(m.getNRow(), m.getNCol());
458 result.mul(s, m);
459 return result;
460 }
461
462 /**
463 * Return the multiplication of a scalar and a matrix (s * m).
464 * @param s the scalar
465 * @param m the matrix
466 */
467 template<typename Real>
469 const DynamicRectMatrix<Real>& m) {
470 DynamicRectMatrix<Real> result(m.getNRow(), m.getNCol());
471 result.mul(s, m);
472 return result;
473 }
474
475 /**
476 * Return the multiplication of two matrices (m1 * m2).
477 * @param m1 the first matrix
478 * @param m2 the second matrix
479 */
480 template<typename Real>
482 const DynamicRectMatrix<Real>& m2) {
483 assert(m1.getNCol() == m2.getNRow());
484 unsigned int sameDim = m1.getNCol();
485 unsigned int nrow = m1.getNRow();
486 unsigned int ncol = m2.getNCol();
487 DynamicRectMatrix<Real> result(nrow, ncol);
488 for (unsigned int i = 0; i < nrow; i++)
489 for (unsigned int j = 0; j < ncol; j++)
490 for (unsigned int k = 0; k < sameDim; k++)
491 result(i, j) += m1(i, k) * m2(k, j);
492 return result;
493 }
494
495 /**
496 * Return the multiplication of a matrix and a vector (m * v).
497 * @param m the matrix
498 * @param v the vector
499 */
500 template<typename Real>
502 const DynamicVector<Real>& v) {
503 unsigned int nrow = m.getNRow();
504 unsigned int ncol = m.getNCol();
505 assert(ncol == v.size());
506 DynamicVector<Real> result(nrow);
507 for (unsigned int i = 0; i < nrow; i++)
508 for (unsigned int j = 0; j < ncol; j++)
509 result[i] += m(i, j) * v[j];
510 return result;
511 }
512
513 /**
514 * Return the scalar division of matrix (m / s).
515 * @param m the matrix
516 * @param s the scalar
517 */
518 template<typename Real>
520 Real s) {
521 DynamicRectMatrix<Real> result(m.getNRow(), m.getNCol());
522 result.div(s, m);
523 return result;
524 }
525
526 /**
527 * Write to an output stream
528 */
529 template<typename Real>
530 std::ostream& operator<<(std::ostream& o, const DynamicRectMatrix<Real>& m) {
531 for (unsigned int i = 0; i < m.getNRow(); i++) {
532 o << "(";
533 for (unsigned int j = 0; j < m.getNCol(); j++) {
534 o << m(i, j);
535 if (j != m.getNCol() - 1) o << "\t";
536 }
537 o << ")" << std::endl;
538 }
539 return o;
540 }
541} // namespace OpenMD
542
543#endif // MATH_DYNAMICRECTMATRIX_HPP
DynamicRectMatrix()
default constructor
Rectangular matrix class with contiguous flat storage.
void add(const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the sum of itself and m (*this += m).
void mul(Real s, const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the scalar multiplication of matrix m (*this = s * m).
DynamicRectMatrix< Real > & operator-=(const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the difference of itself and the other matrix (*this -= m).
DynamicRectMatrix< Real > & operator=(DynamicRectMatrix< Real > &&m) noexcept=default
move assignment operator
void swapColumn(unsigned int i, unsigned int j)
swap two columns of this matrix
void negate()
Negates the value of this matrix in place.
DynamicVector< Real > diagonals() const
Returns a DynamicVector of the diagonal elements.
DynamicVector< Real > getRow(unsigned int row)
Returns a row of this matrix as a vector.
void swapRow(unsigned int i, unsigned int j)
swap two rows of this matrix
void div(Real s)
Sets the value of this matrix to the scalar division of itself (*this /= s).
Real & operator()(unsigned int i, unsigned int j)
Returns the reference of a single element of this matrix.
bool operator==(const DynamicRectMatrix< Real > &m) const
Tests if this matrix is identical to matrix m.
Real operator()(unsigned int i, unsigned int j) const
Returns the value of a single element of this matrix.
void div(Real s, const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the scalar division of matrix m (*this = m / s).
void negate(const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the negation of matrix m.
void mul(Real s)
Sets the value of this matrix to the scalar multiplication of itself (*this *= s).
~DynamicRectMatrix()=default
destructor
void setColumn(unsigned int col, const DynamicVector< Real > &v)
Sets a column of this matrix.
DynamicRectMatrix< Real > & operator*=(const Real s)
Multiples a scalar onto every element of this matrix.
DynamicRectMatrix< Real > & operator+=(const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the sum of the other matrix and itself (*this += m).
void sub(const DynamicRectMatrix< Real > &m)
Sets the value of this matrix to the difference of itself and m (*this -= m).
DynamicRectMatrix< Real > transpose() const
Return the transpose of this matrix.
void getArray(Real *array) const
Copies the internal data to an array (row-major order).
void setRow(unsigned int row, const DynamicVector< Real > &v)
Sets a row of this matrix.
void add(const DynamicRectMatrix< Real > &m1, const DynamicRectMatrix< Real > &m2)
Sets the value of this matrix to the sum of m1 and m2 (*this = m1 + m2).
DynamicVector< Real > getColumn(unsigned int col)
Returns a column of this matrix as a vector.
void sub(const DynamicRectMatrix< Real > &m1, const DynamicRectMatrix< Real > &m2)
Sets the value of this matrix to the difference of matrix m1 and m2 (*this = m1 - m2).
DynamicRectMatrix()
default constructor
DynamicRectMatrix< Real > & operator/=(const Real s)
Divides every element of this matrix by a scalar.
DynamicRectMatrix(unsigned int nrow, unsigned int ncol, Real s)
Constructs and initializes every element of this matrix to a scalar.
bool operator!=(const DynamicRectMatrix< Real > &m) const
Tests if this matrix is not equal to matrix m.
DynamicRectMatrix(SelfType &&m) noexcept=default
move constructor
DynamicRectMatrix< Real > & operator=(const DynamicRectMatrix< Real > &m)=default
copy assignment operator
Real * getArrayPointer()
Returns a pointer to the contiguous internal storage (row-major).
DynamicRectMatrix(const SelfType &m)=default
copy constructor
Dynamically-sized vector class.
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.
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).
DynamicRectMatrix< Real > operator/(const DynamicRectMatrix< Real > &m, Real s)
Return the scalar division of matrix (m / s).