3
7
#include "colvarmodule.h"
4
8
#include "colvarvalue.h"
8
std::string const colvarvalue::type_desc[colvarvalue::type_quaternion+1] =
11
"3-dimensional vector",
12
"3-dimensional unit vector",
13
"4-dimensional unit vector" };
15
size_t const colvarvalue::dof_num[ colvarvalue::type_quaternion+1] =
19
void colvarvalue::undef_op() const
21
cvm::fatal_error ("Error: Undefined operation on a colvar of type \""+
22
colvarvalue::type_desc[this->value_type]+"\".\n");
25
void colvarvalue::error_rside
26
(colvarvalue::Type const &vt) const
28
cvm::fatal_error ("Trying to assign a colvar value with type \""+
29
type_desc[this->value_type]+"\" to one with type \""+
30
type_desc[vt]+"\".\n");
33
void colvarvalue::error_lside
34
(colvarvalue::Type const &vt) const
36
cvm::fatal_error ("Trying to use a colvar value with type \""+
37
type_desc[vt]+"\" as one of type \""+
38
type_desc[this->value_type]+"\".\n");
43
void colvarvalue::inner_opt (colvarvalue const &x,
44
std::vector<colvarvalue>::iterator &xv,
45
std::vector<colvarvalue>::iterator const &xv_end,
46
std::vector<cvm::real>::iterator &inner)
48
// doing type check only once, here
49
colvarvalue::check_types (x, *xv);
51
std::vector<colvarvalue>::iterator &xvi = xv;
52
std::vector<cvm::real>::iterator &ii = inner;
54
switch (x.value_type) {
55
case colvarvalue::type_scalar:
56
while (xvi != xv_end) {
57
*(ii++) += (xvi++)->real_value * x.real_value;
60
case colvarvalue::type_vector:
61
case colvarvalue::type_unitvector:
62
while (xvi != xv_end) {
63
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
66
case colvarvalue::type_quaternion:
67
while (xvi != xv_end) {
68
*(ii++) += ((xvi++)->quaternion_value).cosine (x.quaternion_value);
76
void colvarvalue::inner_opt (colvarvalue const &x,
77
std::list<colvarvalue>::iterator &xv,
78
std::list<colvarvalue>::iterator const &xv_end,
79
std::vector<cvm::real>::iterator &inner)
81
// doing type check only once, here
82
colvarvalue::check_types (x, *xv);
84
std::list<colvarvalue>::iterator &xvi = xv;
85
std::vector<cvm::real>::iterator &ii = inner;
87
switch (x.value_type) {
88
case colvarvalue::type_scalar:
89
while (xvi != xv_end) {
90
*(ii++) += (xvi++)->real_value * x.real_value;
93
case colvarvalue::type_vector:
94
case colvarvalue::type_unitvector:
95
while (xvi != xv_end) {
96
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
99
case colvarvalue::type_quaternion:
100
while (xvi != xv_end) {
101
*(ii++) += ((xvi++)->quaternion_value).cosine (x.quaternion_value);
110
void colvarvalue::p2leg_opt (colvarvalue const &x,
111
std::vector<colvarvalue>::iterator &xv,
112
std::vector<colvarvalue>::iterator const &xv_end,
113
std::vector<cvm::real>::iterator &inner)
115
// doing type check only once, here
116
colvarvalue::check_types (x, *xv);
118
std::vector<colvarvalue>::iterator &xvi = xv;
119
std::vector<cvm::real>::iterator &ii = inner;
121
switch (x.value_type) {
122
case colvarvalue::type_scalar:
123
cvm::fatal_error ("Error: cannot calculate Legendre polynomials "
124
"for scalar variables.\n");
126
case colvarvalue::type_vector:
127
while (xvi != xv_end) {
128
cvm::real const cosine =
129
((xvi)->rvector_value * x.rvector_value) /
130
((xvi)->rvector_value.norm() * x.rvector_value.norm());
132
*(ii++) += 1.5*cosine*cosine - 0.5;
135
case colvarvalue::type_unitvector:
136
while (xvi != xv_end) {
137
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
138
*(ii++) += 1.5*cosine*cosine - 0.5;
141
case colvarvalue::type_quaternion:
142
while (xvi != xv_end) {
143
cvm::real const cosine = (xvi++)->quaternion_value.cosine (x.quaternion_value);
144
*(ii++) += 1.5*cosine*cosine - 0.5;
152
void colvarvalue::p2leg_opt (colvarvalue const &x,
153
std::list<colvarvalue>::iterator &xv,
154
std::list<colvarvalue>::iterator const &xv_end,
155
std::vector<cvm::real>::iterator &inner)
157
// doing type check only once, here
158
colvarvalue::check_types (x, *xv);
160
std::list<colvarvalue>::iterator &xvi = xv;
161
std::vector<cvm::real>::iterator &ii = inner;
163
switch (x.value_type) {
164
case colvarvalue::type_scalar:
165
cvm::fatal_error ("Error: cannot calculate Legendre polynomials "
166
"for scalar variables.\n");
168
case colvarvalue::type_vector:
169
while (xvi != xv_end) {
170
cvm::real const cosine =
171
((xvi)->rvector_value * x.rvector_value) /
172
((xvi)->rvector_value.norm() * x.rvector_value.norm());
174
*(ii++) += 1.5*cosine*cosine - 0.5;
177
case colvarvalue::type_unitvector:
178
while (xvi != xv_end) {
179
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
180
*(ii++) += 1.5*cosine*cosine - 0.5;
183
case colvarvalue::type_quaternion:
184
while (xvi != xv_end) {
185
cvm::real const cosine = (xvi++)->quaternion_value.cosine (x.quaternion_value);
186
*(ii++) += 1.5*cosine*cosine - 0.5;
12
void colvarvalue::add_elem(colvarvalue const &x)
14
if (this->value_type != type_vector) {
15
cvm::error("Error: trying to set an element for a variable that is not set to be a vector.\n");
18
size_t const n = vector1d_value.size();
19
size_t const nd = num_dimensions(x.value_type);
20
elem_types.push_back(x.value_type);
21
elem_indices.push_back(n);
22
elem_sizes.push_back(nd);
23
vector1d_value.resize(n + nd);
28
colvarvalue const colvarvalue::get_elem(int const i_begin, int const i_end, Type const vt) const
30
if (vector1d_value.size() > 0) {
31
cvm::vector1d<cvm::real> const v(vector1d_value.slice(i_begin, i_end));
32
return colvarvalue(v, vt);
34
cvm::error("Error: trying to get an element from a variable that is not a vector.\n");
35
return colvarvalue(type_notset);
40
void colvarvalue::set_elem(int const i_begin, int const i_end, colvarvalue const &x)
42
if (vector1d_value.size() > 0) {
43
vector1d_value.sliceassign(i_begin, i_end, x.as_vector());
45
cvm::error("Error: trying to set an element for a variable that is not a vector.\n");
50
colvarvalue const colvarvalue::get_elem(int const icv) const
52
if (elem_types.size() > 0) {
53
return get_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv],
56
cvm::error("Error: trying to get a colvarvalue element from a vector colvarvalue that was initialized as a plain array.\n");
57
return colvarvalue(type_notset);
62
void colvarvalue::set_elem(int const icv, colvarvalue const &x)
64
if (elem_types.size() > 0) {
65
check_types_assign(elem_types[icv], x.value_type);
66
set_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv], x);
68
cvm::error("Error: trying to set a colvarvalue element for a colvarvalue that was initialized as a plain array.\n");
73
colvarvalue colvarvalue::inverse() const
76
case colvarvalue::type_scalar:
77
return colvarvalue(1.0/real_value);
79
case colvarvalue::type_3vector:
80
case colvarvalue::type_unit3vector:
81
case colvarvalue::type_unit3vectorderiv:
82
return colvarvalue(cvm::rvector(1.0/rvector_value.x,
84
1.0/rvector_value.z));
86
case colvarvalue::type_quaternion:
87
case colvarvalue::type_quaternionderiv:
88
return colvarvalue(cvm::quaternion(1.0/quaternion_value.q0,
89
1.0/quaternion_value.q1,
90
1.0/quaternion_value.q2,
91
1.0/quaternion_value.q3));
93
case colvarvalue::type_vector:
95
cvm::vector1d<cvm::real> result(vector1d_value);
96
if (elem_types.size() > 0) {
97
// if we have information about non-scalar types, use it
99
for (i = 0; i < elem_types.size(); i++) {
100
result.sliceassign(elem_indices[i], elem_indices[i]+elem_sizes[i],
101
cvm::vector1d<cvm::real>((this->get_elem(i)).inverse()));
105
for (i = 0; i < result.size(); i++) {
106
if (result[i] != 0.0) {
107
result = 1.0/result[i];
111
return colvarvalue(result, type_vector);
114
case colvarvalue::type_notset:
119
return colvarvalue();
123
// binary operations between two colvarvalues
125
colvarvalue operator + (colvarvalue const &x1,
126
colvarvalue const &x2)
128
colvarvalue::check_types(x1, x2);
130
switch (x1.value_type) {
131
case colvarvalue::type_scalar:
132
return colvarvalue(x1.real_value + x2.real_value);
133
case colvarvalue::type_3vector:
134
return colvarvalue(x1.rvector_value + x2.rvector_value);
135
case colvarvalue::type_unit3vector:
136
case colvarvalue::type_unit3vectorderiv:
137
return colvarvalue(x1.rvector_value + x2.rvector_value,
138
colvarvalue::type_unit3vector);
139
case colvarvalue::type_quaternion:
140
case colvarvalue::type_quaternionderiv:
141
return colvarvalue(x1.quaternion_value + x2.quaternion_value);
142
case colvarvalue::type_vector:
143
return colvarvalue(x1.vector1d_value + x2.vector1d_value, colvarvalue::type_vector);
144
case colvarvalue::type_notset:
147
return colvarvalue(colvarvalue::type_notset);
152
colvarvalue operator - (colvarvalue const &x1,
153
colvarvalue const &x2)
155
colvarvalue::check_types(x1, x2);
157
switch (x1.value_type) {
158
case colvarvalue::type_scalar:
159
return colvarvalue(x1.real_value - x2.real_value);
160
case colvarvalue::type_3vector:
161
return colvarvalue(x1.rvector_value - x2.rvector_value);
162
case colvarvalue::type_unit3vector:
163
case colvarvalue::type_unit3vectorderiv:
164
return colvarvalue(x1.rvector_value - x2.rvector_value,
165
colvarvalue::type_unit3vector);
166
case colvarvalue::type_quaternion:
167
case colvarvalue::type_quaternionderiv:
168
return colvarvalue(x1.quaternion_value - x2.quaternion_value);
169
case colvarvalue::type_vector:
170
return colvarvalue(x1.vector1d_value - x2.vector1d_value, colvarvalue::type_vector);
171
case colvarvalue::type_notset:
174
return colvarvalue(colvarvalue::type_notset);
179
// binary operations with real numbers
181
colvarvalue operator * (cvm::real const &a,
182
colvarvalue const &x)
184
switch (x.value_type) {
185
case colvarvalue::type_scalar:
186
return colvarvalue(a * x.real_value);
187
case colvarvalue::type_3vector:
188
return colvarvalue(a * x.rvector_value);
189
case colvarvalue::type_unit3vector:
190
case colvarvalue::type_unit3vectorderiv:
191
return colvarvalue(a * x.rvector_value,
192
colvarvalue::type_unit3vector);
193
case colvarvalue::type_quaternion:
194
case colvarvalue::type_quaternionderiv:
195
return colvarvalue(a * x.quaternion_value);
196
case colvarvalue::type_vector:
197
return colvarvalue(x.vector1d_value * a, colvarvalue::type_vector);
198
case colvarvalue::type_notset:
201
return colvarvalue(colvarvalue::type_notset);
206
colvarvalue operator * (colvarvalue const &x,
213
colvarvalue operator / (colvarvalue const &x,
216
switch (x.value_type) {
217
case colvarvalue::type_scalar:
218
return colvarvalue(x.real_value / a);
219
case colvarvalue::type_3vector:
220
return colvarvalue(x.rvector_value / a);
221
case colvarvalue::type_unit3vector:
222
case colvarvalue::type_unit3vectorderiv:
223
return colvarvalue(x.rvector_value / a,
224
colvarvalue::type_unit3vector);
225
case colvarvalue::type_quaternion:
226
case colvarvalue::type_quaternionderiv:
227
return colvarvalue(x.quaternion_value / a);
228
case colvarvalue::type_vector:
229
return colvarvalue(x.vector1d_value / a, colvarvalue::type_vector);
230
case colvarvalue::type_notset:
233
return colvarvalue(colvarvalue::type_notset);
238
// inner product between two colvarvalues
240
cvm::real operator * (colvarvalue const &x1,
241
colvarvalue const &x2)
243
colvarvalue::check_types(x1, x2);
245
switch (x1.value_type) {
246
case colvarvalue::type_scalar:
247
return (x1.real_value * x2.real_value);
248
case colvarvalue::type_3vector:
249
case colvarvalue::type_unit3vector:
250
case colvarvalue::type_unit3vectorderiv:
251
return (x1.rvector_value * x2.rvector_value);
252
case colvarvalue::type_quaternion:
253
case colvarvalue::type_quaternionderiv:
254
// the "*" product is the quaternion product, here the inner
255
// member function is used instead
256
return (x1.quaternion_value.inner(x2.quaternion_value));
257
case colvarvalue::type_vector:
258
return (x1.vector1d_value * x2.vector1d_value);
259
case colvarvalue::type_notset:
267
colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const
269
colvarvalue::check_types(*this, x2);
271
switch (this->value_type) {
272
case colvarvalue::type_scalar:
273
return 2.0 * (this->real_value - x2.real_value);
274
case colvarvalue::type_3vector:
275
return 2.0 * (this->rvector_value - x2.rvector_value);
276
case colvarvalue::type_unit3vector:
277
case colvarvalue::type_unit3vectorderiv:
279
cvm::rvector const &v1 = this->rvector_value;
280
cvm::rvector const &v2 = x2.rvector_value;
281
cvm::real const cos_t = v1 * v2;
282
cvm::real const sin_t = std::sqrt(1.0 - cos_t*cos_t);
283
return colvarvalue( 2.0 * sin_t *
284
cvm::rvector((-1.0) * sin_t * v2.x +
285
cos_t/sin_t * (v1.x - cos_t*v2.x),
286
(-1.0) * sin_t * v2.y +
287
cos_t/sin_t * (v1.y - cos_t*v2.y),
288
(-1.0) * sin_t * v2.z +
289
cos_t/sin_t * (v1.z - cos_t*v2.z)
291
colvarvalue::type_unit3vector );
293
case colvarvalue::type_quaternion:
294
case colvarvalue::type_quaternionderiv:
295
return this->quaternion_value.dist2_grad(x2.quaternion_value);
296
case colvarvalue::type_vector:
297
return colvarvalue(2.0 * (this->vector1d_value - x2.vector1d_value), colvarvalue::type_vector);
299
case colvarvalue::type_notset:
302
return colvarvalue(colvarvalue::type_notset);
307
std::string colvarvalue::to_simple_string() const
310
case colvarvalue::type_scalar:
311
return cvm::to_str(real_value, 0, cvm::cv_prec);
313
case colvarvalue::type_3vector:
314
case colvarvalue::type_unit3vector:
315
case colvarvalue::type_unit3vectorderiv:
316
return rvector_value.to_simple_string();
318
case colvarvalue::type_quaternion:
319
case colvarvalue::type_quaternionderiv:
320
return quaternion_value.to_simple_string();
322
case colvarvalue::type_vector:
323
return vector1d_value.to_simple_string();
325
case colvarvalue::type_notset:
330
return std::string();
334
int colvarvalue::from_simple_string(std::string const &s)
337
case colvarvalue::type_scalar:
338
return ((std::istringstream(s) >> real_value)
339
? COLVARS_OK : COLVARS_ERROR);
341
case colvarvalue::type_3vector:
342
case colvarvalue::type_unit3vector:
343
case colvarvalue::type_unit3vectorderiv:
344
return rvector_value.from_simple_string(s);
346
case colvarvalue::type_quaternion:
347
case colvarvalue::type_quaternionderiv:
348
return quaternion_value.from_simple_string(s);
350
case colvarvalue::type_vector:
351
return vector1d_value.from_simple_string(s);
353
case colvarvalue::type_notset:
358
return COLVARS_ERROR;
195
361
std::ostream & operator << (std::ostream &os, colvarvalue const &x)
197
363
switch (x.type()) {
198
364
case colvarvalue::type_scalar:
199
os << x.real_value; break;
367
case colvarvalue::type_3vector:
368
case colvarvalue::type_unit3vector:
369
case colvarvalue::type_unit3vectorderiv:
370
os << x.rvector_value;
372
case colvarvalue::type_quaternion:
373
case colvarvalue::type_quaternionderiv:
374
os << x.quaternion_value;
200
376
case colvarvalue::type_vector:
201
case colvarvalue::type_unitvector:
202
os << x.rvector_value; break;
203
case colvarvalue::type_quaternion:
204
os << x.quaternion_value; break;
377
os << x.vector1d_value;
205
379
case colvarvalue::type_notset:
206
os << "not set"; break;
458
void colvarvalue::inner_opt(colvarvalue const &x,
459
std::vector<colvarvalue>::iterator &xv,
460
std::vector<colvarvalue>::iterator const &xv_end,
461
std::vector<cvm::real>::iterator &result)
463
// doing type check only once, here
464
colvarvalue::check_types(x, *xv);
466
std::vector<colvarvalue>::iterator &xvi = xv;
467
std::vector<cvm::real>::iterator &ii = result;
469
switch (x.value_type) {
470
case colvarvalue::type_scalar:
471
while (xvi != xv_end) {
472
*(ii++) += (xvi++)->real_value * x.real_value;
475
case colvarvalue::type_3vector:
476
case colvarvalue::type_unit3vector:
477
case colvarvalue::type_unit3vectorderiv:
478
while (xvi != xv_end) {
479
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
482
case colvarvalue::type_quaternion:
483
case colvarvalue::type_quaternionderiv:
484
while (xvi != xv_end) {
485
*(ii++) += ((xvi++)->quaternion_value).cosine(x.quaternion_value);
488
case colvarvalue::type_vector:
489
while (xvi != xv_end) {
490
*(ii++) += (xvi++)->vector1d_value * x.vector1d_value;
499
void colvarvalue::inner_opt(colvarvalue const &x,
500
std::list<colvarvalue>::iterator &xv,
501
std::list<colvarvalue>::iterator const &xv_end,
502
std::vector<cvm::real>::iterator &result)
504
// doing type check only once, here
505
colvarvalue::check_types(x, *xv);
507
std::list<colvarvalue>::iterator &xvi = xv;
508
std::vector<cvm::real>::iterator &ii = result;
510
switch (x.value_type) {
511
case colvarvalue::type_scalar:
512
while (xvi != xv_end) {
513
*(ii++) += (xvi++)->real_value * x.real_value;
516
case colvarvalue::type_3vector:
517
case colvarvalue::type_unit3vector:
518
case colvarvalue::type_unit3vectorderiv:
519
while (xvi != xv_end) {
520
*(ii++) += (xvi++)->rvector_value * x.rvector_value;
523
case colvarvalue::type_quaternion:
524
case colvarvalue::type_quaternionderiv:
525
while (xvi != xv_end) {
526
*(ii++) += ((xvi++)->quaternion_value).cosine(x.quaternion_value);
529
case colvarvalue::type_vector:
530
while (xvi != xv_end) {
531
*(ii++) += (xvi++)->vector1d_value * x.vector1d_value;
540
void colvarvalue::p2leg_opt(colvarvalue const &x,
541
std::vector<colvarvalue>::iterator &xv,
542
std::vector<colvarvalue>::iterator const &xv_end,
543
std::vector<cvm::real>::iterator &result)
545
// doing type check only once, here
546
colvarvalue::check_types(x, *xv);
548
std::vector<colvarvalue>::iterator &xvi = xv;
549
std::vector<cvm::real>::iterator &ii = result;
551
switch (x.value_type) {
552
case colvarvalue::type_scalar:
553
cvm::error("Error: cannot calculate Legendre polynomials "
554
"for scalar variables.\n");
557
case colvarvalue::type_3vector:
558
while (xvi != xv_end) {
559
cvm::real const cosine =
560
((xvi)->rvector_value * x.rvector_value) /
561
((xvi)->rvector_value.norm() * x.rvector_value.norm());
563
*(ii++) += 1.5*cosine*cosine - 0.5;
566
case colvarvalue::type_unit3vector:
567
case colvarvalue::type_unit3vectorderiv:
568
while (xvi != xv_end) {
569
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
570
*(ii++) += 1.5*cosine*cosine - 0.5;
573
case colvarvalue::type_quaternion:
574
case colvarvalue::type_quaternionderiv:
575
while (xvi != xv_end) {
576
cvm::real const cosine = (xvi++)->quaternion_value.cosine(x.quaternion_value);
577
*(ii++) += 1.5*cosine*cosine - 0.5;
580
case colvarvalue::type_vector:
581
while (xvi != xv_end) {
582
cvm::real const cosine =
583
((xvi)->vector1d_value * x.vector1d_value) /
584
((xvi)->vector1d_value.norm() * x.rvector_value.norm());
586
*(ii++) += 1.5*cosine*cosine - 0.5;
595
void colvarvalue::p2leg_opt(colvarvalue const &x,
596
std::list<colvarvalue>::iterator &xv,
597
std::list<colvarvalue>::iterator const &xv_end,
598
std::vector<cvm::real>::iterator &result)
600
// doing type check only once, here
601
colvarvalue::check_types(x, *xv);
603
std::list<colvarvalue>::iterator &xvi = xv;
604
std::vector<cvm::real>::iterator &ii = result;
606
switch (x.value_type) {
607
case colvarvalue::type_scalar:
608
cvm::error("Error: cannot calculate Legendre polynomials "
609
"for scalar variables.\n");
611
case colvarvalue::type_3vector:
612
while (xvi != xv_end) {
613
cvm::real const cosine =
614
((xvi)->rvector_value * x.rvector_value) /
615
((xvi)->rvector_value.norm() * x.rvector_value.norm());
617
*(ii++) += 1.5*cosine*cosine - 0.5;
620
case colvarvalue::type_unit3vector:
621
case colvarvalue::type_unit3vectorderiv:
622
while (xvi != xv_end) {
623
cvm::real const cosine = (xvi++)->rvector_value * x.rvector_value;
624
*(ii++) += 1.5*cosine*cosine - 0.5;
627
case colvarvalue::type_quaternion:
628
case colvarvalue::type_quaternionderiv:
629
while (xvi != xv_end) {
630
cvm::real const cosine = (xvi++)->quaternion_value.cosine(x.quaternion_value);
631
*(ii++) += 1.5*cosine*cosine - 0.5;