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 #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 //   /// Matrix addi(c)tion
00357 //   inline friend matrix2d<T, outer_length, inner_length>
00358 //   operator + (matrix2d<T, outer_length, inner_length> const &mat1,
00359 //               matrix2d<T, outer_length, inner_length> const &mat2) {
00360 //     matrix2d<T, outer_length, inner_length> sum;
00361 //     for (size_t i = 0; i < outer_length; i++) {
00362 //       for (size_t j = 0; j < inner_length; j++) {
00363 //         sum[i][j] = mat1[i][j] + mat2[i][j];
00364 //       }
00365 //     }
00366 //   }
00367 
00368 //   /// Matrix subtraction
00369 //   inline friend matrix2d<T, outer_length, inner_length>
00370 //   operator - (matrix2d<T, outer_length, inner_length> const &mat1,
00371 //               matrix2d<T, outer_length, inner_length> const &mat2) {
00372 //     matrix2d<T, outer_length, inner_length> sum;
00373 //     for (size_t i = 0; i < outer_length; i++) {
00374 //       for (size_t j = 0; j < inner_length; j++) {
00375 //         sum[i][j] = mat1[i][j] - mat2[i][j];
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   //   friend inline cvm::rmatrix const operator * (cvm::rmatrix const &m1, cvm::rmatrix const &m2) {
00515   //     return cvm::rmatrix (m1.xx()*m2.xx() + m1.xy()*m2.yx() + m1.xz()*m2.yz(),
00516   //                     m1.xx()*m2.xy() + m1.xy()*m2.yy() + m1.xz()*m2.zy(),
00517   //                     m1.xx()*m2.xz() + m1.xy()*m2.yz() + m1.xz()*m2.zz(),
00518   //                     m1.yx()*m2.xx() + m1.yy()*m2.yx() + m1.yz()*m2.yz(),
00519   //                     m1.yx()*m2.xy() + m1.yy()*m2.yy() + m1.yz()*m2.yy(),
00520   //                     m1.yx()*m2.xz() + m1.yy()*m2.yz() + m1.yz()*m2.yz(),
00521   //                     m1.zx()*m2.xx() + m1.zy()*m2.yx() + m1.zz()*m2.yz(),
00522   //                     m1.zx()*m2.xy() + m1.zy()*m2.yy() + m1.zz()*m2.yy(),
00523   //                     m1.zx()*m2.xz() + m1.zy()*m2.yz() + m1.zz()*m2.yz());
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     // get a vector orthogonal to both axes of rotation
00805     cvm::rvector const op = (cvm::rvector::outer (this->get_vector(), q.get_vector()));
00806     cvm::real const  opl2 = op.norm2();
00807     // rotate it with both quaternions and get the normalized inner product
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     // get the minimum distance: x and -x are the same quaternion
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       // return a null 4d vector
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 // Emacs
01005 // Local Variables:
01006 // mode: C++
01007 // End:

Generated on Mon Nov 23 04:59:19 2009 for NAMD by  doxygen 1.3.9.1