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
00226 inline operator cvm::real() const
00227 {
00228 if (value_type != type_scalar) error_rside (type_scalar);
00229 return real_value;
00230 }
00231
00232
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
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
00275
00276
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
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
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
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
00622
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
00645 return std::pow (std::acos (this->rvector_value * x2.rvector_value), int (2));
00646 case colvarvalue::type_quaternion:
00647
00648
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
00725
00726
00727