OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
SquareMatrix3.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 SquareMatrix3.hpp
50 * @author Teng Lin
51 * @date 10/11/2004
52 * @version 1.0
53 */
54
55#ifndef MATH_SQUAREMATRIX3_HPP
56#define MATH_SQUAREMATRIX3_HPP
57
58#include <config.h>
59
60#include <cmath>
61#include <limits>
62#include <vector>
63
64#include "Quaternion.hpp"
65#include "SquareMatrix.hpp"
66#include "Vector3.hpp"
67
68namespace OpenMD {
69
70 template<typename Real>
71 class SquareMatrix3 : public SquareMatrix<Real, 3> {
72 public:
73 using ElemType = Real;
74 using ElemPoinerType = Real*;
75
76 /** default constructor */
77 SquareMatrix3() : SquareMatrix<Real, 3>() {}
78
79 /** Constructs and initializes every element of this matrix to a scalar */
80 SquareMatrix3(Real s) : SquareMatrix<Real, 3>(s) {}
81
82 /** Constructs and initializes from an array */
83 SquareMatrix3(Real* array) : SquareMatrix<Real, 3>(array) {}
84
85 /** copy constructor */
87
88 /** Construct from a RectMatrix (e.g. the result of matrix arithmetic). */
90
91 SquareMatrix3(const Vector3<Real>& eulerAngles) {
92 setupRotMat(eulerAngles);
93 }
94
95 SquareMatrix3(Real phi, Real theta, Real psi) {
96 setupRotMat(phi, theta, psi);
97 }
98
99 SquareMatrix3(const Quaternion<Real>& q) { setupRotMat(q); }
100
101 SquareMatrix3(Real w, Real x, Real y, Real z) { setupRotMat(w, x, y, z); }
102
103 /** copy assignment operator */
105 if (this == &m) return *this;
107 return *this;
108 }
109
111 this->setupRotMat(q);
112 return *this;
113 }
114
115 /**
116 * Sets this matrix to a rotation matrix by three euler angles
117 * @ param euler
118 */
119 void setupRotMat(const Vector3<Real>& eulerAngles) {
120 setupRotMat(eulerAngles[0], eulerAngles[1], eulerAngles[2]);
121 }
122
123 /**
124 * Sets this matrix to a rotation matrix by three euler angles
125 * @param phi
126 * @param theta
127 * @param psi
128 */
129 void setupRotMat(Real phi, Real theta, Real psi) {
130 Real sphi, stheta, spsi;
131 Real cphi, ctheta, cpsi;
132
133 sphi = sin(phi);
134 stheta = sin(theta);
135 spsi = sin(psi);
136 cphi = cos(phi);
137 ctheta = cos(theta);
138 cpsi = cos(psi);
139
140 this->data_[0][0] = cpsi * cphi - ctheta * sphi * spsi;
141 this->data_[0][1] = cpsi * sphi + ctheta * cphi * spsi;
142 this->data_[0][2] = spsi * stheta;
143
144 this->data_[1][0] = -spsi * cphi - ctheta * sphi * cpsi;
145 this->data_[1][1] = -spsi * sphi + ctheta * cphi * cpsi;
146 this->data_[1][2] = cpsi * stheta;
147
148 this->data_[2][0] = stheta * sphi;
149 this->data_[2][1] = -stheta * cphi;
150 this->data_[2][2] = ctheta;
151 }
152
153 /**
154 * Sets this matrix to a rotation matrix by quaternion
155 * @param quat
156 */
157 void setupRotMat(const Quaternion<Real>& quat) {
158 setupRotMat(quat.w(), quat.x(), quat.y(), quat.z());
159 }
160
161 /**
162 * Sets this matrix to a rotation matrix by quaternion
163 * @param w the first element
164 * @param x the second element
165 * @param y the third element
166 * @param z the fourth element
167 */
168 void setupRotMat(Real w, Real x, Real y, Real z) {
169 Quaternion<Real> q(w, x, y, z);
170 *this = q.toRotationMatrix3();
171 }
172
173 void setupSkewMat(Vector3<Real> v) { setupSkewMat(v[0], v[1], v[2]); }
174
175 void setupSkewMat(Real v1, Real v2, Real v3) {
176 this->data_[0][0] = 0;
177 this->data_[0][1] = -v3;
178 this->data_[0][2] = v2;
179 this->data_[1][0] = v3;
180 this->data_[1][1] = 0;
181 this->data_[1][2] = -v1;
182 this->data_[2][0] = -v2;
183 this->data_[2][1] = v1;
184 this->data_[2][2] = 0;
185 }
186
187 /**
188 * Sets this matrix to a symmetric tensor using Voigt Notation
189 * @param vt
190 */
192 setupVoigtTensor(vt[0], vt[1], vt[2], vt[3], vt[4], vt[5]);
193 }
194
195 void setupVoigtTensor(Real v1, Real v2, Real v3, Real v4, Real v5,
196 Real v6) {
197 this->data_[0][0] = v1;
198 this->data_[1][1] = v2;
199 this->data_[2][2] = v3;
200 this->data_[1][2] = v4;
201 this->data_[2][1] = v4;
202 this->data_[0][2] = v5;
203 this->data_[2][0] = v5;
204 this->data_[0][1] = v6;
205 this->data_[1][0] = v6;
206 }
207
208 /**
209 * Sets this matrix to an upper-triangular (asymmetric) tensor
210 * using Voigt Notation
211 * @param vt
212 */
214 setupUpperTriangularVoigtTensor(vt[0], vt[1], vt[2], vt[3], vt[4], vt[5]);
215 }
216
217 void setupUpperTriangularVoigtTensor(Real v1, Real v2, Real v3, Real v4,
218 Real v5, Real v6) {
219 this->data_[0][0] = v1;
220 this->data_[1][1] = v2;
221 this->data_[2][2] = v3;
222 this->data_[1][2] = v4;
223 this->data_[0][2] = v5;
224 this->data_[0][1] = v6;
225 }
226
227 /**
228 * Uses Rodrigues' rotation formula for a rotation matrix.
229 * @param axis the axis to rotate around
230 * @param angle the angle to rotate (in radians)
231 */
232 void axisAngle(Vector3d axis, RealType angle) {
233 axis.normalize();
234 RealType ct = cos(angle);
235 RealType st = sin(angle);
236
237 *this = ct * SquareMatrix3<Real>::identity();
238 *this += st * SquareMatrix3<Real>::setupSkewMat(axis);
239 *this += (1 - ct) * SquareMatrix3<Real>::outProduct(axis, axis);
240 }
241
242 /**
243 * Returns the quaternion from this rotation matrix
244 * @return the quaternion from this rotation matrix
245 * @exception invalid rotation matrix
246 */
249 Real t, s;
250 Real ad1, ad2, ad3;
251 t = this->data_[0][0] + this->data_[1][1] + this->data_[2][2] + 1.0;
252
253 if (t > std::numeric_limits<RealType>::epsilon()) {
254 s = 0.5 / sqrt(t);
255 q[0] = 0.25 / s;
256 q[1] = (this->data_[1][2] - this->data_[2][1]) * s;
257 q[2] = (this->data_[2][0] - this->data_[0][2]) * s;
258 q[3] = (this->data_[0][1] - this->data_[1][0]) * s;
259 } else {
260 ad1 = this->data_[0][0];
261 ad2 = this->data_[1][1];
262 ad3 = this->data_[2][2];
263
264 if (ad1 >= ad2 && ad1 >= ad3) {
265 s = 0.5 / sqrt(1.0 + this->data_[0][0] - this->data_[1][1] -
266 this->data_[2][2]);
267 q[0] = (this->data_[1][2] - this->data_[2][1]) * s;
268 q[1] = 0.25 / s;
269 q[2] = (this->data_[0][1] + this->data_[1][0]) * s;
270 q[3] = (this->data_[0][2] + this->data_[2][0]) * s;
271 } else if (ad2 >= ad1 && ad2 >= ad3) {
272 s = 0.5 / sqrt(1.0 + this->data_[1][1] - this->data_[0][0] -
273 this->data_[2][2]);
274 q[0] = (this->data_[2][0] - this->data_[0][2]) * s;
275 q[1] = (this->data_[0][1] + this->data_[1][0]) * s;
276 q[2] = 0.25 / s;
277 q[3] = (this->data_[1][2] + this->data_[2][1]) * s;
278 } else {
279 s = 0.5 / sqrt(1.0 + this->data_[2][2] - this->data_[0][0] -
280 this->data_[1][1]);
281 q[0] = (this->data_[0][1] - this->data_[1][0]) * s;
282 q[1] = (this->data_[0][2] + this->data_[2][0]) * s;
283 q[2] = (this->data_[1][2] + this->data_[2][1]) * s;
284 q[3] = 0.25 / s;
285 }
286 }
287
288 return q;
289 }
290
291 /**
292 * Returns the euler angles from this rotation matrix
293 * @return the euler angles in a vector
294 * @exception invalid rotation matrix
295 * We use so-called "x-convention", which is the most common definition.
296 * In this convention, the rotation given by Euler angles (phi, theta,
297 * psi), where the first rotation is by an angle phi about the z-axis,
298 * the second is by an angle theta (0 <= theta <= 180) about the x-axis,
299 * and the third is by an angle psi about the z-axis (again).
300 */
302 Vector3<Real> myEuler;
303 Real phi;
304 Real theta;
305 Real psi;
306 Real ctheta;
307 Real stheta;
308
309 // set the tolerance for Euler angles and rotation elements
310
311 theta = acos(
312 std::min((RealType)1.0, std::max((RealType)-1.0, this->data_[2][2])));
313 ctheta = this->data_[2][2];
314 stheta = sqrt(1.0 - ctheta * ctheta);
315
316 // when sin(theta) is close to 0, we need to consider
317 // singularity In this case, we can assign an arbitary value to
318 // phi (or psi), and then determine the psi (or phi) or
319 // vice-versa. We'll assume that phi always gets the rotation,
320 // and psi is 0 in cases of singularity.
321 // we use atan2 instead of atan, since atan2 will give us -Pi to Pi.
322 // Since 0 <= theta <= 180, sin(theta) will be always
323 // non-negative. Therefore, it will never change the sign of both of
324 // the parameters passed to atan2.
325
326 if (fabs(stheta) < 1e-6) {
327 psi = 0.0;
328 phi = atan2(-this->data_[1][0], this->data_[0][0]);
329 }
330 // we only have one unique solution
331 else {
332 phi = atan2(this->data_[2][0], -this->data_[2][1]);
333 psi = atan2(this->data_[0][2], this->data_[1][2]);
334 }
335
336 // wrap phi and psi, make sure they are in the range from 0 to 2*Pi
337 if (phi < 0) phi += 2.0 * Constants::PI;
338
339 if (psi < 0) psi += 2.0 * Constants::PI;
340
341 myEuler[0] = phi;
342 myEuler[1] = theta;
343 myEuler[2] = psi;
344
345 return myEuler;
346 }
347
348 bool closeEnough(
349 const Real& a, const Real& b,
350 const Real& epsilon = std::numeric_limits<Real>::epsilon()) {
351 return (epsilon > std::abs(a - b));
352 }
353
354 Vector3<Real> toRPY() {
355 const Real PI = 3.14159265358979323846264;
356 // check for gimbal lock
357 if (closeEnough(this->data_[0][2], -1.0)) {
358 Real x = 0; // gimbal lock, value of x doesn't matter
359 Real y = PI / 2;
360 Real z = x + atan2(this->data_[1][0], this->data_[2][0]);
361 return Vector3<Real>(x, y, z);
362 } else if (closeEnough(this->data_[0][2], 1.0)) {
363 Real x = 0;
364 Real y = -PI / 2;
365 Real z = -x + atan2(-this->data_[1][0], -this->data_[2][0]);
366 return Vector3<Real>(x, y, z);
367 } else {
368 // two solutions exist
369 Real x1 = -asin(this->data_[0][2]);
370 Real x2 = PI - x1;
371
372 Real y1 =
373 atan2(this->data_[1][2] / cos(x1), this->data_[2][2] / cos(x1));
374 Real y2 =
375 atan2(this->data_[1][2] / cos(x2), this->data_[2][2] / cos(x2));
376
377 Real z1 =
378 atan2(this->data_[0][1] / cos(x1), this->data_[0][0] / cos(x1));
379 Real z2 =
380 atan2(this->data_[0][1] / cos(x2), this->data_[0][0] / cos(x2));
381
382 // choose one solution to return
383 // for example the "shortest" rotation
384 if ((std::abs(x1) + std::abs(y1) + std::abs(z1)) <=
385 (std::abs(x2) + std::abs(y2) + std::abs(z2))) {
386 return Vector3<Real>(x1, y1, z1);
387 } else {
388 return Vector3<Real>(x2, y2, z2);
389 }
390 }
391 }
392
393 Vector<Real, 6> toVoigtTensor() {
394 Vector<Real, 6> voigt;
395 voigt[0] = this->data_[0][0];
396 voigt[1] = this->data_[1][1];
397 voigt[2] = this->data_[2][2];
398 voigt[3] = 0.5 * (this->data_[1][2] + this->data_[2][1]);
399 voigt[4] = 0.5 * (this->data_[0][2] + this->data_[2][0]);
400 voigt[5] = 0.5 * (this->data_[0][1] + this->data_[1][0]);
401 return voigt;
402 }
403
404 /** Returns the determinant of this matrix. */
405 Real determinant() const {
406 Real x, y, z;
407
408 x = this->data_[0][0] * (this->data_[1][1] * this->data_[2][2] -
409 this->data_[1][2] * this->data_[2][1]);
410 y = this->data_[0][1] * (this->data_[1][2] * this->data_[2][0] -
411 this->data_[1][0] * this->data_[2][2]);
412 z = this->data_[0][2] * (this->data_[1][0] * this->data_[2][1] -
413 this->data_[1][1] * this->data_[2][0]);
414 return (x + y + z);
415 }
416
417 /** Returns the trace of this matrix. */
418 Real trace() const {
419 return this->data_[0][0] + this->data_[1][1] + this->data_[2][2];
420 }
421
422 /**
423 * Sets the value of this matrix to the inverse of itself.
424 * @note since this simple algorithm can be applied to invert a 3 by 3
425 * matrix, we hide the implementation of inverse in SquareMatrix
426 * class
427 */
430 RealType det = determinant();
431 m(0, 0) = this->data_[1][1] * this->data_[2][2] -
432 this->data_[1][2] * this->data_[2][1];
433 m(1, 0) = this->data_[1][2] * this->data_[2][0] -
434 this->data_[1][0] * this->data_[2][2];
435 m(2, 0) = this->data_[1][0] * this->data_[2][1] -
436 this->data_[1][1] * this->data_[2][0];
437 m(0, 1) = this->data_[2][1] * this->data_[0][2] -
438 this->data_[2][2] * this->data_[0][1];
439 m(1, 1) = this->data_[2][2] * this->data_[0][0] -
440 this->data_[2][0] * this->data_[0][2];
441 m(2, 1) = this->data_[2][0] * this->data_[0][1] -
442 this->data_[2][1] * this->data_[0][0];
443 m(0, 2) = this->data_[0][1] * this->data_[1][2] -
444 this->data_[0][2] * this->data_[1][1];
445 m(1, 2) = this->data_[0][2] * this->data_[1][0] -
446 this->data_[0][0] * this->data_[1][2];
447 m(2, 2) = this->data_[0][0] * this->data_[1][1] -
448 this->data_[0][1] * this->data_[1][0];
449 m /= det;
450 return m;
451 }
452
454 SquareMatrix3<Real> result;
455
456 for (unsigned int i = 0; i < 3; i++)
457 for (unsigned int j = 0; j < 3; j++)
458 result(j, i) = this->data_[i][j];
459
460 return result;
461 }
462 /**
463 * Extract the eigenvalues and eigenvectors from a 3x3 matrix.
464 * The eigenvectors (the columns of V) will be normalized.
465 * The eigenvectors are aligned optimally with the x, y, and z
466 * axes respectively.
467 * @param a symmetric matrix whose eigenvectors are to be computed. On
468 * return, the matrix is overwritten
469 * @param w will contain the eigenvalues of the matrix On return of this
470 * function
471 * @param v the columns of this matrix will contain the eigenvectors. The
472 * eigenvectors are normalized and mutually orthogonal.
473 * @warning a will be overwritten
474 */
477 };
478 /*=========================================================================
479
480 Program: Visualization Toolkit
481 Module: $RCSfile: SquareMatrix3.hpp,v $
482
483 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
484 All rights reserved.
485 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
486
487 This software is distributed WITHOUT ANY WARRANTY; without even
488 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
489 PURPOSE. See the above copyright notice for more information.
490
491 =========================================================================*/
492 template<typename Real>
494 Vector3<Real>& w,
496 int i, j, k, maxI;
497 Real tmp, maxVal;
498 Vector3<Real> v_maxI, v_k, v_j;
499
500 // diagonalize using Jacobi
502 // if all the eigenvalues are the same, return identity matrix
503 if (w[0] == w[1] && w[0] == w[2]) {
505 return;
506 }
507
508 // transpose temporarily, it makes it easier to sort the eigenvectors
509 v = v.transpose();
510
511 // if two eigenvalues are the same, re-orthogonalize to optimally line
512 // up the eigenvectors with the x, y, and z axes
513 for (i = 0; i < 3; i++) {
514 if (w((i + 1) % 3) == w((i + 2) % 3)) { // two eigenvalues are the same
515 // find maximum element of the independant eigenvector
516 maxVal = fabs(v(i, 0));
517 maxI = 0;
518 for (j = 1; j < 3; j++) {
519 if (maxVal < (tmp = fabs(v(i, j)))) {
520 maxVal = tmp;
521 maxI = j;
522 }
523 }
524
525 // swap the eigenvector into its proper position
526 if (maxI != i) {
527 tmp = w(maxI);
528 w(maxI) = w(i);
529 w(i) = tmp;
530
531 v.swapRow(i, maxI);
532 }
533 // maximum element of eigenvector should be positive
534 if (v(maxI, maxI) < 0) {
535 v(maxI, 0) = -v(maxI, 0);
536 v(maxI, 1) = -v(maxI, 1);
537 v(maxI, 2) = -v(maxI, 2);
538 }
539
540 // re-orthogonalize the other two eigenvectors
541 j = (maxI + 1) % 3;
542 k = (maxI + 2) % 3;
543
544 v(j, 0) = 0.0;
545 v(j, 1) = 0.0;
546 v(j, 2) = 0.0;
547 v(j, j) = 1.0;
548
549 /** @todo */
550 v_maxI = v.getRow(maxI);
551 v_j = v.getRow(j);
552 v_k = cross(v_maxI, v_j);
553 v_k.normalize();
554 v_j = cross(v_k, v_maxI);
555 v.setRow(j, v_j);
556 v.setRow(k, v_k);
557
558 // transpose vectors back to columns
559 v = v.transpose();
560 return;
561 }
562 }
563
564 // the three eigenvalues are different, just sort the eigenvectors
565 // to align them with the x, y, and z axes
566
567 // find the vector with the largest x element, make that vector
568 // the first vector
569 maxVal = fabs(v(0, 0));
570 maxI = 0;
571 for (i = 1; i < 3; i++) {
572 if (maxVal < (tmp = fabs(v(i, 0)))) {
573 maxVal = tmp;
574 maxI = i;
575 }
576 }
577
578 // swap eigenvalue and eigenvector
579 if (maxI != 0) {
580 tmp = w(maxI);
581 w(maxI) = w(0);
582 w(0) = tmp;
583 v.swapRow(maxI, 0);
584 }
585 // do the same for the y element
586 if (fabs(v(1, 1)) < fabs(v(2, 1))) {
587 tmp = w(2);
588 w(2) = w(1);
589 w(1) = tmp;
590 v.swapRow(2, 1);
591 }
592
593 // ensure that the sign of the eigenvectors is correct
594 for (i = 0; i < 2; i++) {
595 if (v(i, i) < 0) {
596 v(i, 0) = -v(i, 0);
597 v(i, 1) = -v(i, 1);
598 v(i, 2) = -v(i, 2);
599 }
600 }
601
602 // set sign of final eigenvector to ensure that determinant is positive
603 if (v.determinant() < 0) {
604 v(2, 0) = -v(2, 0);
605 v(2, 1) = -v(2, 1);
606 v(2, 2) = -v(2, 2);
607 }
608
609 // transpose the eigenvectors back again
610 v = v.transpose();
611 return;
612 }
613
614 /**
615 * Return the multiplication of two matrixes (m1 * m2).
616 * @return the multiplication of two matrixes
617 * @param m1 the first matrix
618 * @param m2 the second matrix
619 */
620 template<typename Real>
622 const SquareMatrix3<Real>& m2) {
623 SquareMatrix3<Real> result;
624
625 for (unsigned int i = 0; i < 3; i++)
626 for (unsigned int j = 0; j < 3; j++)
627 for (unsigned int k = 0; k < 3; k++)
628 result(i, j) += m1(i, k) * m2(k, j);
629
630 return result;
631 }
632
633 template<typename Real>
634 inline SquareMatrix3<Real> outProduct(const Vector3<Real>& v1,
635 const Vector3<Real>& v2) {
636 SquareMatrix3<Real> result;
637
638 for (unsigned int i = 0; i < 3; i++) {
639 for (unsigned int j = 0; j < 3; j++) {
640 result(i, j) = v1[i] * v2[j];
641 }
642 }
643
644 return result;
645 }
646
647 using Mat3x3d = SquareMatrix3<RealType>;
648 using RotMat3x3d = SquareMatrix3<RealType>;
649
650 const Mat3x3d M3Zero(0.0);
651} // namespace OpenMD
652
653#endif // MATH_SQUAREMATRIX3_HPP
Quaternion is a sort of a higher-level complex number.
Real x() const
Returns the value of the first element of this quaternion.
Real z() const
Returns the value of the fourth element of this quaternion.
SquareMatrix< Real, 3 > toRotationMatrix3()
Returns the corresponding rotation matrix (3x3).
Real w() const
Returns the value of the first element of this quaternion.
Real y() const
Returns the value of the thirf element of this quaternion.
rectangular matrix class
Vector< Real, Row > getRow(unsigned int row)
Returns a row of this matrix as a vector.
void setRow(unsigned int row, const Vector< Real, Row > &v)
Sets a row of this matrix.
void swapRow(unsigned int i, unsigned int j)
swap two rows of this matrix
RectMatrix< Real, Row, Col > & operator=(const RectMatrix< Real, Row, Col > &m)
copy assignment operator
static void diagonalize(SquareMatrix3< Real > &a, Vector3< Real > &w, SquareMatrix3< Real > &v)
Extract the eigenvalues and eigenvectors from a 3x3 matrix.
SquareMatrix3(const RectMatrix< Real, 3, 3 > &m)
Construct from a RectMatrix (e.g.
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
SquareMatrix3(Real s)
Constructs and initializes every element of this matrix to a scalar.
Real determinant() const
Returns the determinant of this matrix.
SquareMatrix3()
default constructor
void axisAngle(Vector3d axis, RealType angle)
Uses Rodrigues' rotation formula for a rotation matrix.
void setupRotMat(const Quaternion< Real > &quat)
Sets this matrix to a rotation matrix by quaternion.
SquareMatrix3(Real *array)
Constructs and initializes from an array.
SquareMatrix3< Real > & operator=(const RectMatrix< Real, 3, 3 > &m)
copy assignment operator
Real trace() const
Returns the trace of this matrix.
Quaternion< Real > toQuaternion()
Returns the quaternion from this rotation matrix.
void setupUpperTriangularVoigtTensor(Vector< Real, 6 > vt)
Sets this matrix to an upper-triangular (asymmetric) tensor using Voigt Notation.
void setupRotMat(const Vector3< Real > &eulerAngles)
Sets this matrix to a rotation matrix by three euler angles @ param euler.
SquareMatrix3(const SquareMatrix< Real, 3 > &m)
copy constructor
Vector3< Real > toEulerAngles()
Returns the euler angles from this rotation matrix.
void setupRotMat(Real w, Real x, Real y, Real z)
Sets this matrix to a rotation matrix by quaternion.
void setupRotMat(Real phi, Real theta, Real psi)
Sets this matrix to a rotation matrix by three euler angles.
void setupVoigtTensor(Vector< Real, 6 > vt)
Sets this matrix to a symmetric tensor using Voigt Notation.
static SquareMatrix< Real, Dim > identity()
SquareMatrix< Real, Dim > transpose() const
static int jacobi(SquareMatrix< Real, Dim > &a, Vector< Real, Dim > &d, SquareMatrix< Real, Dim > &v)
Fix length vector class.
Definition Vector.hpp:81
void normalize()
Normalizes this vector in place.
Definition Vector.hpp:406
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Definition Vector3.hpp:139
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).