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

colvarvalue.h

Go to the documentation of this file.
00001 #ifndef COLVARVALUE_H
00002 #define COLVARVALUE_H
00003 
00004 #include "colvarmodule.h"
00005 
00006 
00056 
00057 class colvarvalue {
00058 
00059 public:
00060 
00066   enum Type {
00068     type_notset,
00070     type_scalar,
00072     type_vector,
00074     type_unitvector,
00076     type_quaternion
00077   };
00078 
00080   std::string static const type_desc[colvarvalue::type_quaternion+1];
00081 
00083   size_t static const      dof_num[  colvarvalue::type_quaternion+1];
00084 
00086   cvm::real       real_value;
00087 
00089   cvm::rvector    rvector_value;
00090 
00092   cvm::quaternion quaternion_value;
00093 
00095   Type  value_type; 
00096 
00097   static inline bool type_checking()
00098   {
00099     return true;
00100   }
00101 
00104   inline colvarvalue()
00105     : real_value (0.0), value_type (type_scalar)
00106   {}
00107 
00109   inline colvarvalue (Type const &vti)
00110     : value_type (vti)
00111   {
00112     reset();
00113   }
00114 
00116   inline colvarvalue (cvm::real const &x)
00117     : real_value (x), value_type (type_scalar)
00118   {}
00119 
00123   inline colvarvalue (cvm::rvector const &v)
00124     : rvector_value (v), value_type (type_vector)
00125   {}
00126 
00130   inline colvarvalue (cvm::rvector const &v, Type const &vti)
00131     : rvector_value (v), value_type (vti)
00132   {}
00133 
00135   inline colvarvalue (cvm::quaternion const &q)
00136     : quaternion_value (q), value_type (type_quaternion)
00137   {}
00138 
00140   inline colvarvalue (colvarvalue const &x)
00141     : value_type (x.value_type)
00142   {
00143     reset();
00144 
00145     switch (x.value_type) {
00146     case type_scalar:
00147       real_value = x.real_value;
00148       break;
00149     case type_vector: 
00150     case type_unitvector:
00151       rvector_value = x.rvector_value;
00152       break;
00153     case type_quaternion:
00154       quaternion_value = x.quaternion_value;
00155       break;
00156     case type_notset:
00157     default:
00158       break;
00159     }
00160   }
00161 
00162 
00163 
00165   void reset();
00166 
00167 
00172   void apply_constraints();
00173 
00174 
00176   inline Type type() const
00177   {
00178     return value_type;
00179   }
00180 
00182   inline void type (Type const &vti)
00183   {
00184     reset();
00185     value_type = vti;
00186     reset();
00187   }
00188 
00190   inline void type (colvarvalue const &x)
00191   {
00192     reset();
00193     value_type = x.value_type;
00194     reset();
00195   }
00196 
00198   cvm::real norm2() const;
00199 
00201   inline cvm::real norm() const
00202   {
00203     return std::sqrt (this->norm2());
00204   }
00205 
00208   inline colvarvalue inverse() const;
00209 
00211   cvm::real dist2 (colvarvalue const &x2) const;
00212 
00214   colvarvalue dist2_grad (colvarvalue const &x2) const;
00215 
00217   colvarvalue & operator = (colvarvalue const &x);
00218 
00219   void operator += (colvarvalue const &x);
00220   void operator -= (colvarvalue const &x);
00221   void operator *= (cvm::real const &a);
00222   void operator /= (cvm::real const &a);
00223 
00224 
00225   // Casting operator
00226   inline operator cvm::real() const
00227   {
00228     if (value_type != type_scalar) error_rside (type_scalar);
00229     return real_value;
00230   }
00231 
00232   // Casting operator
00233   inline operator cvm::rvector() const
00234   {
00235     if ( (value_type != type_vector) && (value_type != type_unitvector))
00236       error_rside (type_vector);
00237     return rvector_value;
00238   }
00239 
00240   // Casting operator
00241   inline operator cvm::quaternion() const
00242   {
00243     if (value_type != type_quaternion) error_rside (type_quaternion);
00244     return quaternion_value;
00245   }
00246 
00248   inline bool is_scalar()
00249   {
00250     return (value_type == type_scalar);
00251   }
00252 
00253 
00255   void static check_types (colvarvalue const &x1, colvarvalue const &x2);
00256 
00258   void undef_op() const;
00259 
00262   void error_lside (Type const &vt) const;
00263 
00266   void error_rside (Type const &vt) const;
00267 
00271   size_t output_width (size_t const &real_width);
00272 
00273 
00274   // optimized routines for operations with an array; xv and inner as
00275   // vectors are assumed to have the same number of elements (i.e. the
00276   // end for inner comes together with xv_end in the loop)
00277 
00280   void static inner_opt (colvarvalue const                        &x,
00281                          std::vector<colvarvalue>::iterator       &xv,
00282                          std::vector<colvarvalue>::iterator const &xv_end,
00283                          std::vector<cvm::real>::iterator         &inner);
00284 
00287   void static inner_opt (colvarvalue const                        &x,
00288                          std::list<colvarvalue>::iterator         &xv,
00289                          std::list<colvarvalue>::iterator const   &xv_end,
00290                          std::vector<cvm::real>::iterator         &inner);
00291 
00295   void static p2leg_opt (colvarvalue const                        &x,
00296                          std::vector<colvarvalue>::iterator       &xv,
00297                          std::vector<colvarvalue>::iterator const &xv_end,
00298                          std::vector<cvm::real>::iterator         &inner);
00299 
00302   void static p2leg_opt (colvarvalue const                        &x,
00303                          std::list<colvarvalue>::iterator         &xv,
00304                          std::list<colvarvalue>::iterator const   &xv_end,
00305                          std::vector<cvm::real>::iterator         &inner);
00306 
00307 };
00308 
00309 
00310 
00311 inline void colvarvalue::reset()
00312 {
00313   switch (value_type) {
00314   case colvarvalue::type_scalar:
00315     real_value = cvm::real (0.0);
00316     break;
00317   case colvarvalue::type_vector:
00318   case colvarvalue::type_unitvector:
00319     rvector_value = cvm::rvector (0.0, 0.0, 0.0);
00320     break;
00321   case colvarvalue::type_quaternion:
00322     quaternion_value = cvm::quaternion (0.0, 0.0, 0.0, 0.0);
00323     break;
00324   case colvarvalue::type_notset:
00325   default:
00326     break;
00327   }  
00328 }
00329 
00330 
00331 inline void colvarvalue::apply_constraints()
00332 {
00333   switch (value_type) {
00334   case colvarvalue::type_scalar:
00335     break;
00336   case colvarvalue::type_vector:
00337     break;
00338   case colvarvalue::type_unitvector:
00339     rvector_value /= std::sqrt (rvector_value.norm2());
00340     break;
00341   case colvarvalue::type_quaternion:
00342     quaternion_value /= std::sqrt (quaternion_value.norm2());
00343     break;
00344   case colvarvalue::type_notset:
00345   default:
00346     break;
00347   }  
00348 }
00349 
00350 
00351 
00352 inline cvm::real colvarvalue::norm2() const
00353 {
00354   switch (value_type) {
00355   case colvarvalue::type_scalar:
00356     return (this->real_value)*(this->real_value);
00357   case colvarvalue::type_vector:
00358   case colvarvalue::type_unitvector:
00359     return (this->rvector_value).norm2();
00360   case colvarvalue::type_quaternion:
00361     return (this->quaternion_value).norm2();
00362   case colvarvalue::type_notset:
00363   default:
00364     return 0.0;
00365   }  
00366 }
00367 
00368 
00369 inline colvarvalue colvarvalue::inverse() const
00370 {
00371   switch (value_type) {
00372   case colvarvalue::type_scalar:
00373     return colvarvalue (1.0/real_value);
00374   case colvarvalue::type_vector:
00375     return colvarvalue (cvm::rvector (1.0/rvector_value.x,
00376                                       1.0/rvector_value.y,
00377                                       1.0/rvector_value.z));
00378   case colvarvalue::type_quaternion:
00379     return colvarvalue (cvm::quaternion (1.0/quaternion_value.q0,
00380                                          1.0/quaternion_value.q1,
00381                                          1.0/quaternion_value.q2,
00382                                          1.0/quaternion_value.q3));
00383   case colvarvalue::type_notset:
00384   default:
00385     undef_op();
00386   }  
00387   return colvarvalue();
00388 }
00389 
00390 
00391 inline colvarvalue & colvarvalue::operator = (colvarvalue const &x)
00392 {
00393   if (this->value_type != type_notset)
00394     if (this->value_type != x.value_type) 
00395       error_lside (x.value_type);
00396 
00397   this->value_type = x.value_type;
00398   
00399   switch (this->value_type) {
00400   case colvarvalue::type_scalar:
00401     this->real_value = x.real_value;
00402     break;
00403   case colvarvalue::type_vector:
00404   case colvarvalue::type_unitvector:
00405     this->rvector_value = x.rvector_value;
00406     break;
00407   case colvarvalue::type_quaternion:
00408     this->quaternion_value = x.quaternion_value;
00409     break;
00410   case colvarvalue::type_notset:
00411   default:
00412     undef_op();
00413     break;
00414   }
00415   return *this;
00416 }
00417 
00418 inline void colvarvalue::operator += (colvarvalue const &x)
00419 {
00420   if (colvarvalue::type_checking())
00421     colvarvalue::check_types (*this, x);
00422 
00423   switch (this->value_type) {
00424   case colvarvalue::type_scalar:
00425     this->real_value += x.real_value;
00426     break;
00427   case colvarvalue::type_vector:
00428   case colvarvalue::type_unitvector:
00429     this->rvector_value += x.rvector_value;
00430     break;
00431   case colvarvalue::type_quaternion:
00432     this->quaternion_value += x.quaternion_value;
00433     break;
00434   case colvarvalue::type_notset:
00435   default:
00436     undef_op();
00437   }
00438 }
00439 
00440 inline void colvarvalue::operator -= (colvarvalue const &x)
00441 {
00442   if (colvarvalue::type_checking())
00443     colvarvalue::check_types (*this, x);
00444 
00445   switch (value_type) {
00446   case colvarvalue::type_scalar:
00447     real_value -= x.real_value; break;
00448   case colvarvalue::type_vector:
00449   case colvarvalue::type_unitvector:
00450     rvector_value -= x.rvector_value; break;
00451   case colvarvalue::type_quaternion:
00452     quaternion_value -= x.quaternion_value; break;
00453   case colvarvalue::type_notset:
00454   default:
00455     undef_op();
00456   }
00457 }
00458 
00459 inline void colvarvalue::operator *= (cvm::real const &a)
00460 {
00461   switch (value_type) {
00462   case colvarvalue::type_scalar:
00463     real_value *= a;
00464     break;
00465   case colvarvalue::type_vector:
00466   case colvarvalue::type_unitvector:
00467     rvector_value *= a;
00468     break;
00469   case colvarvalue::type_quaternion:
00470     quaternion_value *= a;
00471     break;
00472   case colvarvalue::type_notset:
00473   default:
00474     undef_op();
00475   }
00476 }
00477 
00478 inline void colvarvalue::operator /= (cvm::real const &a)
00479 {
00480   switch (value_type) {
00481   case colvarvalue::type_scalar:
00482     real_value /= a; break;
00483   case colvarvalue::type_vector:
00484   case colvarvalue::type_unitvector:
00485     rvector_value /= a; break;
00486   case colvarvalue::type_quaternion:
00487     quaternion_value /= a; break;
00488   case colvarvalue::type_notset:
00489   default:
00490     undef_op();
00491   }
00492 }
00493 
00494 
00495 // binary operations between two colvarvalues
00496 
00497 inline colvarvalue operator + (colvarvalue const &x1,
00498                                colvarvalue const &x2)
00499 {
00500   if (colvarvalue::type_checking())
00501     colvarvalue::check_types (x1, x2);
00502 
00503   switch (x1.value_type) {
00504   case colvarvalue::type_scalar:
00505     return colvarvalue (x1.real_value + x2.real_value);
00506   case colvarvalue::type_vector:
00507     return colvarvalue (x1.rvector_value + x2.rvector_value);
00508   case colvarvalue::type_unitvector:
00509     return colvarvalue (x1.rvector_value + x2.rvector_value,
00510                         colvarvalue::type_unitvector);
00511   case colvarvalue::type_quaternion:
00512     return colvarvalue (x1.quaternion_value + x2.quaternion_value);
00513   case colvarvalue::type_notset:
00514   default:
00515     x1.undef_op();
00516     return colvarvalue (colvarvalue::type_notset);
00517   };
00518 }
00519 
00520 inline colvarvalue operator - (colvarvalue const &x1,
00521                                colvarvalue const &x2)
00522 {
00523   if (colvarvalue::type_checking())
00524     colvarvalue::check_types (x1, x2);
00525 
00526   switch (x1.value_type) {
00527   case colvarvalue::type_scalar:
00528     return colvarvalue (x1.real_value - x2.real_value);
00529   case colvarvalue::type_vector:
00530     return colvarvalue (x1.rvector_value - x2.rvector_value);
00531   case colvarvalue::type_unitvector:
00532     return colvarvalue (x1.rvector_value - x2.rvector_value,
00533                         colvarvalue::type_unitvector);
00534   case colvarvalue::type_quaternion:
00535     return colvarvalue (x1.quaternion_value - x2.quaternion_value);
00536   default:
00537     x1.undef_op();
00538     return colvarvalue (colvarvalue::type_notset);
00539   };
00540 }
00541 
00542 
00543 // binary operations with real numbers
00544 
00545 inline colvarvalue operator * (cvm::real const &a,
00546                                colvarvalue const &x)
00547 {
00548   switch (x.value_type) {
00549   case colvarvalue::type_scalar:
00550     return colvarvalue (a * x.real_value);
00551   case colvarvalue::type_vector:
00552     return colvarvalue (a * x.rvector_value);
00553   case colvarvalue::type_unitvector:
00554     return colvarvalue (a * x.rvector_value,
00555                         colvarvalue::type_unitvector);
00556   case colvarvalue::type_quaternion:
00557     return colvarvalue (a * x.quaternion_value);
00558   case colvarvalue::type_notset:
00559   default:
00560     x.undef_op();
00561     return colvarvalue (colvarvalue::type_notset);
00562   }
00563 }
00564 
00565 inline colvarvalue operator * (colvarvalue const &x,
00566                                cvm::real const &a)
00567 {
00568   switch (x.value_type) {
00569   case colvarvalue::type_scalar:
00570     return colvarvalue (x.real_value * a);
00571   case colvarvalue::type_vector:
00572     return colvarvalue (x.rvector_value * a);
00573   case colvarvalue::type_unitvector:
00574     return colvarvalue (x.rvector_value * a,
00575                         colvarvalue::type_unitvector);
00576   case colvarvalue::type_quaternion:
00577     return colvarvalue (x.quaternion_value * a);
00578   case colvarvalue::type_notset:
00579   default:
00580     x.undef_op();
00581     return colvarvalue (colvarvalue::type_notset);
00582   }
00583 }
00584 
00585 inline colvarvalue operator / (colvarvalue const &x,
00586                                cvm::real const &a)
00587 {
00588   switch (x.value_type) {
00589   case colvarvalue::type_scalar:
00590     return colvarvalue (x.real_value / a);
00591   case colvarvalue::type_vector:
00592     return colvarvalue (x.rvector_value / a);
00593   case colvarvalue::type_unitvector:
00594     return colvarvalue (x.rvector_value / a,
00595                         colvarvalue::type_unitvector);
00596   case colvarvalue::type_quaternion:
00597     return colvarvalue (x.quaternion_value / a);
00598   case colvarvalue::type_notset:
00599   default:
00600     x.undef_op();
00601     return colvarvalue (colvarvalue::type_notset);
00602   }
00603 }
00604 
00605 
00606 // inner product between two colvarvalues
00607 
00608 inline cvm::real operator * (colvarvalue const &x1,
00609                              colvarvalue const &x2)
00610 {
00611   if (colvarvalue::type_checking())
00612     colvarvalue::check_types (x1, x2);
00613 
00614   switch (x1.value_type) {
00615   case colvarvalue::type_scalar:
00616     return (x1.real_value * x2.real_value);
00617   case colvarvalue::type_vector:
00618   case colvarvalue::type_unitvector:
00619     return (x1.rvector_value * x2.rvector_value);
00620   case colvarvalue::type_quaternion:
00621     // the "*" product is the quaternion product, here the inner
00622     // member function is used instead
00623     return (x1.quaternion_value.inner (x2.quaternion_value));
00624   case colvarvalue::type_notset:
00625   default:
00626     x1.undef_op();
00627     return 0.0;
00628   };
00629 }
00630 
00631 
00632 
00633 inline cvm::real colvarvalue::dist2 (colvarvalue const &x2) const
00634 {
00635   if (colvarvalue::type_checking())
00636     colvarvalue::check_types (*this, x2);
00637 
00638   switch (this->value_type) {
00639   case colvarvalue::type_scalar:
00640     return std::pow (this->real_value - x2.real_value, int (2));
00641   case colvarvalue::type_vector:
00642     return (this->rvector_value - x2.rvector_value).norm2();
00643   case colvarvalue::type_unitvector:
00644     // angle between (*this) and x2 is the distance
00645     return std::pow (std::acos (this->rvector_value * x2.rvector_value), int (2));
00646   case colvarvalue::type_quaternion:
00647     // angle between (*this) and x2 is the distance, the quaternion
00648     // object has it implemented internally
00649     return this->quaternion_value.dist2 (x2.quaternion_value);
00650   case colvarvalue::type_notset:
00651   default:
00652     this->undef_op();
00653     return 0.0;
00654   };
00655 }
00656 
00657 
00658 inline colvarvalue colvarvalue::dist2_grad (colvarvalue const &x2) const
00659 {
00660   if (colvarvalue::type_checking())
00661     colvarvalue::check_types (*this, x2);
00662 
00663   switch (this->value_type) {
00664   case colvarvalue::type_scalar:
00665     return 2.0 * (this->real_value - x2.real_value);
00666   case colvarvalue::type_vector:
00667     return 2.0 * (this->rvector_value - x2.rvector_value);
00668   case colvarvalue::type_unitvector:
00669     {
00670       cvm::rvector const &v1 = this->rvector_value;
00671       cvm::rvector const &v2 = x2.rvector_value;
00672       cvm::real const cos_t = v1 * v2;
00673       cvm::real const sin_t = std::sqrt (1.0 - cos_t*cos_t);
00674       return colvarvalue ( 2.0 * sin_t *
00675                            cvm::rvector ( (-1.0) * sin_t * v2.x +
00676                                           cos_t/sin_t * (v1.x - cos_t*v2.x),
00677                                           (-1.0) * sin_t * v2.y +
00678                                           cos_t/sin_t * (v1.y - cos_t*v2.y),
00679                                           (-1.0) * sin_t * v2.z +
00680                                           cos_t/sin_t * (v1.z - cos_t*v2.z)
00681                                           ),
00682                            colvarvalue::type_unitvector );
00683     }
00684   case colvarvalue::type_quaternion:
00685     return this->quaternion_value.dist2_grad (x2.quaternion_value);
00686   case colvarvalue::type_notset:
00687   default:
00688     this->undef_op();
00689     return colvarvalue (colvarvalue::type_notset);
00690   };
00691 }
00692 
00693 
00694 inline void colvarvalue::check_types (colvarvalue const &x1,
00695                                       colvarvalue const &x2)
00696 {
00697   if (x1.value_type != x2.value_type) {
00698     cvm::log ("x1 type = "+cvm::to_str (x1.value_type)+
00699               ", x2 type = "+cvm::to_str (x2.value_type)+"\n");
00700     cvm::fatal_error ("Performing an operation between two colvar "
00701                       "values with different types, \""+
00702                       colvarvalue::type_desc[x1.value_type]+
00703                       "\" and \""+
00704                       colvarvalue::type_desc[x2.value_type]+
00705                       "\".\n");
00706   }
00707 }
00708 
00709 
00710 
00711 
00712 std::ostream & operator << (std::ostream &os, colvarvalue const &x);
00713 std::ostream & operator << (std::ostream &os, std::vector<colvarvalue> const &v);
00714 
00715 std::istream & operator >> (std::istream &is, colvarvalue &x);
00716 
00717 
00718 
00719 
00720 
00721 #endif
00722 
00723 
00724 // Emacs
00725 // Local Variables:
00726 // mode: C++
00727 // End:

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