00001 #ifndef COLVARTYPES_H
00002 #define COLVARTYPES_H
00003
00004 #ifndef PI
00005 #define PI 3.14159265358979323846
00006 #endif
00007
00008
00011
00012
00013
00015 class colvarmodule::rvector {
00016
00017 public:
00018
00019 cvm::real x, y, z;
00020
00021 inline rvector()
00022 : x (0.0), y (0.0), z (0.0)
00023 {}
00024
00025 inline rvector (cvm::real const &x_i,
00026 cvm::real const &y_i,
00027 cvm::real const &z_i)
00028 : x (x_i), y (y_i), z (z_i)
00029 {}
00030
00031 inline rvector (cvm::real v)
00032 : x (v), y (v), z (v)
00033 {}
00034
00036 inline void set (cvm::real const value = 0.0) {
00037 x = y = z = value;
00038 }
00039
00041 inline void reset() {
00042 x = y = z = 0.0;
00043 }
00044
00046 inline cvm::real & operator [] (int const &i) {
00047 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
00048 }
00049
00051 inline cvm::real const & operator [] (int const &i) const {
00052 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
00053 }
00054
00055
00056 inline cvm::rvector & operator = (cvm::real const &v)
00057 {
00058 x = v;
00059 y = v;
00060 z = v;
00061 return *this;
00062 }
00063
00064 inline void operator += (cvm::rvector const &v)
00065 {
00066 x += v.x;
00067 y += v.y;
00068 z += v.z;
00069 }
00070
00071 inline void operator -= (cvm::rvector const &v)
00072 {
00073 x -= v.x;
00074 y -= v.y;
00075 z -= v.z;
00076 }
00077
00078 inline void operator *= (cvm::real const &v)
00079 {
00080 x *= v;
00081 y *= v;
00082 z *= v;
00083 }
00084
00085 inline void operator /= (cvm::real const& v)
00086 {
00087 x /= v;
00088 y /= v;
00089 z /= v;
00090 }
00091
00092 inline cvm::real norm2() const
00093 {
00094 return (x*x + y*y + z*z);
00095 }
00096
00097 inline cvm::real norm() const
00098 {
00099 return ::sqrt (this->norm2());
00100 }
00101
00102 inline cvm::rvector unit() const
00103 {
00104 return cvm::rvector (x, y, z)/this->norm();
00105 }
00106
00107 static inline size_t output_width (size_t const &real_width)
00108 {
00109 return 3*real_width + 10;
00110 }
00111
00112
00113 static inline cvm::rvector outer (cvm::rvector const &v1, cvm::rvector const &v2)
00114 {
00115 return cvm::rvector ( v1.y*v2.z - v2.y*v1.z,
00116 -v1.x*v2.z + v2.x*v1.z,
00117 v1.x*v2.y - v2.x*v1.y);
00118 }
00119
00120 friend inline cvm::rvector operator - (cvm::rvector const &v)
00121 {
00122 return cvm::rvector (-v.x, -v.y, -v.z);
00123 }
00124
00125 friend inline int operator == (cvm::rvector const &v1, cvm::rvector const &v2)
00126 {
00127 return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
00128 }
00129
00130 friend inline int operator != (cvm::rvector const &v1, cvm::rvector const &v2)
00131 {
00132 return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z);
00133 }
00134
00135 friend inline cvm::rvector operator + (cvm::rvector const &v1, cvm::rvector const &v2)
00136 {
00137 return cvm::rvector (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
00138 }
00139 friend inline cvm::rvector operator - (cvm::rvector const &v1, cvm::rvector const &v2)
00140 {
00141 return cvm::rvector (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
00142 }
00143
00144 friend inline cvm::real operator * (cvm::rvector const &v1, cvm::rvector const &v2)
00145 {
00146 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
00147 }
00148
00149 friend inline cvm::rvector operator * (cvm::real const &a, cvm::rvector const &v)
00150 {
00151 return cvm::rvector (a*v.x, a*v.y, a*v.z);
00152 }
00153
00154 friend inline cvm::rvector operator * (cvm::rvector const &v, cvm::real const &a)
00155 {
00156 return cvm::rvector (a*v.x, a*v.y, a*v.z);
00157 }
00158
00159 friend inline cvm::rvector operator / (cvm::rvector const &v, cvm::real const &a)
00160 {
00161 return cvm::rvector (v.x/a, v.y/a, v.z/a);
00162 }
00163
00164
00165 };
00166
00167
00168
00172 template <class T, size_t const length> class colvarmodule::vector1d
00173 {
00174 protected:
00175
00177 T *array;
00178
00179 public:
00180
00182 inline size_t size()
00183 {
00184 return length;
00185 }
00186
00188 inline vector1d (T const &t = T())
00189 {
00190 array = new T[length];
00191 reset();
00192 }
00193
00195 inline void reset()
00196 {
00197 for (size_t i = 0; i < length; i++) {
00198 array[i] = T (0.0);
00199 }
00200 }
00201
00203 inline vector1d (T const *v)
00204 {
00205 array = new T[length];
00206 for (size_t i = 0; i < length; i++) {
00207 array[i] = v[i];
00208 }
00209 }
00210
00212 inline vector1d (vector1d<T, length> const &v)
00213 {
00214 array = new T[length];
00215 for (size_t i = 0; i < length; i++) {
00216 array[i] = v.array[i];
00217 }
00218 }
00219
00221 inline vector1d<T, length> & operator = (vector1d<T, length> const &v)
00222 {
00223 for (size_t i = 0; i < length; i++) {
00224 this->array[i] = v.array[i];
00225 }
00226 return *this;
00227 }
00228
00230 inline ~vector1d() {
00231 delete [] array;
00232 }
00233
00235 inline T *c_array() { return array; }
00236
00238 inline operator T *() { return array; }
00239
00241 inline friend T operator * (vector1d<T, length> const &v1,
00242 vector1d<T, length> const &v2)
00243 {
00244 T prod (0.0);
00245 for (size_t i = 0; i < length; i++) {
00246 prod += v1.array[i] * v2.array[i];
00247 }
00248 return prod;
00249 }
00250
00252 friend std::ostream & operator << (std::ostream &os,
00253 vector1d<T, length> const &v)
00254 {
00255 std::streamsize const w = os.width();
00256 std::streamsize const p = os.precision();
00257
00258 os << "( ";
00259 for (size_t i = 0; i < length-1; i++) {
00260 os.width (w); os.precision (p);
00261 os << v.array[i] << " , ";
00262 }
00263 os.width (w); os.precision (p);
00264 os << v.array[length-1] << " )";
00265 return os;
00266 }
00267
00268 };
00269
00270
00271
00275 template <class T,
00276 size_t const outer_length,
00277 size_t const inner_length> class colvarmodule::matrix2d
00278 {
00279 protected:
00280
00282 T **array;
00283
00284 public:
00285
00287 inline void alloc() {
00288 array = new T * [outer_length];
00289 for (size_t i = 0; i < outer_length; i++) {
00290 array[i] = new T [inner_length];
00291 }
00292 }
00293
00295 inline void reset()
00296 {
00297 for (size_t i = 0; i < outer_length; i++) {
00298 for (size_t j = 0; j < inner_length; j++) {
00299 array[i][j] = T (0.0);
00300 }
00301 }
00302 }
00303
00305 inline matrix2d()
00306 {
00307 this->alloc();
00308 reset();
00309 }
00310
00312 inline matrix2d (T const **m)
00313 {
00314 this->alloc();
00315 for (size_t i = 0; i < outer_length; i++) {
00316 for (size_t j = 0; j < inner_length; j++)
00317 array[i][j] = m[i][j];
00318 }
00319 }
00320
00322 inline matrix2d (matrix2d<T, outer_length, inner_length> const &m)
00323 {
00324 this->alloc();
00325 for (size_t i = 0; i < outer_length; i++) {
00326 for (size_t j = 0; j < inner_length; j++)
00327 this->array[i][j] = m.array[i][j];
00328 }
00329 }
00330
00332 inline matrix2d<T, outer_length, inner_length> &
00333 operator = (matrix2d<T, outer_length, inner_length> const &m)
00334 {
00335 for (size_t i = 0; i < outer_length; i++) {
00336 for (size_t j = 0; j < inner_length; j++)
00337 this->array[i][j] = m.array[i][j];
00338 }
00339 return *this;
00340 }
00341
00343 inline ~matrix2d() {
00344 for (size_t i = 0; i < outer_length; i++) {
00345 delete [] array[i];
00346 }
00347 delete [] array;
00348 }
00349
00351 inline T **c_array() { return array; }
00352
00354 inline operator T **() { return array; }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00381 friend std::ostream & operator << (std::ostream &os,
00382 matrix2d<T, outer_length, inner_length> const &m)
00383 {
00384 std::streamsize const w = os.width();
00385 std::streamsize const p = os.precision();
00386
00387 os << "(";
00388 for (size_t i = 0; i < outer_length; i++) {
00389 os << " ( ";
00390 for (size_t j = 0; j < inner_length-1; j++) {
00391 os.width (w);
00392 os.precision (p);
00393 os << m.array[i][j] << " , ";
00394 }
00395 os.width (w);
00396 os.precision (p);
00397 os << m.array[i][inner_length-1] << " )";
00398 }
00399
00400 os << " )";
00401 return os;
00402 }
00403
00404 };
00405
00406
00409 class colvarmodule::rmatrix
00410 : public colvarmodule::matrix2d<colvarmodule::real, 3, 3> {
00411 private:
00412
00413 public:
00414
00416 inline cvm::real & xx() { return array[0][0]; }
00418 inline cvm::real & xy() { return array[0][1]; }
00420 inline cvm::real & xz() { return array[0][2]; }
00422 inline cvm::real & yx() { return array[1][0]; }
00424 inline cvm::real & yy() { return array[1][1]; }
00426 inline cvm::real & yz() { return array[1][2]; }
00428 inline cvm::real & zx() { return array[2][0]; }
00430 inline cvm::real & zy() { return array[2][1]; }
00432 inline cvm::real & zz() { return array[2][2]; }
00433
00435 inline cvm::real xx() const { return array[0][0]; }
00437 inline cvm::real xy() const { return array[0][1]; }
00439 inline cvm::real xz() const { return array[0][2]; }
00441 inline cvm::real yx() const { return array[1][0]; }
00443 inline cvm::real yy() const { return array[1][1]; }
00445 inline cvm::real yz() const { return array[1][2]; }
00447 inline cvm::real zx() const { return array[2][0]; }
00449 inline cvm::real zy() const { return array[2][1]; }
00451 inline cvm::real zz() const { return array[2][2]; }
00452
00454 inline rmatrix (cvm::real const **m)
00455 : cvm::matrix2d<cvm::real, 3, 3> (m)
00456 {}
00457
00459 inline rmatrix()
00460 : cvm::matrix2d<cvm::real, 3, 3>()
00461 {}
00462
00464 inline rmatrix (cvm::real const &xxi,
00465 cvm::real const &xyi,
00466 cvm::real const &xzi,
00467 cvm::real const &yxi,
00468 cvm::real const &yyi,
00469 cvm::real const &yzi,
00470 cvm::real const &zxi,
00471 cvm::real const &zyi,
00472 cvm::real const &zzi)
00473 : cvm::matrix2d<cvm::real, 3, 3>()
00474 {
00475 this->xx() = xxi;
00476 this->xy() = xyi;
00477 this->xz() = xzi;
00478 this->yx() = yxi;
00479 this->yy() = yyi;
00480 this->yz() = yzi;
00481 this->zx() = zxi;
00482 this->zy() = xyi;
00483 this->zz() = zzi;
00484 }
00485
00487 inline ~rmatrix()
00488 {}
00489
00491 inline cvm::real determinant() const
00492 {
00493 return
00494 ( xx() * (yy()*zz() - zy()*yz()))
00495 - (yx() * (xy()*zz() - zy()*xz()))
00496 + (zx() * (xy()*yz() - yy()*xz()));
00497 }
00498
00499 inline cvm::rmatrix transpose() const
00500 {
00501 return cvm::rmatrix (this->xx(),
00502 this->yx(),
00503 this->zx(),
00504 this->xy(),
00505 this->yy(),
00506 this->zy(),
00507 this->xz(),
00508 this->yz(),
00509 this->zz());
00510 }
00511
00512 friend cvm::rvector operator * (cvm::rmatrix const &m, cvm::rvector const &r);
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 };
00527
00528
00529 inline cvm::rvector operator * (cvm::rmatrix const &m,
00530 cvm::rvector const &r)
00531 {
00532 return cvm::rvector (m.xx()*r.x + m.xy()*r.y + m.xz()*r.z,
00533 m.yx()*r.x + m.yy()*r.y + m.yz()*r.z,
00534 m.zx()*r.x + m.zy()*r.y + m.zz()*r.z);
00535 }
00536
00537
00539 void jacobi (cvm::real **a, int n, cvm::real d[], cvm::real **v, int *nrot);
00540
00542 void eigsrt (cvm::real d[], cvm::real **v, int n);
00543
00545 void transpose (cvm::real **v, int n);
00546
00547
00548
00549
00552 class colvarmodule::quaternion {
00553
00554 public:
00555
00556 cvm::real q0, q1, q2, q3;
00557
00559 inline quaternion (cvm::real const &x, cvm::real const &y, cvm::real const &z)
00560 : q0 (0.0), q1 (x), q2 (y), q3 (z)
00561 {}
00562
00564 inline quaternion (cvm::real const qv[4])
00565 : q0 (qv[0]), q1 (qv[1]), q2 (qv[2]), q3 (qv[3])
00566 {}
00567
00569 inline quaternion (cvm::real const &q0i,
00570 cvm::real const &q1i,
00571 cvm::real const &q2i,
00572 cvm::real const &q3i)
00573 : q0 (q0i), q1 (q1i), q2 (q2i), q3 (q3i)
00574 {}
00575
00579 inline void set_from_euler_angles (cvm::real const &phi_in,
00580 cvm::real const &theta_in,
00581 cvm::real const &psi_in)
00582 {
00583 q0 = ( (::cos (phi_in/2.0)) * (::cos (theta_in/2.0)) * (::cos (psi_in/2.0)) +
00584 (::sin (phi_in/2.0)) * (::sin (theta_in/2.0)) * (::sin (psi_in/2.0)) );
00585
00586 q1 = ( (::sin (phi_in/2.0)) * (::cos (theta_in/2.0)) * (::cos (psi_in/2.0)) -
00587 (::cos (phi_in/2.0)) * (::sin (theta_in/2.0)) * (::sin (psi_in/2.0)) );
00588
00589 q2 = ( (::cos (phi_in/2.0)) * (::sin (theta_in/2.0)) * (::cos (psi_in/2.0)) +
00590 (::sin (phi_in/2.0)) * (::cos (theta_in/2.0)) * (::sin (psi_in/2.0)) );
00591
00592 q3 = ( (::cos (phi_in/2.0)) * (::cos (theta_in/2.0)) * (::sin (psi_in/2.0)) -
00593 (::sin (phi_in/2.0)) * (::sin (theta_in/2.0)) * (::cos (psi_in/2.0)) );
00594 }
00595
00597 inline quaternion()
00598 {
00599 reset();
00600 }
00601
00603 inline void set (cvm::real const value = 0.0)
00604 {
00605 q0 = q1 = q2 = q3 = value;
00606 }
00607
00609 inline void reset()
00610 {
00611 q0 = q1 = q2 = q3 = 0.0;
00612 }
00613
00616 inline void reset_rotation()
00617 {
00618 q0 = 1.0;
00619 q1 = q2 = q3 = 0.0;
00620 }
00621
00623 static inline size_t output_width (size_t const &real_width)
00624 {
00625 return 4*real_width + 13;
00626 }
00627
00629 friend std::ostream & operator << (std::ostream &os, cvm::quaternion const &q);
00631 friend std::istream & operator >> (std::istream &is, cvm::quaternion &q);
00632
00634 inline cvm::real & operator [] (int const &i) {
00635 switch (i) {
00636 case 0:
00637 return this->q0;
00638 case 1:
00639 return this->q1;
00640 case 2:
00641 return this->q2;
00642 case 3:
00643 return this->q3;
00644 default:
00645 cvm::fatal_error ("Error: incorrect quaternion component.\n");
00646 return q0;
00647 }
00648 }
00649
00651 inline cvm::real operator [] (int const &i) const {
00652 switch (i) {
00653 case 0:
00654 return this->q0;
00655 case 1:
00656 return this->q1;
00657 case 2:
00658 return this->q2;
00659 case 3:
00660 return this->q3;
00661 default:
00662 cvm::fatal_error ("Error: trying to access a quaternion "
00663 "component which is not between 0 and 3.\n");
00664 return this->q0;
00665 }
00666 }
00667
00669 inline cvm::real norm2() const
00670 {
00671 return q0*q0 + q1*q1 + q2*q2 + q3*q3;
00672 }
00673
00675 inline cvm::real norm() const
00676 {
00677 return ::sqrt (this->norm2());
00678 }
00679
00681 inline cvm::quaternion conjugate() const
00682 {
00683 return cvm::quaternion (q0, -q1, -q2, -q3);
00684 }
00685
00686 inline void operator *= (cvm::real const &a)
00687 {
00688 q0 *= a; q1 *= a; q2 *= a; q3 *= a;
00689 }
00690
00691 inline void operator /= (cvm::real const &a)
00692 {
00693 q0 /= a; q1 /= a; q2 /= a; q3 /= a;
00694 }
00695
00696 inline void set_positive()
00697 {
00698 if (q0 > 0.0) return;
00699 q0 = -q0;
00700 q1 = -q1;
00701 q2 = -q2;
00702 q3 = -q3;
00703 }
00704
00705 inline void operator += (cvm::quaternion const &h)
00706 {
00707 q0+=h.q0; q1+=h.q1; q2+=h.q2; q3+=h.q3;
00708 }
00709 inline void operator -= (cvm::quaternion const &h)
00710 {
00711 q0-=h.q0; q1-=h.q1; q2-=h.q2; q3-=h.q3;
00712 }
00713
00715 static inline cvm::quaternion promote (cvm::rvector const &v)
00716 {
00717 return cvm::quaternion (0.0, v.x, v.y, v.z);
00718 }
00720 inline cvm::rvector get_vector() const
00721 {
00722 return cvm::rvector (q1, q2, q3);
00723 }
00724
00725
00726 friend inline cvm::quaternion operator + (cvm::quaternion const &h, cvm::quaternion const &q)
00727 {
00728 return cvm::quaternion (h.q0+q.q0, h.q1+q.q1, h.q2+q.q2, h.q3+q.q3);
00729 }
00730
00731 friend inline cvm::quaternion operator - (cvm::quaternion const &h, cvm::quaternion const &q)
00732 {
00733 return cvm::quaternion (h.q0-q.q0, h.q1-q.q1, h.q2-q.q2, h.q3-q.q3);
00734 }
00735
00738 friend inline cvm::quaternion operator * (cvm::quaternion const &h, cvm::quaternion const &q)
00739 {
00740 return cvm::quaternion (h.q0*q.q0 - h.q1*q.q1 - h.q2*q.q2 - h.q3*q.q3,
00741 h.q0*q.q1 + h.q1*q.q0 + h.q2*q.q3 - h.q3*q.q2,
00742 h.q0*q.q2 + h.q2*q.q0 + h.q3*q.q1 - h.q1*q.q3,
00743 h.q0*q.q3 + h.q3*q.q0 + h.q1*q.q2 - h.q2*q.q1);
00744 }
00745
00746 friend inline cvm::quaternion operator * (cvm::real const &c,
00747 cvm::quaternion const &q)
00748 {
00749 return cvm::quaternion (c*q.q0, c*q.q1, c*q.q2, c*q.q3);
00750 }
00751 friend inline cvm::quaternion operator * (cvm::quaternion const &q,
00752 cvm::real const &c)
00753 {
00754 return cvm::quaternion (q.q0*c, q.q1*c, q.q2*c, q.q3*c);
00755 }
00756 friend inline cvm::quaternion operator / (cvm::quaternion const &q,
00757 cvm::real const &c)
00758 {
00759 return cvm::quaternion (q.q0/c, q.q1/c, q.q2/c, q.q3/c);
00760 }
00761
00762
00765 inline cvm::rvector rotate (cvm::rvector const &v) const
00766 {
00767 return ((*this) * promote (v) * ((*this).conjugate())).get_vector();
00768 }
00769
00772 inline cvm::quaternion rotate (cvm::quaternion const &Q2) const
00773 {
00774 cvm::rvector const vq_rot = this->rotate (Q2.get_vector());
00775 return cvm::quaternion (Q2.q0, vq_rot.x, vq_rot.y, vq_rot.z);
00776 }
00777
00779 inline cvm::rmatrix rotation_matrix() const
00780 {
00781 cvm::rmatrix R;
00782
00783 R.xx() = q0*q0 + q1*q1 - q2*q2 - q3*q3;
00784 R.yy() = q0*q0 - q1*q1 + q2*q2 - q3*q3;
00785 R.zz() = q0*q0 - q1*q1 - q2*q2 + q3*q3;
00786
00787 R.xy() = 2.0 * (q1*q2 - q0*q3);
00788 R.xz() = 2.0 * (q0*q2 + q1*q3);
00789
00790 R.yx() = 2.0 * (q0*q3 + q1*q2);
00791 R.yz() = 2.0 * (q2*q3 - q0*q1);
00792
00793 R.zx() = 2.0 * (q1*q3 - q0*q2);
00794 R.zy() = 2.0 * (q0*q1 + q2*q3);
00795
00796 return R;
00797 }
00798
00799
00802 inline cvm::real cos2 (cvm::quaternion const &q) const
00803 {
00804
00805 cvm::rvector const op = (cvm::rvector::outer (this->get_vector(), q.get_vector()));
00806 cvm::real const opl2 = op.norm2();
00807
00808 return ( (opl2 > 0.0) ?
00809 ((this->rotate (op)) * (q.rotate (op))) / opl2 :
00810 1.0 );
00811 }
00812
00813
00817 inline cvm::real dist2 (cvm::quaternion const &Q2) const
00818 {
00819 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
00820 this->q2*Q2.q2 + this->q3*Q2.q3;
00821
00822 cvm::real const omega = ::acos ( (cos_omega > 1.0) ? 1.0 :
00823 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
00824
00825
00826 if (cos_omega > 0.0)
00827 return omega * omega;
00828 else
00829 return (PI-omega) * (PI-omega);
00830 }
00831
00834 inline cvm::quaternion dist2_grad (cvm::quaternion const &Q2) const
00835 {
00836 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
00837 cvm::real const omega = ::acos ( (cos_omega > 1.0) ? 1.0 :
00838 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
00839 cvm::real const sin_omega = ::sin (omega);
00840
00841 if (::fabs (sin_omega) < 1.0E-14) {
00842
00843 return cvm::quaternion (0.0, 0.0, 0.0, 0.0);
00844 }
00845
00846 cvm::quaternion const
00847 grad1 ((-1.0)*sin_omega*Q2.q0 + cos_omega*(this->q0-cos_omega*Q2.q0)/sin_omega,
00848 (-1.0)*sin_omega*Q2.q1 + cos_omega*(this->q1-cos_omega*Q2.q1)/sin_omega,
00849 (-1.0)*sin_omega*Q2.q2 + cos_omega*(this->q2-cos_omega*Q2.q2)/sin_omega,
00850 (-1.0)*sin_omega*Q2.q3 + cos_omega*(this->q3-cos_omega*Q2.q3)/sin_omega);
00851
00852 if (cos_omega > 0.0) {
00853 return 2.0*omega*grad1;
00854 }
00855 else {
00856 return -2.0*(PI-omega)*grad1;
00857 }
00858 }
00859
00862 inline void match (cvm::quaternion &Q2) const
00863 {
00864 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
00865 this->q2*Q2.q2 + this->q3*Q2.q3;
00866 if (cos_omega < 0.0) Q2 *= -1.0;
00867 }
00868
00871 inline cvm::real inner (cvm::quaternion const &Q2) const
00872 {
00873 cvm::real const prod = this->q0*Q2.q0 + this->q1*Q2.q1 +
00874 this->q2*Q2.q2 + this->q3*Q2.q3;
00875 return prod;
00876 }
00877
00878
00879 };
00880
00881
00884 class colvarmodule::rotation
00885 {
00886 public:
00887
00889 cvm::quaternion q;
00890
00892 cvm::real lambda;
00893
00895 bool b_debug_gradients;
00896
00899 std::vector< cvm::atom_pos > pos1, pos2;
00900
00902 std::vector< cvm::matrix2d<cvm::rvector, 4, 4> > dS_1, dS_2;
00904 std::vector< cvm::rvector > dL0_1, dL0_2;
00906 std::vector< cvm::vector1d<cvm::rvector, 4> > dQ0_1, dQ0_2;
00907
00909 inline void request_group1_gradients (size_t const &n)
00910 {
00911 dS_1.resize (n, cvm::matrix2d<cvm::rvector, 4, 4>());
00912 dL0_1.resize (n, cvm::rvector (0.0, 0.0, 0.0));
00913 dQ0_1.resize (n, cvm::vector1d<cvm::rvector, 4>());
00914 }
00915
00916 inline void request_group2_gradients (size_t const &n)
00917 {
00918 dS_2.resize (n, cvm::matrix2d<cvm::rvector, 4, 4>());
00919 dL0_2.resize (n, cvm::rvector (0.0, 0.0, 0.0));
00920 dQ0_2.resize (n, cvm::vector1d<cvm::rvector, 4>());
00921 }
00922
00933 void calc_optimal_rotation (std::vector<atom_pos> const &pos1,
00934 std::vector<atom_pos> const &pos2);
00935
00937 inline rotation()
00938 : b_debug_gradients (false)
00939 {}
00940
00942 inline rotation (cvm::quaternion const &qi)
00943 : b_debug_gradients (false)
00944 {
00945 q = qi;
00946 }
00947
00949 inline rotation (cvm::real const &angle, cvm::rvector const &axis)
00950 : b_debug_gradients (false)
00951 {
00952 cvm::rvector const axis_n = axis.unit();
00953 cvm::real const sina = ::sin (angle/2.0);
00954 q = cvm::quaternion (::cos (angle/2.0),
00955 sina * axis_n.x, sina * axis_n.y, sina * axis_n.z);
00956 }
00957
00959 inline ~rotation()
00960 {}
00961
00963 inline cvm::rvector rotate (cvm::rvector const &v) const
00964 {
00965 return q.rotate (v);
00966 }
00967
00969 inline cvm::rotation inverse() const
00970 {
00971 return cvm::rotation (this->q.conjugate());
00972 }
00973
00975 inline cvm::rmatrix matrix() const
00976 {
00977 return q.rotation_matrix();
00978 }
00979
00981 static cvm::real crossing_threshold;
00982
00983 protected:
00984
00988 cvm::quaternion q_old;
00989
00991 void build_matrix (std::vector<cvm::atom_pos> const &pos1,
00992 std::vector<cvm::atom_pos> const &pos2,
00993 cvm::matrix2d<real, 4, 4> &S);
00994
00996 void diagonalize_matrix (cvm::matrix2d<cvm::real, 4, 4> &S,
00997 cvm::real S_eigval[4],
00998 cvm::matrix2d<cvm::real, 4, 4> &S_eigvec);
00999 };
01000
01001
01002 #endif
01003
01004
01005
01006
01007