Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

colvartypes.h

Go to the documentation of this file.
00001 #ifndef COLVARTYPES_H
00002 #define COLVARTYPES_H
00003 
00004 #include <cmath>
00005 
00006 #ifndef PI
00007 #define PI 3.14159265358979323846
00008 #endif
00009 
00010 // ----------------------------------------------------------------------
00013 // ----------------------------------------------------------------------
00014 
00015 
00017 class colvarmodule::rvector {
00018 
00019 public:
00020 
00021   cvm::real x, y, z;
00022      
00023   inline rvector()
00024     : x (0.0), y (0.0), z (0.0)
00025   {}
00026 
00027   inline rvector (cvm::real const &x_i,
00028                   cvm::real const &y_i,
00029                   cvm::real const &z_i)
00030     : x (x_i), y (y_i), z (z_i)
00031   {}
00032 
00033   inline rvector (cvm::real v)
00034     : x (v), y (v), z (v)
00035   {}
00036 
00038   inline void set (cvm::real const value = 0.0) {
00039     x = y = z = value;
00040   }
00041 
00043   inline void reset() {
00044     x = y = z = 0.0;
00045   }
00046 
00048   inline cvm::real & operator [] (int const &i) {
00049     return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
00050   }
00051 
00053   inline cvm::real const & operator [] (int const &i) const {
00054     return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
00055   }
00056 
00057 
00058   inline cvm::rvector & operator = (cvm::real const &v) 
00059   {
00060     x = v;
00061     y = v;
00062     z = v;
00063     return *this;
00064   }
00065 
00066   inline void operator += (cvm::rvector const &v) 
00067   {
00068     x += v.x;
00069     y += v.y;
00070     z += v.z;
00071   }
00072 
00073   inline void operator -= (cvm::rvector const &v) 
00074   {
00075     x -= v.x;
00076     y -= v.y;
00077     z -= v.z;
00078   }
00079 
00080   inline void operator *= (cvm::real const &v) 
00081   {
00082     x *= v;
00083     y *= v;
00084     z *= v;
00085   }
00086 
00087   inline void operator /= (cvm::real const& v) 
00088   {
00089     x /= v;
00090     y /= v;
00091     z /= v;
00092   }
00093 
00094   inline cvm::real norm2() const
00095   {
00096     return (x*x + y*y + z*z);
00097   }
00098 
00099   inline cvm::real norm() const
00100   {
00101     return std::sqrt (this->norm2());
00102   }
00103 
00104   inline cvm::rvector unit() const
00105   {
00106     return cvm::rvector (x, y, z)/this->norm();
00107   }
00108 
00109   static inline size_t output_width (size_t const &real_width)
00110   {
00111     return 3*real_width + 10;
00112   }
00113 
00114 
00115   static inline cvm::rvector outer (cvm::rvector const &v1, cvm::rvector const &v2) 
00116   {
00117     return cvm::rvector ( v1.y*v2.z - v2.y*v1.z,
00118                          -v1.x*v2.z + v2.x*v1.z,
00119                           v1.x*v2.y - v2.x*v1.y);
00120   }
00121 
00122   friend inline cvm::rvector operator - (cvm::rvector const &v) 
00123   {
00124     return cvm::rvector (-v.x, -v.y, -v.z);
00125   }
00126 
00127   friend inline int operator == (cvm::rvector const &v1, cvm::rvector const &v2) 
00128   {
00129     return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z);
00130   }
00131 
00132   friend inline int operator != (cvm::rvector const &v1, cvm::rvector const &v2) 
00133   {
00134     return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z);
00135   }
00136 
00137   friend inline cvm::rvector operator + (cvm::rvector const &v1, cvm::rvector const &v2) 
00138   {
00139     return cvm::rvector (v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
00140   }
00141   friend inline cvm::rvector operator - (cvm::rvector const &v1, cvm::rvector const &v2) 
00142   {
00143     return cvm::rvector (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
00144   }
00145 
00146   friend inline cvm::real operator * (cvm::rvector const &v1, cvm::rvector const &v2) 
00147   {
00148     return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
00149   }
00150 
00151   friend inline cvm::rvector operator * (cvm::real const &a, cvm::rvector const &v) 
00152   {
00153     return cvm::rvector (a*v.x, a*v.y, a*v.z);
00154   }
00155 
00156   friend inline cvm::rvector operator * (cvm::rvector const &v, cvm::real const &a) 
00157   {
00158     return cvm::rvector (a*v.x, a*v.y, a*v.z);
00159   }
00160 
00161   friend inline cvm::rvector operator / (cvm::rvector const &v, cvm::real const &a) 
00162   {
00163     return cvm::rvector (v.x/a, v.y/a, v.z/a);
00164   }
00165      
00166 
00167 };
00168 
00169 
00170 
00174 template <class T, size_t const length> class colvarmodule::vector1d
00175 {
00176 protected:
00177 
00179   T *array;
00180 
00181 public:
00182 
00184   inline size_t size()
00185   {
00186     return length;
00187   }
00188  
00190   inline vector1d (T const &t = T())
00191   {
00192     array = new T[length];
00193     reset();
00194   }
00195 
00197   inline void reset()
00198   {
00199     for (size_t i = 0; i < length; i++) {
00200       array[i] = T (0.0);
00201     }
00202   }
00203 
00205   inline vector1d (T const *v)
00206   {
00207     array = new T[length];
00208     for (size_t i = 0; i < length; i++) {
00209       array[i] = v[i];
00210     }
00211   }
00212 
00214   inline vector1d (vector1d<T, length> const &v)
00215   {
00216     array = new T[length];
00217     for (size_t i = 0; i < length; i++) {
00218       array[i] = v.array[i];
00219     }
00220   }
00221 
00223   inline vector1d<T, length> & operator = (vector1d<T, length> const &v)
00224   {
00225     for (size_t i = 0; i < length; i++) {
00226       this->array[i] = v.array[i];
00227     }
00228     return *this;
00229   }
00230 
00232   inline ~vector1d() {
00233     delete [] array;
00234   }
00235 
00237   inline T *c_array() { return array; }
00238 
00240   inline operator T *() { return array; }
00241 
00243   inline friend T operator * (vector1d<T, length> const &v1,
00244                               vector1d<T, length> const &v2)
00245   {
00246     T prod (0.0);
00247     for (size_t i = 0; i < length; i++) {
00248       prod += v1.array[i] * v2.array[i];
00249     }
00250     return prod;
00251   }
00252 
00254   friend std::ostream & operator << (std::ostream &os,
00255                                      vector1d<T, length> const &v)
00256   {
00257     std::streamsize const w = os.width();
00258     std::streamsize const p = os.precision();
00259 
00260     os << "( ";
00261     for (size_t i = 0; i < length-1; i++) {
00262       os.width (w); os.precision (p);
00263       os << v.array[i] << " , ";
00264     }
00265     os.width (w); os.precision (p);
00266     os << v.array[length-1] << " )";
00267     return os;
00268   }
00269 
00270 };
00271 
00272 
00273 
00277 template <class T,
00278           size_t const outer_length,
00279           size_t const inner_length> class colvarmodule::matrix2d
00280 {
00281 protected:
00282 
00284   T **array;
00285 
00286 public:
00287 
00289   inline void alloc() {
00290     array = new T * [outer_length];
00291     for (size_t i = 0; i < outer_length; i++) {
00292       array[i] = new T [inner_length];
00293     }
00294   }
00295 
00297   inline void reset()
00298   {
00299     for (size_t i = 0; i < outer_length; i++) {
00300       for (size_t j = 0; j < inner_length; j++) {
00301         array[i][j] = T (0.0);
00302       }
00303     }
00304   }
00305 
00307   inline matrix2d()
00308   {
00309     this->alloc();
00310     reset();
00311   }
00312  
00314   inline matrix2d (T const **m)
00315   {
00316     this->alloc();
00317     for (size_t i = 0; i < outer_length; i++) {
00318       for (size_t j = 0; j < inner_length; j++)
00319         array[i][j] = m[i][j];
00320     }
00321   }
00322 
00324   inline matrix2d (matrix2d<T, outer_length, inner_length> const &m)
00325   {
00326     this->alloc();
00327     for (size_t i = 0; i < outer_length; i++) {
00328       for (size_t j = 0; j < inner_length; j++)
00329         this->array[i][j] = m.array[i][j];
00330     }
00331   }
00332 
00334   inline matrix2d<T, outer_length, inner_length> &
00335   operator = (matrix2d<T, outer_length, inner_length> const &m)
00336   {
00337     for (size_t i = 0; i < outer_length; i++) {
00338       for (size_t j = 0; j < inner_length; j++)
00339         this->array[i][j] = m.array[i][j];
00340     }
00341     return *this;
00342   }
00343 
00345   inline ~matrix2d() {
00346     for (size_t i = 0; i < outer_length; i++) {
00347       delete [] array[i];
00348     }
00349     delete [] array;
00350   }
00351 
00353   inline T **c_array() { return array; }
00354 
00356   inline operator T **() { return array; }
00357 
00358 //   /// Matrix addi(c)tion
00359 //   inline friend matrix2d<T, outer_length, inner_length>
00360 //   operator + (matrix2d<T, outer_length, inner_length> const &mat1,
00361 //               matrix2d<T, outer_length, inner_length> const &mat2) {
00362 //     matrix2d<T, outer_length, inner_length> sum;
00363 //     for (size_t i = 0; i < outer_length; i++) {
00364 //       for (size_t j = 0; j < inner_length; j++) {
00365 //         sum[i][j] = mat1[i][j] + mat2[i][j];
00366 //       }
00367 //     }
00368 //   }
00369 
00370 //   /// Matrix subtraction
00371 //   inline friend matrix2d<T, outer_length, inner_length>
00372 //   operator - (matrix2d<T, outer_length, inner_length> const &mat1,
00373 //               matrix2d<T, outer_length, inner_length> const &mat2) {
00374 //     matrix2d<T, outer_length, inner_length> sum;
00375 //     for (size_t i = 0; i < outer_length; i++) {
00376 //       for (size_t j = 0; j < inner_length; j++) {
00377 //         sum[i][j] = mat1[i][j] - mat2[i][j];
00378 //       }
00379 //     }
00380 //   }
00381 
00383   friend std::ostream & operator << (std::ostream &os,
00384                                      matrix2d<T, outer_length, inner_length> const &m)
00385   {
00386     std::streamsize const w = os.width();
00387     std::streamsize const p = os.precision();
00388 
00389     os << "(";
00390     for (size_t i = 0; i < outer_length; i++) {
00391       os << " ( ";
00392       for (size_t j = 0; j < inner_length-1; j++) {
00393         os.width (w);
00394         os.precision (p);
00395         os << m.array[i][j] << " , ";
00396       }
00397       os.width (w);
00398       os.precision (p);
00399       os << m.array[i][inner_length-1] << " )";
00400     }
00401 
00402     os << " )";
00403     return os;
00404   }
00405 
00406 };
00407 
00408 
00411 class colvarmodule::rmatrix
00412   : public colvarmodule::matrix2d<colvarmodule::real, 3, 3> {
00413 private:
00414 
00415 public:
00416 
00418   inline cvm::real & xx() { return array[0][0]; }
00420   inline cvm::real & xy() { return array[0][1]; }
00422   inline cvm::real & xz() { return array[0][2]; }
00424   inline cvm::real & yx() { return array[1][0]; }
00426   inline cvm::real & yy() { return array[1][1]; }
00428   inline cvm::real & yz() { return array[1][2]; }
00430   inline cvm::real & zx() { return array[2][0]; }
00432   inline cvm::real & zy() { return array[2][1]; }
00434   inline cvm::real & zz() { return array[2][2]; }
00435 
00437   inline cvm::real xx() const { return array[0][0]; }
00439   inline cvm::real xy() const { return array[0][1]; }
00441   inline cvm::real xz() const { return array[0][2]; }
00443   inline cvm::real yx() const { return array[1][0]; }
00445   inline cvm::real yy() const { return array[1][1]; }
00447   inline cvm::real yz() const { return array[1][2]; }
00449   inline cvm::real zx() const { return array[2][0]; }
00451   inline cvm::real zy() const { return array[2][1]; }
00453   inline cvm::real zz() const { return array[2][2]; }
00454 
00456   inline rmatrix (cvm::real const **m) 
00457     : cvm::matrix2d<cvm::real, 3, 3> (m) 
00458   {}
00459 
00461   inline rmatrix() 
00462     : cvm::matrix2d<cvm::real, 3, 3>()
00463   {}
00464 
00466   inline rmatrix (cvm::real const &xxi,
00467                   cvm::real const &xyi,
00468                   cvm::real const &xzi,
00469                   cvm::real const &yxi,
00470                   cvm::real const &yyi,
00471                   cvm::real const &yzi,
00472                   cvm::real const &zxi,
00473                   cvm::real const &zyi,
00474                   cvm::real const &zzi) 
00475     : cvm::matrix2d<cvm::real, 3, 3>()
00476   {
00477     this->xx() = xxi;
00478     this->xy() = xyi;
00479     this->xz() = xzi;
00480     this->yx() = yxi;
00481     this->yy() = yyi;
00482     this->yz() = yzi;
00483     this->zx() = zxi;
00484     this->zy() = zyi;
00485     this->zz() = zzi;
00486   }
00487 
00489   inline ~rmatrix()
00490   {}    
00491 
00493   inline cvm::real determinant() const
00494   {
00495     return
00496       (  xx() * (yy()*zz() - zy()*yz()))
00497       - (yx() * (xy()*zz() - zy()*xz()))
00498       + (zx() * (xy()*yz() - yy()*xz()));
00499   }
00500 
00501   inline cvm::rmatrix transpose() const
00502   {
00503     return cvm::rmatrix (this->xx(),
00504                          this->yx(),
00505                          this->zx(),
00506                          this->xy(),
00507                          this->yy(),
00508                          this->zy(),
00509                          this->xz(),
00510                          this->yz(),
00511                          this->zz());
00512   }
00513 
00514   friend cvm::rvector operator * (cvm::rmatrix const &m, cvm::rvector const &r);
00515 
00516   //   friend inline cvm::rmatrix const operator * (cvm::rmatrix const &m1, cvm::rmatrix const &m2) {
00517   //     return cvm::rmatrix (m1.xx()*m2.xx() + m1.xy()*m2.yx() + m1.xz()*m2.yz(),
00518   //                     m1.xx()*m2.xy() + m1.xy()*m2.yy() + m1.xz()*m2.zy(),
00519   //                     m1.xx()*m2.xz() + m1.xy()*m2.yz() + m1.xz()*m2.zz(),
00520   //                     m1.yx()*m2.xx() + m1.yy()*m2.yx() + m1.yz()*m2.yz(),
00521   //                     m1.yx()*m2.xy() + m1.yy()*m2.yy() + m1.yz()*m2.yy(),
00522   //                     m1.yx()*m2.xz() + m1.yy()*m2.yz() + m1.yz()*m2.yz(),
00523   //                     m1.zx()*m2.xx() + m1.zy()*m2.yx() + m1.zz()*m2.yz(),
00524   //                     m1.zx()*m2.xy() + m1.zy()*m2.yy() + m1.zz()*m2.yy(),
00525   //                     m1.zx()*m2.xz() + m1.zy()*m2.yz() + m1.zz()*m2.yz());
00526   //   }
00527 
00528 };
00529 
00530                     
00531 inline cvm::rvector operator * (cvm::rmatrix const &m,
00532                                 cvm::rvector const &r)
00533 {
00534   return cvm::rvector (m.xx()*r.x + m.xy()*r.y + m.xz()*r.z,
00535                        m.yx()*r.x + m.yy()*r.y + m.yz()*r.z,
00536                        m.zx()*r.x + m.zy()*r.y + m.zz()*r.z);
00537 }
00538 
00539 
00541 void jacobi (cvm::real **a, int n, cvm::real d[], cvm::real **v, int *nrot);
00542 
00544 void eigsrt (cvm::real d[], cvm::real **v, int n);
00545 
00547 void transpose (cvm::real **v, int n);
00548 
00549 
00550 
00551 
00554 class colvarmodule::quaternion {
00555 
00556 public:
00557 
00558   cvm::real q0, q1, q2, q3;
00559 
00561   inline quaternion (cvm::real const &x, cvm::real const &y, cvm::real const &z)
00562     : q0 (0.0), q1 (x), q2 (y), q3 (z)
00563   {}
00564 
00566   inline quaternion (cvm::real const qv[4])
00567     : q0 (qv[0]), q1 (qv[1]), q2 (qv[2]), q3 (qv[3])
00568   {}
00569 
00571   inline quaternion (cvm::real const &q0i,
00572                      cvm::real const &q1i,
00573                      cvm::real const &q2i,
00574                      cvm::real const &q3i)
00575     : q0 (q0i), q1 (q1i), q2 (q2i), q3 (q3i)
00576   {}
00577 
00581   inline void set_from_euler_angles (cvm::real const &phi_in,
00582                                      cvm::real const &theta_in,
00583                                      cvm::real const &psi_in)
00584   {
00585     q0 = ( (std::cos (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::cos (psi_in/2.0)) +
00586            (std::sin (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
00587 
00588     q1 = ( (std::sin (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::cos (psi_in/2.0)) -
00589            (std::cos (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
00590 
00591     q2 = ( (std::cos (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::cos (psi_in/2.0)) +
00592            (std::sin (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::sin (psi_in/2.0)) );
00593 
00594     q3 = ( (std::cos (phi_in/2.0)) * (std::cos (theta_in/2.0)) * (std::sin (psi_in/2.0)) -
00595            (std::sin (phi_in/2.0)) * (std::sin (theta_in/2.0)) * (std::cos (psi_in/2.0)) );
00596   }
00597 
00599   inline quaternion()
00600   {
00601     reset();
00602   }
00603 
00605   inline void set (cvm::real const value = 0.0)
00606   {
00607     q0 = q1 = q2 = q3 = value;
00608   }
00609 
00611   inline void reset()
00612   {
00613     q0 = q1 = q2 = q3 = 0.0;
00614   }
00615 
00618   inline void reset_rotation()
00619   {
00620     q0 = 1.0;
00621     q1 = q2 = q3 = 0.0;
00622   }
00623 
00625   static inline size_t output_width (size_t const &real_width)
00626   {
00627     return 4*real_width + 13;
00628   }
00629 
00631   friend std::ostream & operator << (std::ostream &os, cvm::quaternion const &q);
00633   friend std::istream & operator >> (std::istream &is, cvm::quaternion &q);
00634 
00636   inline cvm::real & operator [] (int const &i) {
00637     switch (i) {
00638     case 0:
00639       return this->q0;
00640     case 1:
00641       return this->q1;
00642     case 2:
00643       return this->q2;
00644     case 3:
00645       return this->q3;
00646     default:
00647       cvm::fatal_error ("Error: incorrect quaternion component.\n");
00648       return q0;
00649     }
00650   }
00651 
00653   inline cvm::real operator [] (int const &i) const {
00654     switch (i) {
00655     case 0:
00656       return this->q0;
00657     case 1:
00658       return this->q1;
00659     case 2:
00660       return this->q2;
00661     case 3:
00662       return this->q3;
00663     default:
00664       cvm::fatal_error ("Error: trying to access a quaternion "
00665                         "component which is not between 0 and 3.\n");
00666       return this->q0;
00667     }
00668   }
00669 
00671   inline cvm::real norm2() const
00672   {
00673     return q0*q0 + q1*q1 + q2*q2 + q3*q3;
00674   }
00675 
00677   inline cvm::real norm() const
00678   {
00679     return std::sqrt (this->norm2());
00680   }
00681 
00683   inline cvm::quaternion conjugate() const
00684   {
00685     return cvm::quaternion (q0, -q1, -q2, -q3);
00686   }
00687 
00688   inline void operator *= (cvm::real const &a)
00689   {
00690     q0 *= a; q1 *= a; q2 *= a; q3 *= a;
00691   }
00692 
00693   inline void operator /= (cvm::real const &a)
00694   {
00695     q0 /= a; q1 /= a; q2 /= a; q3 /= a;
00696   }
00697 
00698   inline void set_positive()
00699   {
00700     if (q0 > 0.0) return;
00701     q0 = -q0;
00702     q1 = -q1;
00703     q2 = -q2;
00704     q3 = -q3;
00705   }
00706 
00707   inline void operator += (cvm::quaternion const &h)
00708   {
00709     q0+=h.q0; q1+=h.q1; q2+=h.q2; q3+=h.q3;
00710   }
00711   inline void operator -= (cvm::quaternion const &h)
00712   {
00713     q0-=h.q0; q1-=h.q1; q2-=h.q2; q3-=h.q3;
00714   }
00715 
00717   static inline cvm::quaternion promote (cvm::rvector const &v)
00718   {
00719     return cvm::quaternion (0.0, v.x, v.y, v.z);
00720   }
00722   inline cvm::rvector get_vector() const 
00723   {
00724     return cvm::rvector (q1, q2, q3);
00725   }
00726 
00727 
00728   friend inline cvm::quaternion operator + (cvm::quaternion const &h, cvm::quaternion const &q)
00729   {
00730     return cvm::quaternion (h.q0+q.q0, h.q1+q.q1, h.q2+q.q2, h.q3+q.q3);
00731   }
00732 
00733   friend inline cvm::quaternion operator - (cvm::quaternion const &h, cvm::quaternion const &q)
00734   {
00735     return cvm::quaternion (h.q0-q.q0, h.q1-q.q1, h.q2-q.q2, h.q3-q.q3);
00736   }
00737 
00740   friend inline cvm::quaternion operator * (cvm::quaternion const &h, cvm::quaternion const &q)
00741   {
00742     return cvm::quaternion (h.q0*q.q0 - h.q1*q.q1 - h.q2*q.q2 - h.q3*q.q3,
00743                             h.q0*q.q1 + h.q1*q.q0 + h.q2*q.q3 - h.q3*q.q2,
00744                             h.q0*q.q2 + h.q2*q.q0 + h.q3*q.q1 - h.q1*q.q3,
00745                             h.q0*q.q3 + h.q3*q.q0 + h.q1*q.q2 - h.q2*q.q1);
00746   }
00747 
00748   friend inline cvm::quaternion operator * (cvm::real const &c,
00749                                             cvm::quaternion const &q)
00750   {
00751     return cvm::quaternion (c*q.q0, c*q.q1, c*q.q2, c*q.q3);
00752   }
00753   friend inline cvm::quaternion operator * (cvm::quaternion const &q,
00754                                             cvm::real const &c)
00755   {
00756     return cvm::quaternion (q.q0*c, q.q1*c, q.q2*c, q.q3*c);
00757   }
00758   friend inline cvm::quaternion operator / (cvm::quaternion const &q,
00759                                             cvm::real const &c)
00760   {
00761     return cvm::quaternion (q.q0/c, q.q1/c, q.q2/c, q.q3/c);
00762   }
00763 
00764 
00767   inline cvm::rvector rotate (cvm::rvector const &v) const
00768   {
00769     return ((*this) * promote (v) * ((*this).conjugate())).get_vector();
00770   }
00771 
00774   inline cvm::quaternion rotate (cvm::quaternion const &Q2) const
00775   {
00776     cvm::rvector const vq_rot = this->rotate (Q2.get_vector());
00777     return cvm::quaternion (Q2.q0, vq_rot.x, vq_rot.y, vq_rot.z);
00778   }
00779 
00781   inline cvm::rmatrix rotation_matrix() const
00782   {
00783     cvm::rmatrix R;
00784 
00785     R.xx() = q0*q0 + q1*q1 - q2*q2 - q3*q3;
00786     R.yy() = q0*q0 - q1*q1 + q2*q2 - q3*q3;
00787     R.zz() = q0*q0 - q1*q1 - q2*q2 + q3*q3;
00788 
00789     R.xy() = 2.0 * (q1*q2 - q0*q3);
00790     R.xz() = 2.0 * (q0*q2 + q1*q3);
00791 
00792     R.yx() = 2.0 * (q0*q3 + q1*q2);
00793     R.yz() = 2.0 * (q2*q3 - q0*q1);
00794 
00795     R.zx() = 2.0 * (q1*q3 - q0*q2);
00796     R.zy() = 2.0 * (q0*q1 + q2*q3);
00797 
00798     return R;
00799   }
00800 
00801 
00804   cvm::quaternion position_derivative_inner (cvm::rvector const &pos,
00805                                              cvm::rvector const &vec) const;
00806 
00807 
00810   inline cvm::real cosine (cvm::quaternion const &q) const
00811   {
00812     if (q0*q0 >= (1.0-1.0E-10)) {
00813       // null quaternion, return the square of the cosine of the other
00814       // quaternion's rotation angle
00815       return (2.0*q.q0*q.q0 - 1.0);
00816     } else if (q.q0*q.q0 >= (1.0-1.0E-10)) {
00817       return (2.0*q0*q0 - 1.0);
00818     } else {
00819       // get a vector orthogonal to both axes of rotation
00820       cvm::rvector const op = (cvm::rvector::outer (this->get_vector(), q.get_vector()));
00821       cvm::real const  opl2 = op.norm2();
00822       // rotate it with both quaternions and get the normalized inner product
00823       return ( (opl2 > 0.0) ?
00824                ((this->rotate (op)) * (q.rotate (op))) / opl2 :
00825                1.0 );
00826     }
00827   }
00828 
00832   inline cvm::real dist2 (cvm::quaternion const &Q2) const
00833   {
00834     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
00835       this->q2*Q2.q2 + this->q3*Q2.q3;
00836 
00837     cvm::real const omega = std::acos ( (cos_omega > 1.0) ? 1.0 :
00838                                      ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
00839 
00840     // get the minimum distance: x and -x are the same quaternion
00841     if (cos_omega > 0.0)
00842       return omega * omega;
00843     else
00844       return (PI-omega) * (PI-omega);
00845   }
00846 
00849   inline cvm::quaternion dist2_grad (cvm::quaternion const &Q2) const
00850   {
00851     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
00852     cvm::real const omega = std::acos ( (cos_omega > 1.0) ? 1.0 :
00853                                      ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
00854     cvm::real const sin_omega = std::sin (omega);
00855 
00856     if (std::fabs (sin_omega) < 1.0E-14) {
00857       // return a null 4d vector
00858       return cvm::quaternion (0.0, 0.0, 0.0, 0.0);
00859     }
00860 
00861     cvm::quaternion const
00862       grad1 ((-1.0)*sin_omega*Q2.q0 + cos_omega*(this->q0-cos_omega*Q2.q0)/sin_omega,
00863              (-1.0)*sin_omega*Q2.q1 + cos_omega*(this->q1-cos_omega*Q2.q1)/sin_omega,
00864              (-1.0)*sin_omega*Q2.q2 + cos_omega*(this->q2-cos_omega*Q2.q2)/sin_omega,
00865              (-1.0)*sin_omega*Q2.q3 + cos_omega*(this->q3-cos_omega*Q2.q3)/sin_omega);
00866 
00867     if (cos_omega > 0.0) {
00868       return 2.0*omega*grad1;
00869     }
00870     else {
00871       return -2.0*(PI-omega)*grad1;
00872     }
00873   }
00874 
00877   inline void match (cvm::quaternion &Q2) const
00878   {
00879     cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
00880       this->q2*Q2.q2 + this->q3*Q2.q3;
00881     if (cos_omega < 0.0) Q2 *= -1.0;
00882   }
00883 
00886   inline cvm::real inner (cvm::quaternion const &Q2) const
00887   {
00888     cvm::real const prod = this->q0*Q2.q0 + this->q1*Q2.q1 +
00889       this->q2*Q2.q2 + this->q3*Q2.q3;
00890     return prod;
00891   }
00892 
00893 
00894 };
00895 
00896 
00899 class colvarmodule::rotation
00900 {
00901 public:
00902 
00904   cvm::quaternion q;
00905 
00907   cvm::real lambda;
00908 
00910   bool b_debug_gradients;
00911 
00914   std::vector< cvm::atom_pos > pos1, pos2;
00915 
00917   std::vector< cvm::matrix2d<cvm::rvector, 4, 4> > dS_1,  dS_2;
00919   std::vector< cvm::rvector >                      dL0_1, dL0_2;
00921   std::vector< cvm::vector1d<cvm::rvector, 4> >    dQ0_1, dQ0_2;
00922 
00924   inline void request_group1_gradients (size_t const &n)
00925   {
00926     dS_1.resize  (n, cvm::matrix2d<cvm::rvector, 4, 4>());
00927     dL0_1.resize (n, cvm::rvector (0.0, 0.0, 0.0));
00928     dQ0_1.resize (n, cvm::vector1d<cvm::rvector, 4>());
00929   }
00930 
00931   inline void request_group2_gradients (size_t const &n)
00932   {
00933     dS_2.resize  (n, cvm::matrix2d<cvm::rvector, 4, 4>());
00934     dL0_2.resize (n, cvm::rvector (0.0, 0.0, 0.0));
00935     dQ0_2.resize (n, cvm::vector1d<cvm::rvector, 4>());
00936   }
00937 
00948   void calc_optimal_rotation (std::vector<atom_pos> const &pos1,
00949                               std::vector<atom_pos> const &pos2);
00950 
00952   inline rotation()
00953     : b_debug_gradients (false)
00954   {}
00955 
00957   inline rotation (cvm::quaternion const &qi)
00958     : b_debug_gradients (false)
00959   {
00960     q = qi;
00961   }
00962 
00964   inline rotation (cvm::real const &angle, cvm::rvector const &axis)
00965     : b_debug_gradients (false)
00966   {
00967     cvm::rvector const axis_n = axis.unit();
00968     cvm::real const sina = std::sin (angle/2.0);
00969     q = cvm::quaternion (std::cos (angle/2.0),
00970                          sina * axis_n.x, sina * axis_n.y, sina * axis_n.z);
00971   }
00972 
00974   inline ~rotation()
00975   {}
00976 
00978   inline cvm::rvector rotate (cvm::rvector const &v) const
00979   {
00980     return q.rotate (v);
00981   }
00982 
00984   inline cvm::rotation inverse() const
00985   {
00986     return cvm::rotation (this->q.conjugate());
00987   }
00988 
00990   inline cvm::rmatrix matrix() const
00991   {
00992     return q.rotation_matrix();
00993   }
00994 
00995 
00998   inline cvm::real spin_angle (cvm::rvector const &axis) const
00999   {
01000     cvm::rvector const q_vec = q.get_vector();
01001     cvm::real alpha = (180.0/PI) * 2.0 * std::atan2 (axis * q_vec, q.q0);
01002     while (alpha >  180.0) alpha -= 360;
01003     while (alpha < -180.0) alpha += 360;
01004     return alpha;
01005   }
01006 
01009   inline cvm::quaternion dspin_angle_dq (cvm::rvector const &axis) const
01010   {
01011     cvm::rvector const q_vec = q.get_vector();
01012     cvm::real const iprod = axis * q_vec;
01013 
01014     if (q.q0 != 0.0) {
01015 
01016       // cvm::real const x = iprod/q.q0;
01017       
01018       cvm::real const dspindx = (180.0/PI) * 2.0 * (1.0 / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
01019 
01020       return 
01021         cvm::quaternion ( dspindx * (iprod * (-1.0) / (q.q0*q.q0)), 
01022                           dspindx * ((1.0/q.q0) * axis.x),
01023                           dspindx * ((1.0/q.q0) * axis.y),
01024                           dspindx * ((1.0/q.q0) * axis.z));
01025     } else {
01026       // (1/(1+x^2)) ~ (1/x)^2
01027       return
01028         cvm::quaternion ((180.0/PI) * 2.0 * ((-1.0)/iprod), 0.0, 0.0, 0.0);
01029       // XX TODO: What if iprod == 0? XX
01030     }
01031   }
01032 
01035   inline cvm::real cos_theta (cvm::rvector const &axis) const
01036   {
01037     cvm::rvector const q_vec = q.get_vector();
01038     cvm::real const alpha = 
01039       (180.0/PI) * 2.0 * std::atan2 (axis * q_vec, q.q0);
01040 
01041     cvm::real const cos_spin_2 = std::cos (alpha * (PI/180.0) * 0.5);
01042     cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ? 
01043                                     (q.q0 / cos_spin_2) :
01044                                     (0.0) );
01045     // cos(2t) = 2*cos(t)^2 - 1
01046     return 2.0 * (cos_theta_2*cos_theta_2) - 1.0;
01047   }
01048 
01050   inline cvm::quaternion dcos_theta_dq (cvm::rvector const &axis) const
01051   {
01052     cvm::rvector const q_vec = q.get_vector();
01053     cvm::real const iprod = axis * q_vec;
01054 
01055     cvm::real const cos_spin_2 = std::cos (std::atan2 (iprod, q.q0));
01056 
01057     if (q.q0 != 0.0)  {
01058 
01059       cvm::real const d_cos_theta_dq0 = 
01060         (4.0 * q.q0 / (cos_spin_2*cos_spin_2)) *
01061         (1.0 - (iprod*iprod)/(q.q0*q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
01062 
01063       cvm::real const d_cos_theta_dqn =
01064         (4.0 * q.q0 / (cos_spin_2*cos_spin_2) *
01065          (iprod/q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
01066 
01067       return cvm::quaternion (d_cos_theta_dq0, 
01068                               d_cos_theta_dqn * axis.x,
01069                               d_cos_theta_dqn * axis.y,
01070                               d_cos_theta_dqn * axis.z);
01071     } else {
01072 
01073       cvm::real const d_cos_theta_dqn =
01074         (4.0 / (cos_spin_2*cos_spin_2 * iprod));
01075 
01076       return cvm::quaternion (0.0,
01077                               d_cos_theta_dqn * axis.x,
01078                               d_cos_theta_dqn * axis.y,
01079                               d_cos_theta_dqn * axis.z);
01080     }
01081   }
01082 
01084   static cvm::real crossing_threshold;
01085 
01086 protected:
01087 
01091   cvm::quaternion q_old;
01092 
01094   void build_matrix (std::vector<cvm::atom_pos> const &pos1,
01095                      std::vector<cvm::atom_pos> const &pos2,
01096                      cvm::matrix2d<real, 4, 4>        &S);
01097 
01099   void diagonalize_matrix (cvm::matrix2d<cvm::real, 4, 4> &S,
01100                            cvm::real                       S_eigval[4],
01101                            cvm::matrix2d<cvm::real, 4, 4> &S_eigvec);
01102 };
01103 
01104 
01105 #endif
01106 
01107 // Emacs
01108 // Local Variables:
01109 // mode: C++
01110 // End:

Generated on Fri May 25 04:07:13 2012 for NAMD by  doxygen 1.3.9.1