00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef COLVARVALUE_H
00011 #define COLVARVALUE_H
00012
00013 #include "colvarmodule.h"
00014 #include "colvartypes.h"
00015
00016
00039
00040
00041 class colvarvalue {
00042
00043 public:
00044
00050 enum Type {
00052 type_notset,
00054 type_scalar,
00056 type_3vector,
00058 type_unit3vector,
00060 type_unit3vectorderiv,
00062 type_quaternion,
00064 type_quaternionderiv,
00066 type_vector,
00068 type_all
00069 };
00070
00072 Type value_type;
00073
00075 cvm::real real_value;
00076
00078 cvm::rvector rvector_value;
00079
00081 cvm::quaternion quaternion_value;
00082
00084 cvm::vector1d<cvm::real> vector1d_value;
00085
00088 std::vector<Type> elem_types;
00089
00092 std::vector<int> elem_indices;
00093
00096 std::vector<int> elem_sizes;
00097
00099 static inline bool type_checking()
00100 {
00101 return true;
00102 }
00103
00105 static std::string const type_desc(Type t);
00106
00108 static std::string const type_keyword(Type t);
00109
00111 static size_t num_df(Type t);
00112
00114 static size_t num_dimensions(Type t);
00115
00117 size_t size() const;
00118
00121 colvarvalue();
00122
00124 colvarvalue(Type const &vti);
00125
00127 colvarvalue(cvm::real const &x);
00128
00132 colvarvalue(cvm::rvector const &v, Type vti = type_3vector);
00133
00135 colvarvalue(cvm::quaternion const &q, Type vti = type_quaternion);
00136
00138 colvarvalue(cvm::vector1d<cvm::real> const &v, Type vti = type_vector);
00139
00141 colvarvalue(colvarvalue const &x);
00142
00143
00145 void reset();
00146
00151 void apply_constraints();
00152
00154 inline Type type() const
00155 {
00156 return value_type;
00157 }
00158
00160 void type(Type const &vti);
00161
00163 void type(colvarvalue const &x);
00164
00167 void is_derivative();
00168
00170 cvm::real norm2() const;
00171
00173 inline cvm::real norm() const
00174 {
00175 return cvm::sqrt(this->norm2());
00176 }
00177
00179 cvm::real sum() const;
00180
00182 colvarvalue ones() const;
00183
00185 cvm::real dist2(colvarvalue const &x2) const;
00186
00188 colvarvalue dist2_grad(colvarvalue const &x2) const;
00189
00192 static colvarvalue const interpolate(colvarvalue const &x1,
00193 colvarvalue const &x2,
00194 cvm::real const lambda = 0.5);
00195
00197 colvarvalue & operator = (colvarvalue const &x);
00198
00199 void operator += (colvarvalue const &x);
00200 void operator -= (colvarvalue const &x);
00201 void operator *= (cvm::real const &a);
00202 void operator /= (cvm::real const &a);
00203
00204
00205 friend colvarvalue operator + (colvarvalue const &x1, colvarvalue const &x2);
00206 friend colvarvalue operator - (colvarvalue const &x1, colvarvalue const &x2);
00207 friend colvarvalue operator * (colvarvalue const &x, cvm::real const &a);
00208 friend colvarvalue operator * (cvm::real const &a, colvarvalue const &x);
00209 friend colvarvalue operator / (colvarvalue const &x, cvm::real const &a);
00210
00212 friend cvm::real operator * (colvarvalue const &x1, colvarvalue const &x2);
00213
00214
00215 inline operator cvm::real() const
00216 {
00217 if (value_type != type_scalar) {
00218 cvm::error("Error: trying to use a variable of type \""+
00219 type_desc(value_type)+"\" as one of type \""+
00220 type_desc(type_scalar)+"\".\n");
00221 }
00222 return real_value;
00223 }
00224
00225
00226 inline operator cvm::rvector() const
00227 {
00228 if ((value_type != type_3vector) &&
00229 (value_type != type_unit3vector) &&
00230 (value_type != type_unit3vectorderiv)) {
00231 cvm::error("Error: trying to use a variable of type \""+
00232 type_desc(value_type)+"\" as one of type \""+
00233 type_desc(type_3vector)+"\".\n");
00234 }
00235 return rvector_value;
00236 }
00237
00238
00239 inline operator cvm::quaternion() const
00240 {
00241 if ((value_type != type_quaternion) &&
00242 (value_type != type_quaternionderiv)) {
00243 cvm::error("Error: trying to use a variable of type \""+
00244 type_desc(value_type)+"\" as one of type \""+
00245 type_desc(type_quaternion)+"\".\n");
00246 }
00247 return quaternion_value;
00248 }
00249
00250
00251 cvm::vector1d<cvm::real> const as_vector() const;
00252
00253
00255 inline bool is_scalar() const
00256 {
00257 return (value_type == type_scalar);
00258 }
00259
00260
00264 void add_elem(colvarvalue const &x);
00265
00267 colvarvalue const get_elem(int const i_begin, int const i_end, Type const vt) const;
00268
00270 colvarvalue const get_elem(int const icv) const;
00271
00274 void set_elem(int const icv, colvarvalue const &x);
00275
00277 void set_elem(int const i_begin, int const i_end, colvarvalue const &x);
00278
00280 void set_random();
00281
00283 void set_ones(cvm::real assigned_value = 1.0);
00284
00286 cvm::real operator [] (int const i) const;
00287
00289 cvm::real & operator [] (int const i);
00290
00292 static int check_types(colvarvalue const &x1, colvarvalue const &x2);
00293
00295 static int check_types_assign(Type const &vt1, Type const &vt2);
00296
00298 void undef_op() const;
00299
00300
00302 friend std::ostream & operator << (std::ostream &os, colvarvalue const &q);
00303
00305 friend std::istream & operator >> (std::istream &is, colvarvalue &q);
00306
00310 size_t output_width(size_t const &real_width) const;
00311
00313 std::string to_simple_string() const;
00314
00316 int from_simple_string(std::string const &s);
00317
00318
00319
00320
00321
00324 static void inner_opt(colvarvalue const &x,
00325 std::vector<colvarvalue>::iterator &xv,
00326 std::vector<colvarvalue>::iterator const &xv_end,
00327 std::vector<cvm::real>::iterator &result);
00328
00331 static void inner_opt(colvarvalue const &x,
00332 std::list<colvarvalue>::iterator &xv,
00333 std::list<colvarvalue>::iterator const &xv_end,
00334 std::vector<cvm::real>::iterator &result);
00335
00339 static void p2leg_opt(colvarvalue const &x,
00340 std::vector<colvarvalue>::iterator &xv,
00341 std::vector<colvarvalue>::iterator const &xv_end,
00342 std::vector<cvm::real>::iterator &result);
00343
00346 static void p2leg_opt(colvarvalue const &x,
00347 std::list<colvarvalue>::iterator &xv,
00348 std::list<colvarvalue>::iterator const &xv_end,
00349 std::vector<cvm::real>::iterator &result);
00350
00351 };
00352
00353
00354 inline size_t colvarvalue::size() const
00355 {
00356 switch (value_type) {
00357 case colvarvalue::type_notset:
00358 default:
00359 return 0; break;
00360 case colvarvalue::type_scalar:
00361 return 1; break;
00362 case colvarvalue::type_3vector:
00363 case colvarvalue::type_unit3vector:
00364 case colvarvalue::type_unit3vectorderiv:
00365 return 3; break;
00366 case colvarvalue::type_quaternion:
00367 case colvarvalue::type_quaternionderiv:
00368 return 4; break;
00369 case colvarvalue::type_vector:
00370 return vector1d_value.size(); break;
00371 }
00372 }
00373
00374
00375 inline cvm::real colvarvalue::operator [] (int const i) const
00376 {
00377 switch (value_type) {
00378 case colvarvalue::type_notset:
00379 default:
00380 cvm::error("Error: trying to access a colvar value "
00381 "that is not initialized.\n", COLVARS_BUG_ERROR);
00382 return 0.0; break;
00383 case colvarvalue::type_scalar:
00384 return real_value; break;
00385 case colvarvalue::type_3vector:
00386 case colvarvalue::type_unit3vector:
00387 case colvarvalue::type_unit3vectorderiv:
00388 return rvector_value[i]; break;
00389 case colvarvalue::type_quaternion:
00390 case colvarvalue::type_quaternionderiv:
00391 return quaternion_value[i]; break;
00392 case colvarvalue::type_vector:
00393 return vector1d_value[i]; break;
00394 }
00395 }
00396
00397
00398 inline cvm::real & colvarvalue::operator [] (int const i)
00399 {
00400 switch (value_type) {
00401 case colvarvalue::type_notset:
00402 default:
00403 cvm::error("Error: trying to access a colvar value "
00404 "that is not initialized.\n", COLVARS_BUG_ERROR);
00405 return real_value; break;
00406 case colvarvalue::type_scalar:
00407 return real_value; break;
00408 case colvarvalue::type_3vector:
00409 case colvarvalue::type_unit3vector:
00410 case colvarvalue::type_unit3vectorderiv:
00411 return rvector_value[i]; break;
00412 case colvarvalue::type_quaternion:
00413 case colvarvalue::type_quaternionderiv:
00414 return quaternion_value[i]; break;
00415 case colvarvalue::type_vector:
00416 return vector1d_value[i]; break;
00417 }
00418 }
00419
00420
00421 inline int colvarvalue::check_types(colvarvalue const &x1,
00422 colvarvalue const &x2)
00423 {
00424 if (!colvarvalue::type_checking()) {
00425 return COLVARS_OK;
00426 }
00427
00428 if (x1.type() != x2.type()) {
00429 if (((x1.type() == type_unit3vector) &&
00430 (x2.type() == type_unit3vectorderiv)) ||
00431 ((x2.type() == type_unit3vector) &&
00432 (x1.type() == type_unit3vectorderiv)) ||
00433 ((x1.type() == type_quaternion) &&
00434 (x2.type() == type_quaternionderiv)) ||
00435 ((x2.type() == type_quaternion) &&
00436 (x1.type() == type_quaternionderiv))) {
00437 return COLVARS_OK;
00438 } else {
00439 cvm::error("Trying to perform an operation between two colvar "
00440 "values with different types, \""+
00441 colvarvalue::type_desc(x1.type())+
00442 "\" and \""+
00443 colvarvalue::type_desc(x2.type())+
00444 "\".\n");
00445 return COLVARS_ERROR;
00446 }
00447 }
00448
00449 if (x1.type() == type_vector) {
00450 if (x1.vector1d_value.size() != x2.vector1d_value.size()) {
00451 cvm::error("Trying to perform an operation between two vector colvar "
00452 "values with different sizes, "+
00453 cvm::to_str(x1.vector1d_value.size())+
00454 " and "+
00455 cvm::to_str(x2.vector1d_value.size())+
00456 ".\n");
00457 return COLVARS_ERROR;
00458 }
00459 }
00460 return COLVARS_OK;
00461 }
00462
00463
00464 inline int colvarvalue::check_types_assign(colvarvalue::Type const &vt1,
00465 colvarvalue::Type const &vt2)
00466 {
00467 if (!colvarvalue::type_checking()) {
00468 return COLVARS_OK;
00469 }
00470
00471 if (vt1 != type_notset) {
00472 if (((vt1 == type_unit3vector) &&
00473 (vt2 == type_unit3vectorderiv)) ||
00474 ((vt2 == type_unit3vector) &&
00475 (vt1 == type_unit3vectorderiv)) ||
00476 ((vt1 == type_quaternion) &&
00477 (vt2 == type_quaternionderiv)) ||
00478 ((vt2 == type_quaternion) &&
00479 (vt1 == type_quaternionderiv))) {
00480 return COLVARS_OK;
00481 } else {
00482 if (vt1 != vt2) {
00483 cvm::error("Trying to assign a colvar value with type \""+
00484 type_desc(vt2)+"\" to one with type \""+
00485 type_desc(vt1)+"\".\n");
00486 return COLVARS_ERROR;
00487 }
00488 }
00489 }
00490 return COLVARS_OK;
00491 }
00492
00493
00494 inline colvarvalue & colvarvalue::operator = (colvarvalue const &x)
00495 {
00496 check_types_assign(this->type(), x.type());
00497 value_type = x.type();
00498
00499 switch (this->type()) {
00500 case colvarvalue::type_scalar:
00501 this->real_value = x.real_value;
00502 break;
00503 case colvarvalue::type_3vector:
00504 case colvarvalue::type_unit3vector:
00505 case colvarvalue::type_unit3vectorderiv:
00506 this->rvector_value = x.rvector_value;
00507 break;
00508 case colvarvalue::type_quaternion:
00509 case colvarvalue::type_quaternionderiv:
00510 this->quaternion_value = x.quaternion_value;
00511 break;
00512 case colvarvalue::type_vector:
00513 vector1d_value = x.vector1d_value;
00514 elem_types = x.elem_types;
00515 elem_indices = x.elem_indices;
00516 elem_sizes = x.elem_sizes;
00517 break;
00518 case colvarvalue::type_notset:
00519 default:
00520 undef_op();
00521 break;
00522 }
00523 return *this;
00524 }
00525
00526
00527 inline void colvarvalue::operator += (colvarvalue const &x)
00528 {
00529 colvarvalue::check_types(*this, x);
00530
00531 switch (this->type()) {
00532 case colvarvalue::type_scalar:
00533 this->real_value += x.real_value;
00534 break;
00535 case colvarvalue::type_3vector:
00536 case colvarvalue::type_unit3vector:
00537 case colvarvalue::type_unit3vectorderiv:
00538 this->rvector_value += x.rvector_value;
00539 break;
00540 case colvarvalue::type_quaternion:
00541 case colvarvalue::type_quaternionderiv:
00542 this->quaternion_value += x.quaternion_value;
00543 break;
00544 case colvarvalue::type_vector:
00545 this->vector1d_value += x.vector1d_value;
00546 break;
00547 case colvarvalue::type_notset:
00548 default:
00549 undef_op();
00550 }
00551 }
00552
00553
00554 inline void colvarvalue::operator -= (colvarvalue const &x)
00555 {
00556 colvarvalue::check_types(*this, x);
00557
00558 switch (value_type) {
00559 case colvarvalue::type_scalar:
00560 real_value -= x.real_value;
00561 break;
00562 case colvarvalue::type_3vector:
00563 case colvarvalue::type_unit3vector:
00564 case colvarvalue::type_unit3vectorderiv:
00565 rvector_value -= x.rvector_value;
00566 break;
00567 case colvarvalue::type_quaternion:
00568 case colvarvalue::type_quaternionderiv:
00569 quaternion_value -= x.quaternion_value;
00570 break;
00571 case colvarvalue::type_vector:
00572 this->vector1d_value -= x.vector1d_value;
00573 break;
00574 case colvarvalue::type_notset:
00575 default:
00576 undef_op();
00577 }
00578 }
00579
00580
00581 inline void colvarvalue::operator *= (cvm::real const &a)
00582 {
00583 switch (value_type) {
00584 case colvarvalue::type_scalar:
00585 real_value *= a;
00586 break;
00587 case colvarvalue::type_3vector:
00588 case colvarvalue::type_unit3vectorderiv:
00589 rvector_value *= a;
00590 break;
00591 case colvarvalue::type_quaternion:
00592 case colvarvalue::type_quaternionderiv:
00593 quaternion_value *= a;
00594 break;
00595 case colvarvalue::type_vector:
00596 this->vector1d_value *= a;
00597 break;
00598 case colvarvalue::type_notset:
00599 default:
00600 undef_op();
00601 }
00602 }
00603
00604
00605 inline void colvarvalue::operator /= (cvm::real const &a)
00606 {
00607 switch (value_type) {
00608 case colvarvalue::type_scalar:
00609 real_value /= a; break;
00610 case colvarvalue::type_3vector:
00611 case colvarvalue::type_unit3vector:
00612 case colvarvalue::type_unit3vectorderiv:
00613 rvector_value /= a; break;
00614 case colvarvalue::type_quaternion:
00615 case colvarvalue::type_quaternionderiv:
00616 quaternion_value /= a; break;
00617 case colvarvalue::type_vector:
00618 this->vector1d_value /= a;
00619 break;
00620 case colvarvalue::type_notset:
00621 default:
00622 undef_op();
00623 }
00624 }
00625
00626
00627 inline cvm::vector1d<cvm::real> const colvarvalue::as_vector() const
00628 {
00629 switch (value_type) {
00630 case colvarvalue::type_scalar:
00631 {
00632 cvm::vector1d<cvm::real> v(1);
00633 v[0] = real_value;
00634 return v;
00635 }
00636 case colvarvalue::type_3vector:
00637 case colvarvalue::type_unit3vector:
00638 case colvarvalue::type_unit3vectorderiv:
00639 return rvector_value.as_vector();
00640 case colvarvalue::type_quaternion:
00641 case colvarvalue::type_quaternionderiv:
00642 return quaternion_value.as_vector();
00643 case colvarvalue::type_vector:
00644 return vector1d_value;
00645 case colvarvalue::type_notset:
00646 default:
00647 return cvm::vector1d<cvm::real>(0);
00648 }
00649 }
00650
00651
00652 inline cvm::real colvarvalue::norm2() const
00653 {
00654 switch (value_type) {
00655 case colvarvalue::type_scalar:
00656 return (this->real_value)*(this->real_value);
00657 case colvarvalue::type_3vector:
00658 case colvarvalue::type_unit3vector:
00659 case colvarvalue::type_unit3vectorderiv:
00660 return (this->rvector_value).norm2();
00661 case colvarvalue::type_quaternion:
00662 case colvarvalue::type_quaternionderiv:
00663 return (this->quaternion_value).norm2();
00664 case colvarvalue::type_vector:
00665 if (elem_types.size() > 0) {
00666
00667 cvm::real result = 0.0;
00668 size_t i;
00669 for (i = 0; i < elem_types.size(); i++) {
00670 result += (this->get_elem(i)).norm2();
00671 }
00672 return result;
00673 } else {
00674 return vector1d_value.norm2();
00675 }
00676 break;
00677 case colvarvalue::type_notset:
00678 default:
00679 return 0.0;
00680 }
00681 }
00682
00683
00684 inline cvm::real colvarvalue::sum() const
00685 {
00686 switch (value_type) {
00687 case colvarvalue::type_scalar:
00688 return (this->real_value);
00689 case colvarvalue::type_3vector:
00690 case colvarvalue::type_unit3vector:
00691 case colvarvalue::type_unit3vectorderiv:
00692 return (this->rvector_value).x + (this->rvector_value).y +
00693 (this->rvector_value).z;
00694 case colvarvalue::type_quaternion:
00695 case colvarvalue::type_quaternionderiv:
00696 return (this->quaternion_value).q0 + (this->quaternion_value).q1 +
00697 (this->quaternion_value).q2 + (this->quaternion_value).q3;
00698 case colvarvalue::type_vector:
00699 return (this->vector1d_value).sum();
00700 case colvarvalue::type_notset:
00701 default:
00702 return 0.0;
00703 }
00704 }
00705
00706
00707 inline cvm::real colvarvalue::dist2(colvarvalue const &x2) const
00708 {
00709 colvarvalue::check_types(*this, x2);
00710
00711 switch (this->type()) {
00712 case colvarvalue::type_scalar:
00713 return (this->real_value - x2.real_value)*(this->real_value - x2.real_value);
00714 case colvarvalue::type_3vector:
00715 return (this->rvector_value - x2.rvector_value).norm2();
00716 case colvarvalue::type_unit3vector:
00717 case colvarvalue::type_unit3vectorderiv:
00718
00719 return cvm::acos(this->rvector_value * x2.rvector_value) * cvm::acos(this->rvector_value * x2.rvector_value);
00720 case colvarvalue::type_quaternion:
00721 case colvarvalue::type_quaternionderiv:
00722
00723
00724 return this->quaternion_value.dist2(x2.quaternion_value);
00725 case colvarvalue::type_vector:
00726 return (this->vector1d_value - x2.vector1d_value).norm2();
00727 case colvarvalue::type_notset:
00728 default:
00729 this->undef_op();
00730 return 0.0;
00731 };
00732 }
00733
00734
00735 #endif