Collective Variables Module - Developer Documentation
Loading...
Searching...
No Matches
colvartypes.h
1// -*- c++ -*-
2
3// This file is part of the Collective Variables module (Colvars).
4// The original version of Colvars and its updates are located at:
5// https://github.com/Colvars/colvars
6// Please update all Colvars source files before making any changes.
7// If you wish to distribute your changes, please submit them to the
8// Colvars repository at GitHub.
9
10#ifndef COLVARTYPES_H
11#define COLVARTYPES_H
12
13#include "colvar_gpu_support.h"
14#include <sstream> // TODO specialize templates and replace this with iosfwd
15#include <vector>
16#include <array>
17#include <unordered_map>
18
19#ifdef COLVARS_LAMMPS
20// Use open-source Jacobi implementation
21#include "math_eigen_impl.h"
22#endif
23
24#include "colvarmodule.h"
25
26// ----------------------------------------------------------------------
29// ----------------------------------------------------------------------
30
31
35template <class T> class colvarmodule::vector1d
36{
37protected:
38
39 std::vector<T> data;
40
41public:
42
44 inline vector1d(size_t const n = 0)
45 {
46 data.resize(n);
47 reset();
48 }
49
51 inline vector1d(size_t const n, T const *t)
52 {
53 data.resize(n);
54 reset();
55 size_t i;
56 for (i = 0; i < size(); i++) {
57 data[i] = t[i];
58 }
59 }
60
62 inline vector1d(const vector1d&) = default;
63
65 inline vector1d& operator=(const vector1d&) = default;
66
68 inline T * c_array()
69 {
70 if (data.size() > 0) {
71 return &(data[0]);
72 } else {
73 return NULL;
74 }
75 }
76
78 inline std::vector<T> &data_array()
79 {
80 return data;
81 }
82
84 inline std::vector<T> const &data_array() const
85 {
86 return data;
87 }
88
89 inline ~vector1d()
90 {
91 data.clear();
92 }
93
95 inline void reset()
96 {
97 data.assign(data.size(), T(0.0));
98 }
99
100 inline size_t size() const
101 {
102 return data.size();
103 }
104
105 inline void resize(size_t const n)
106 {
107 data.resize(n);
108 }
109
110 inline void clear()
111 {
112 data.clear();
113 }
114
115 inline T & operator [] (size_t const i) {
116 return data[i];
117 }
118
119 inline T const & operator [] (size_t const i) const {
120 return data[i];
121 }
122
123 inline static void check_sizes(vector1d<T> const &v1, vector1d<T> const &v2)
124 {
125 if (v1.size() != v2.size()) {
126 cvm::error_static("Error: trying to perform an operation between vectors of different sizes, "+
127 cvm::to_str(v1.size())+" and "+cvm::to_str(v2.size())+".\n");
128 }
129 }
130
131 inline void operator += (vector1d<T> const &v)
132 {
133 check_sizes(*this, v);
134 size_t i;
135 for (i = 0; i < this->size(); i++) {
136 (*this)[i] += v[i];
137 }
138 }
139
140 inline void operator -= (vector1d<T> const &v)
141 {
142 check_sizes(*this, v);
143 size_t i;
144 for (i = 0; i < this->size(); i++) {
145 (*this)[i] -= v[i];
146 }
147 }
148
149 inline void operator *= (cvm::real a)
150 {
151 size_t i;
152 for (i = 0; i < this->size(); i++) {
153 (*this)[i] *= a;
154 }
155 }
156
157 inline void operator /= (cvm::real a)
158 {
159 size_t i;
160 for (i = 0; i < this->size(); i++) {
161 (*this)[i] /= a;
162 }
163 }
164
165 inline friend vector1d<T> operator + (vector1d<T> const &v1,
166 vector1d<T> const &v2)
167 {
168 check_sizes(v1.size(), v2.size());
169 vector1d<T> result(v1.size());
170 size_t i;
171 for (i = 0; i < v1.size(); i++) {
172 result[i] = v1[i] + v2[i];
173 }
174 return result;
175 }
176
177 inline friend vector1d<T> operator - (vector1d<T> const &v1,
178 vector1d<T> const &v2)
179 {
180 check_sizes(v1.size(), v2.size());
181 vector1d<T> result(v1.size());
182 size_t i;
183 for (i = 0; i < v1.size(); i++) {
184 result[i] = v1[i] - v2[i];
185 }
186 return result;
187 }
188
189 inline friend vector1d<T> operator * (vector1d<T> const &v, cvm::real a)
190 {
191 vector1d<T> result(v.size());
192 size_t i;
193 for (i = 0; i < v.size(); i++) {
194 result[i] = v[i] * a;
195 }
196 return result;
197 }
198
199 inline friend vector1d<T> operator * (cvm::real a, vector1d<T> const &v)
200 {
201 return v * a;
202 }
203
204 inline friend vector1d<T> operator / (vector1d<T> const &v, cvm::real a)
205 {
206 vector1d<T> result(v.size());
207 size_t i;
208 for (i = 0; i < v.size(); i++) {
209 result[i] = v[i] / a;
210 }
211 return result;
212 }
213
215 inline friend T operator * (vector1d<T> const &v1, vector1d<T> const &v2)
216 {
217 check_sizes(v1.size(), v2.size());
218 T prod(0.0);
219 size_t i;
220 for (i = 0; i < v1.size(); i++) {
221 prod += v1[i] * v2[i];
222 }
223 return prod;
224 }
225
227 inline cvm::real norm2() const
228 {
229 cvm::real result = 0.0;
230 size_t i;
231 for (i = 0; i < this->size(); i++) {
232 result += (*this)[i] * (*this)[i];
233 }
234 return result;
235 }
236
237 inline cvm::real norm() const
238 {
239 return cvm::sqrt(this->norm2());
240 }
241
242 inline cvm::real sum() const
243 {
244 cvm::real result = 0.0;
245 size_t i;
246 for (i = 0; i < this->size(); i++) {
247 result += (*this)[i];
248 }
249 return result;
250 }
251
253 inline vector1d<T> const slice(size_t const i1, size_t const i2) const
254 {
255 if ((i2 < i1) || (i2 >= this->size())) {
256 cvm::error_static("Error: trying to slice a vector using incorrect boundaries.\n");
257 }
258 vector1d<T> result(i2 - i1);
259 size_t i;
260 for (i = 0; i < (i2 - i1); i++) {
261 result[i] = (*this)[i1+i];
262 }
263 return result;
264 }
265
267 inline void sliceassign(size_t const i1, size_t const i2,
268 vector1d<T> const &v)
269 {
270 if ((i2 < i1) || (i2 >= this->size())) {
271 cvm::error_static("Error: trying to slice a vector using incorrect boundaries.\n");
272 }
273 size_t i;
274 for (i = 0; i < (i2 - i1); i++) {
275 (*this)[i1+i] = v[i];
276 }
277 }
278
280
281 inline size_t output_width(size_t real_width) const
282 {
283 return real_width*(this->size()) + 3*(this->size()-1) + 4;
284 }
285
286 inline friend std::istream & operator >> (std::istream &is,
288 {
289 if (v.size() == 0) return is;
290 std::streampos const start_pos = is.tellg();
291 char sep;
292 if ( !(is >> sep) || !(sep == '(') ) {
293 is.clear();
294 is.seekg(start_pos, std::ios::beg);
295 is.setstate(std::ios::failbit);
296 return is;
297 }
298 size_t count = 0;
299 while ( (is >> v[count]) &&
300 (count < (v.size()-1) ? ((is >> sep) && (sep == ',')) : true) ) {
301 if (++count == v.size()) break;
302 }
303 if (count < v.size()) {
304 is.clear();
305 is.seekg(start_pos, std::ios::beg);
306 is.setstate(std::ios::failbit);
307 }
308 return is;
309 }
310
311 inline friend std::ostream & operator << (std::ostream &os,
312 cvm::vector1d<T> const &v)
313 {
314 std::streamsize const w = os.width();
315 std::streamsize const p = os.precision();
316
317 os.width(2);
318 os << "( ";
319 size_t i;
320 for (i = 0; i < v.size()-1; i++) {
321 os.width(w); os.precision(p);
322 os << v[i] << " , ";
323 }
324 os.width(w); os.precision(p);
325 os << v[v.size()-1] << " )";
326 return os;
327 }
328
329 inline std::string to_simple_string() const
330 {
331 if (this->size() == 0) return std::string("");
332 std::ostringstream os;
333 os.setf(std::ios::scientific, std::ios::floatfield);
334 // os.precision(cvmodule->cv_prec);
335 os.precision(14);
336 os << (*this)[0];
337 size_t i;
338 for (i = 1; i < this->size(); i++) {
339 os << " " << (*this)[i];
340 }
341 return os.str();
342 }
343
344 inline int from_simple_string(std::string const &s)
345 {
346 std::stringstream stream(s);
347 size_t i = 0;
348 if (this->size()) {
349 while ((i < this->size()) && (stream >> (*this)[i])) {
350 i++;
351 }
352 if (i < this->size()) {
353 return COLVARS_ERROR;
354 }
355 } else {
356 T input;
357 while (stream >> input) {
358 if ((i % 100) == 0) {
359 data.reserve(data.size()+100);
360 }
361 data.resize(data.size()+1);
362 data[i] = input;
363 i++;
364 }
365 }
366 return COLVARS_OK;
367 }
368
369};
370
371
375template <class T> class colvarmodule::matrix2d
376{
377public:
378
379 friend class row;
380 size_t outer_length;
381 size_t inner_length;
382
383protected:
384
385 class row {
386 public:
387 T * data;
388 size_t length;
389 inline row(T * const row_data, size_t const inner_length)
390 : data(row_data), length(inner_length)
391 {}
392 inline T & operator [] (size_t const j) {
393 return *(data+j);
394 }
395 inline T const & operator [] (size_t const j) const {
396 return *(data+j);
397 }
398 inline operator vector1d<T>() const
399 {
400 return vector1d<T>(length, data);
401 }
402 inline int set(cvm::vector1d<T> const &v) const
403 {
404 if (v.size() != length) {
405 return cvm::error_static("Error: setting a matrix row from a vector of "
406 "incompatible size.\n", COLVARS_BUG_ERROR);
407 }
408 for (size_t i = 0; i < length; i++) data[i] = v[i];
409 return COLVARS_OK;
410 }
411 };
412
413 std::vector<T> data;
414 std::vector<row> rows;
415 std::vector<T *> pointers;
416
417public:
418
420 inline void resize(size_t const ol, size_t const il)
421 {
422 if ((ol > 0) && (il > 0)) {
423
424 if (data.size() > 0) {
425 // copy previous data
426 size_t i, j;
427 std::vector<T> new_data(ol * il);
428 for (i = 0; i < outer_length; i++) {
429 for (j = 0; j < inner_length; j++) {
430 new_data[il*i+j] = data[inner_length*i+j];
431 }
432 }
433 data.resize(ol * il);
434 // copy them back
435 data = new_data;
436 } else {
437 data.resize(ol * il);
438 }
439
440 outer_length = ol;
441 inner_length = il;
442
443 if (data.size() > 0) {
444 // rebuild rows
445 size_t i;
446 rows.clear();
447 rows.reserve(outer_length);
448 pointers.clear();
449 pointers.reserve(outer_length);
450 for (i = 0; i < outer_length; i++) {
451 rows.push_back(row(&(data[0])+inner_length*i, inner_length));
452 pointers.push_back(&(data[0])+inner_length*i);
453 }
454 }
455 } else {
456 // zero size
457 data.clear();
458 rows.clear();
459 }
460 }
461
463 inline void clear() {
464 rows.clear();
465 data.clear();
466 }
467
469 inline void reset()
470 {
471 data.assign(data.size(), T(0.0));
472 }
473
474 inline size_t size() const
475 {
476 return data.size();
477 }
478
480 inline matrix2d()
481 : outer_length(0), inner_length(0)
482 {
483 this->resize(0, 0);
484 }
485
486 inline matrix2d(size_t const ol, size_t const il)
487 : outer_length(ol), inner_length(il)
488 {
489 this->resize(outer_length, inner_length);
490 reset();
491 }
492
494 inline matrix2d(matrix2d<T> const &m)
495 : outer_length(m.outer_length), inner_length(m.inner_length)
496 {
497 // reinitialize data and rows arrays
498 this->resize(outer_length, inner_length);
499 // copy data
500 data = m.data;
501 }
502
504 inline ~matrix2d() {
505 this->clear();
506 }
507
509 inline std::vector<T> &data_array()
510 {
511 return data;
512 }
513
515 inline std::vector<T> const &data_array() const
516 {
517 return data;
518 }
519
520 inline row & operator [] (size_t const i)
521 {
522 return rows[i];
523 }
524 inline row const & operator [] (size_t const i) const
525 {
526 return rows[i];
527 }
528
531 {
532 if ((outer_length != m.outer_length) || (inner_length != m.inner_length)){
533 this->clear();
534 outer_length = m.outer_length;
535 inner_length = m.inner_length;
536 this->resize(outer_length, inner_length);
537 }
538 data = m.data;
539 return *this;
540 }
541
543 inline T ** c_array() {
544 if (rows.size() > 0) {
545 return &(pointers[0]);
546 } else {
547 return NULL;
548 }
549 }
550
551 inline static void check_sizes(matrix2d<T> const &m1, matrix2d<T> const &m2)
552 {
553 if ((m1.outer_length != m2.outer_length) ||
554 (m1.inner_length != m2.inner_length)) {
555 cvm::error_static("Error: trying to perform an operation between "
556 "matrices of different sizes, "+
557 cvm::to_str(m1.outer_length)+"x"+
558 cvm::to_str(m1.inner_length)+" and "+
559 cvm::to_str(m2.outer_length)+"x"+
560 cvm::to_str(m2.inner_length)+".\n");
561 }
562 }
563
564 inline void operator += (matrix2d<T> const &m)
565 {
566 check_sizes(*this, m);
567 size_t i;
568 for (i = 0; i < data.size(); i++) {
569 data[i] += m.data[i];
570 }
571 }
572
573 inline void operator -= (matrix2d<T> const &m)
574 {
575 check_sizes(*this, m);
576 size_t i;
577 for (i = 0; i < data.size(); i++) {
578 data[i] -= m.data[i];
579 }
580 }
581
582 inline void operator *= (cvm::real a)
583 {
584 size_t i;
585 for (i = 0; i < data.size(); i++) {
586 data[i] *= a;
587 }
588 }
589
590 inline void operator /= (cvm::real a)
591 {
592 size_t i;
593 for (i = 0; i < data.size(); i++) {
594 data[i] /= a;
595 }
596 }
597
598 inline friend matrix2d<T> operator + (matrix2d<T> const &m1,
599 matrix2d<T> const &m2)
600 {
601 check_sizes(m1, m2);
602 matrix2d<T> result(m1.outer_length, m1.inner_length);
603 size_t i;
604 for (i = 0; i < m1.data.size(); i++) {
605 result.data[i] = m1.data[i] + m2.data[i];
606 }
607 return result;
608 }
609
610 inline friend matrix2d<T> operator - (matrix2d<T> const &m1,
611 matrix2d<T> const &m2)
612 {
613 check_sizes(m1, m2);
614 matrix2d<T> result(m1.outer_length, m1.inner_length);
615 size_t i;
616 for (i = 0; i < m1.data.size(); i++) {
617 result.data[i] = m1.data[i] - m1.data[i];
618 }
619 return result;
620 }
621
622 inline friend matrix2d<T> operator * (matrix2d<T> const &m, cvm::real a)
623 {
624 matrix2d<T> result(m.outer_length, m.inner_length);
625 size_t i;
626 for (i = 0; i < m.data.size(); i++) {
627 result.data[i] = m.data[i] * a;
628 }
629 return result;
630 }
631
632 inline friend matrix2d<T> operator * (cvm::real a, matrix2d<T> const &m)
633 {
634 return m * a;
635 }
636
637 inline friend matrix2d<T> operator / (matrix2d<T> const &m, cvm::real a)
638 {
639 matrix2d<T> result(m.outer_length, m.inner_length);
640 size_t i;
641 for (i = 0; i < m.data.size(); i++) {
642 result.data[i] = m.data[i] * a;
643 }
644 return result;
645 }
646
648 inline friend vector1d<T> operator * (vector1d<T> const &v,
649 matrix2d<T> const &m)
650 {
651 vector1d<T> result(m.inner_length);
652 if (m.outer_length != v.size()) {
653 cvm::error_static("Error: trying to multiply a vector and a matrix "
654 "of incompatible sizes, "+
655 cvm::to_str(v.size()) + " and " +
656 cvm::to_str(m.outer_length)+"x"+cvm::to_str(m.inner_length) +
657 ".\n");
658 } else {
659 size_t i, k;
660 for (i = 0; i < m.inner_length; i++) {
661 for (k = 0; k < m.outer_length; k++) {
662 result[i] += m[k][i] * v[k];
663 }
664 }
665 }
666 return result;
667 }
668
670 friend std::ostream & operator << (std::ostream &os,
671 matrix2d<T> const &m)
672 {
673 std::streamsize const w = os.width();
674 std::streamsize const p = os.precision();
675
676 os.width(2);
677 os << "( ";
678 size_t i;
679 for (i = 0; i < m.outer_length; i++) {
680 os << " ( ";
681 size_t j;
682 for (j = 0; j < m.inner_length-1; j++) {
683 os.width(w);
684 os.precision(p);
685 os << m[i][j] << " , ";
686 }
687 os.width(w);
688 os.precision(p);
689 os << m[i][m.inner_length-1] << " )";
690 }
691
692 os << " )";
693 return os;
694 }
695
696 inline std::string to_simple_string() const
697 {
698 if (this->size() == 0) return std::string("");
699 std::ostringstream os;
700 os.setf(std::ios::scientific, std::ios::floatfield);
701 // os.precision(cvmodule->cv_prec);
702 os.precision(14);
703 os << (*this)[0];
704 size_t i;
705 for (i = 1; i < data.size(); i++) {
706 os << " " << data[i];
707 }
708 return os.str();
709 }
710
711 inline int from_simple_string(std::string const &s)
712 {
713 std::stringstream stream(s);
714 size_t i = 0;
715 while ((i < data.size()) && (stream >> data[i])) {
716 i++;
717 }
718 if (i < data.size()) {
719 return COLVARS_ERROR;
720 }
721 return COLVARS_OK;
722 }
723
724};
725
726
729
730public:
731
732 cvm::real x, y, z;
733
734 inline COLVARS_HOST_DEVICE rvector()
735 {
736 reset();
737 }
738
740 inline COLVARS_HOST_DEVICE void reset()
741 {
742 set(0.0);
743 }
744
745 inline COLVARS_HOST_DEVICE rvector(cvm::real x_i, cvm::real y_i, cvm::real z_i)
746 {
747 set(x_i, y_i, z_i);
748 }
749
750 inline rvector(cvm::vector1d<cvm::real> const &v)
751 {
752 set(v[0], v[1], v[2]);
753 }
754
755 inline COLVARS_HOST_DEVICE rvector(cvm::real t)
756 {
757 set(t);
758 }
759
761 inline COLVARS_HOST_DEVICE void set(cvm::real value)
762 {
763 x = y = z = value;
764 }
765
767 inline COLVARS_HOST_DEVICE void set(cvm::real x_i, cvm::real y_i, cvm::real z_i)
768 {
769 x = x_i;
770 y = y_i;
771 z = z_i;
772 }
773
775 inline COLVARS_HOST_DEVICE cvm::real & operator [] (int i) {
776 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
777 }
778
780 inline COLVARS_HOST_DEVICE cvm::real operator [] (int i) const {
781 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
782 }
783
784 inline cvm::vector1d<cvm::real> const as_vector() const
785 {
786 cvm::vector1d<cvm::real> result(3);
787 result[0] = this->x;
788 result[1] = this->y;
789 result[2] = this->z;
790 return result;
791 }
792
793 inline COLVARS_HOST_DEVICE void operator += (cvm::rvector const &v)
794 {
795 x += v.x;
796 y += v.y;
797 z += v.z;
798 }
799
800 inline COLVARS_HOST_DEVICE void operator -= (cvm::rvector const &v)
801 {
802 x -= v.x;
803 y -= v.y;
804 z -= v.z;
805 }
806
807 inline COLVARS_HOST_DEVICE void operator *= (cvm::real v)
808 {
809 x *= v;
810 y *= v;
811 z *= v;
812 }
813
814 inline COLVARS_HOST_DEVICE void operator /= (cvm::real const& v)
815 {
816 x /= v;
817 y /= v;
818 z /= v;
819 }
820
821 inline COLVARS_HOST_DEVICE cvm::real norm2() const
822 {
823 return (x*x + y*y + z*z);
824 }
825
826 inline COLVARS_HOST_DEVICE cvm::real norm() const
827 {
828#if (defined(__HIP_DEVICE_COMPILE__)) || (defined (__CUDA_ARCH__))
829#define COLVARS_MATH_SQRT ::sqrt
830#else
831#define COLVARS_MATH_SQRT cvm::sqrt
832#endif
833 return COLVARS_MATH_SQRT(this->norm2());
834#undef COLVARS_MATH_SQRT
835 }
836
837 inline COLVARS_HOST_DEVICE cvm::rvector unit() const
838 {
839 const cvm::real n = this->norm();
840 return (n > 0. ? cvm::rvector(x, y, z)/n : cvm::rvector(1., 0., 0.));
841 }
842
843 static inline size_t output_width(size_t real_width)
844 {
845 return 3*real_width + 10;
846 }
847
848
849 static inline COLVARS_HOST_DEVICE
850 cvm::rvector outer(cvm::rvector const &v1,
851 cvm::rvector const &v2)
852 {
853 return cvm::rvector( v1.y*v2.z - v2.y*v1.z,
854 -v1.x*v2.z + v2.x*v1.z,
855 v1.x*v2.y - v2.x*v1.y);
856 }
857
858 friend inline COLVARS_HOST_DEVICE cvm::rvector operator - (cvm::rvector const &v)
859 {
860 return cvm::rvector(-v.x, -v.y, -v.z);
861 }
862
863 friend inline COLVARS_HOST_DEVICE cvm::rvector operator + (cvm::rvector const &v1,
864 cvm::rvector const &v2)
865 {
866 return cvm::rvector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
867 }
868 friend inline COLVARS_HOST_DEVICE cvm::rvector operator - (cvm::rvector const &v1,
869 cvm::rvector const &v2)
870 {
871 return cvm::rvector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
872 }
873
875 friend inline COLVARS_HOST_DEVICE cvm::real operator * (cvm::rvector const &v1,
876 cvm::rvector const &v2)
877 {
878 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
879 }
880
881 friend inline COLVARS_HOST_DEVICE cvm::rvector operator * (cvm::real a, cvm::rvector const &v)
882 {
883 return cvm::rvector(a*v.x, a*v.y, a*v.z);
884 }
885
886 friend inline COLVARS_HOST_DEVICE cvm::rvector operator * (cvm::rvector const &v, cvm::real a)
887 {
888 return cvm::rvector(a*v.x, a*v.y, a*v.z);
889 }
890
891 friend inline COLVARS_HOST_DEVICE cvm::rvector operator / (cvm::rvector const &v, cvm::real a)
892 {
893 return cvm::rvector(v.x/a, v.y/a, v.z/a);
894 }
895
896 std::string to_simple_string() const;
897 int from_simple_string(std::string const &s);
898};
899
900
904
905public:
906
907 cvm::real xx, xy, xz, yx, yy, yz, zx, zy, zz;
908
910 inline COLVARS_HOST_DEVICE rmatrix()
911 {
912 reset();
913 }
914
916 inline COLVARS_HOST_DEVICE
918 cvm::real yxi, cvm::real yyi, cvm::real yzi,
919 cvm::real zxi, cvm::real zyi, cvm::real zzi)
920 {
921 xx = xxi;
922 xy = xyi;
923 xz = xzi;
924 yx = yxi;
925 yy = yyi;
926 yz = yzi;
927 zx = zxi;
928 zy = zyi;
929 zz = zzi;
930 }
931
932
933 inline COLVARS_HOST_DEVICE void reset()
934 {
935 xx = xy = xz = yx = yy = yz = zx = zy = zz = 0.0;
936 }
937
939 inline COLVARS_HOST_DEVICE cvm::real determinant() const
940 {
941 return
942 ( xx * (yy*zz - zy*yz))
943 - (yx * (xy*zz - zy*xz))
944 + (zx * (xy*yz - yy*xz));
945 }
946
947 inline COLVARS_HOST_DEVICE cvm::rmatrix transpose() const
948 {
949 return cvm::rmatrix(xx, yx, zx,
950 xy, yy, zy,
951 xz, yz, zz);
952 }
953
954 inline COLVARS_HOST_DEVICE friend cvm::rvector operator * (cvm::rmatrix const &m,
955 cvm::rvector const &r)
956 {
957 return cvm::rvector(m.xx*r.x + m.xy*r.y + m.xz*r.z,
958 m.yx*r.x + m.yy*r.y + m.yz*r.z,
959 m.zx*r.x + m.zy*r.y + m.zz*r.z);
960 }
961
962 inline COLVARS_HOST_DEVICE rmatrix& operator+=(const rmatrix& rhs) {
963 this->xx += rhs.xx;
964 this->xy += rhs.xy;
965 this->xz += rhs.xz;
966 this->yx += rhs.yx;
967 this->yy += rhs.yy;
968 this->yz += rhs.yz;
969 this->zx += rhs.zx;
970 this->zy += rhs.zy;
971 this->zz += rhs.zz;
972 return *this;
973 }
974};
975
976
977
981
982public:
983
984 cvm::real q0, q1, q2, q3;
985
987 inline COLVARS_HOST_DEVICE quaternion(cvm::real const qv[4])
988 : q0(qv[0]), q1(qv[1]), q2(qv[2]), q3(qv[3])
989 {}
990
992 inline COLVARS_HOST_DEVICE quaternion(cvm::real q0i,
993 cvm::real q1i,
994 cvm::real q2i,
995 cvm::real q3i)
996 : q0(q0i), q1(q1i), q2(q2i), q3(q3i)
997 {}
998
999 inline quaternion(cvm::vector1d<cvm::real> const &v)
1000 : q0(v[0]), q1(v[1]), q2(v[2]), q3(v[3])
1001 {}
1002
1004 inline COLVARS_HOST_DEVICE quaternion()
1005 {
1006 reset();
1007 }
1008
1010 inline COLVARS_HOST_DEVICE void reset()
1011 {
1012 q0 = q1 = q2 = q3 = 0.0;
1013 }
1014
1016 static inline size_t output_width(size_t real_width)
1017 {
1018 return 4*real_width + 13;
1019 }
1020
1021 std::string to_simple_string() const;
1022 int from_simple_string(std::string const &s);
1023
1025 friend std::ostream & operator << (std::ostream &os, cvm::quaternion const &q);
1027 friend std::istream & operator >> (std::istream &is, cvm::quaternion &q);
1028
1030 inline COLVARS_HOST_DEVICE cvm::real & operator [] (int i) {
1031 switch (i) {
1032 case 0:
1033 return this->q0;
1034 case 1:
1035 return this->q1;
1036 case 2:
1037 return this->q2;
1038 case 3:
1039 return this->q3;
1040 default:
1041#if !(defined(__NVCC__) || defined(__HIPCC__))
1042 cvm::error_static("Error: incorrect quaternion component.\n");
1043#endif
1044 return q0;
1045 }
1046 }
1047
1049 inline COLVARS_HOST_DEVICE cvm::real operator [] (int i) const {
1050 switch (i) {
1051 case 0:
1052 return this->q0;
1053 case 1:
1054 return this->q1;
1055 case 2:
1056 return this->q2;
1057 case 3:
1058 return this->q3;
1059 default:
1060#if !(defined(__NVCC__) || defined(__HIPCC__))
1061 cvm::error_static("Error: trying to access a quaternion "
1062 "component which is not between 0 and 3.\n");
1063#endif
1064 return 0.0;
1065 }
1066 }
1067
1068 inline cvm::vector1d<cvm::real> const as_vector() const
1069 {
1070 cvm::vector1d<cvm::real> result(4);
1071 result[0] = q0;
1072 result[1] = q1;
1073 result[2] = q2;
1074 result[3] = q3;
1075 return result;
1076 }
1077
1079 inline COLVARS_HOST_DEVICE cvm::real norm2() const
1080 {
1081 return q0*q0 + q1*q1 + q2*q2 + q3*q3;
1082 }
1083
1085 inline COLVARS_HOST_DEVICE cvm::real norm() const
1086 {
1087#if (defined(__HIP_DEVICE_COMPILE__)) || (defined (__CUDA_ARCH__))
1088#define COLVARS_MATH_SQRT ::sqrt
1089#else
1090#define COLVARS_MATH_SQRT cvm::sqrt
1091#endif
1092 return COLVARS_MATH_SQRT(this->norm2());
1093#undef COLVARS_MATH_SQRT
1094 }
1095
1097 inline COLVARS_HOST_DEVICE cvm::quaternion conjugate() const
1098 {
1099 return cvm::quaternion(q0, -q1, -q2, -q3);
1100 }
1101
1102 inline COLVARS_HOST_DEVICE void operator *= (cvm::real a)
1103 {
1104 q0 *= a; q1 *= a; q2 *= a; q3 *= a;
1105 }
1106
1107 inline COLVARS_HOST_DEVICE void operator /= (cvm::real a)
1108 {
1109 q0 /= a; q1 /= a; q2 /= a; q3 /= a;
1110 }
1111
1112 inline COLVARS_HOST_DEVICE void set_positive()
1113 {
1114 if (q0 > 0.0) return;
1115 q0 = -q0;
1116 q1 = -q1;
1117 q2 = -q2;
1118 q3 = -q3;
1119 }
1120
1121 inline COLVARS_HOST_DEVICE void operator += (cvm::quaternion const &h)
1122 {
1123 q0+=h.q0; q1+=h.q1; q2+=h.q2; q3+=h.q3;
1124 }
1125 inline COLVARS_HOST_DEVICE void operator -= (cvm::quaternion const &h)
1126 {
1127 q0-=h.q0; q1-=h.q1; q2-=h.q2; q3-=h.q3;
1128 }
1129
1131 inline COLVARS_HOST_DEVICE cvm::rvector get_vector() const
1132 {
1133 return cvm::rvector(q1, q2, q3);
1134 }
1135
1136
1137 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator + (cvm::quaternion const &h,
1138 cvm::quaternion const &q)
1139 {
1140 return cvm::quaternion(h.q0+q.q0, h.q1+q.q1, h.q2+q.q2, h.q3+q.q3);
1141 }
1142
1143 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator - (cvm::quaternion const &h,
1144 cvm::quaternion const &q)
1145 {
1146 return cvm::quaternion(h.q0-q.q0, h.q1-q.q1, h.q2-q.q2, h.q3-q.q3);
1147 }
1148
1151 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::quaternion const &h,
1152 cvm::quaternion const &q)
1153 {
1154 return cvm::quaternion(h.q0*q.q0 - h.q1*q.q1 - h.q2*q.q2 - h.q3*q.q3,
1155 h.q0*q.q1 + h.q1*q.q0 + h.q2*q.q3 - h.q3*q.q2,
1156 h.q0*q.q2 + h.q2*q.q0 + h.q3*q.q1 - h.q1*q.q3,
1157 h.q0*q.q3 + h.q3*q.q0 + h.q1*q.q2 - h.q2*q.q1);
1158 }
1159
1160 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::real c,
1161 cvm::quaternion const &q)
1162 {
1163 return cvm::quaternion(c*q.q0, c*q.q1, c*q.q2, c*q.q3);
1164 }
1165 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::quaternion const &q,
1166 cvm::real c)
1167 {
1168 return cvm::quaternion(q.q0*c, q.q1*c, q.q2*c, q.q3*c);
1169 }
1170 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator / (cvm::quaternion const &q,
1171 cvm::real c)
1172 {
1173 return cvm::quaternion(q.q0/c, q.q1/c, q.q2/c, q.q3/c);
1174 }
1175
1176
1179 inline COLVARS_HOST_DEVICE cvm::rvector rotate(cvm::rvector const &v) const
1180 {
1181 return ( (*this) * cvm::quaternion(0.0, v.x, v.y, v.z) *
1182 this->conjugate() ).get_vector();
1183 }
1184
1187 inline COLVARS_HOST_DEVICE cvm::quaternion rotate(cvm::quaternion const &Q2) const
1188 {
1189 cvm::rvector const vq_rot = this->rotate(Q2.get_vector());
1190 return cvm::quaternion(Q2.q0, vq_rot.x, vq_rot.y, vq_rot.z);
1191 }
1192
1194 inline COLVARS_HOST_DEVICE cvm::rmatrix rotation_matrix() const
1195 {
1196 cvm::rmatrix R;
1197
1198 R.xx = q0*q0 + q1*q1 - q2*q2 - q3*q3;
1199 R.yy = q0*q0 - q1*q1 + q2*q2 - q3*q3;
1200 R.zz = q0*q0 - q1*q1 - q2*q2 + q3*q3;
1201
1202 R.xy = 2.0 * (q1*q2 - q0*q3);
1203 R.xz = 2.0 * (q0*q2 + q1*q3);
1204
1205 R.yx = 2.0 * (q0*q3 + q1*q2);
1206 R.yz = 2.0 * (q2*q3 - q0*q1);
1207
1208 R.zx = 2.0 * (q1*q3 - q0*q2);
1209 R.zy = 2.0 * (q0*q1 + q2*q3);
1210
1211 return R;
1212 }
1213
1248 template <typename T>
1249 inline COLVARS_HOST_DEVICE T derivative_element_wise_product_sum(const cvm::real (&C)[3][3]) const {
1250 return T{{
1251 2.0 * ( q0 * C[0][0] - q3 * C[0][1] + q2 * C[0][2] +
1252 q3 * C[1][0] + q0 * C[1][1] - q1 * C[1][2] +
1253 -q2 * C[2][0] + q1 * C[2][1] + q0 * C[2][2]),
1254 2.0 * ( q1 * C[0][0] + q2 * C[0][1] + q3 * C[0][2] +
1255 q2 * C[1][0] - q1 * C[1][1] - q0 * C[1][2] +
1256 q3 * C[2][0] + q0 * C[2][1] - q1 * C[2][2]),
1257 2.0 * (-q2 * C[0][0] + q1 * C[0][1] + q0 * C[0][2] +
1258 q1 * C[1][0] + q2 * C[1][1] + q3 * C[1][2] +
1259 -q0 * C[2][0] + q3 * C[2][1] - q2 * C[2][2]),
1260 2.0 * (-q3 * C[0][0] - q0 * C[0][1] + q1 * C[0][2] +
1261 q0 * C[1][0] - q3 * C[1][1] + q2 * C[1][2] +
1262 q1 * C[2][0] + q2 * C[2][1] + q3 * C[2][2])
1263 }};
1264 }
1265
1268 inline COLVARS_HOST_DEVICE cvm::real cosine(cvm::quaternion const &q) const
1269 {
1270 cvm::real const iprod = this->inner(q);
1271 return 2.0*iprod*iprod - 1.0;
1272 }
1273
1277 inline COLVARS_HOST_DEVICE cvm::real dist2(cvm::quaternion const &Q2) const
1278 {
1279 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
1280 this->q2*Q2.q2 + this->q3*Q2.q3;
1281#if (defined(__HIP_DEVICE_COMPILE__)) || (defined (__CUDA_ARCH__))
1282#define COLVARS_MATH_ACOS ::acos
1283#else
1284#define COLVARS_MATH_ACOS cvm::acos
1285#endif
1286 cvm::real const omega = COLVARS_MATH_ACOS( (cos_omega > 1.0) ? 1.0 :
1287 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
1288#undef COLVARS_MATH_ACOS
1289
1290 // get the minimum distance: x and -x are the same quaternion
1291 if (cos_omega > 0.0)
1292 return omega * omega;
1293 else
1294 return (PI-omega) * (PI-omega);
1295 }
1296
1299 inline COLVARS_HOST_DEVICE cvm::quaternion dist2_grad(cvm::quaternion const &Q2) const
1300 {
1301#if (defined(__HIP_DEVICE_COMPILE__)) || (defined (__CUDA_ARCH__))
1302#define COLVARS_MATH_ACOS ::acos
1303#define COLVARS_MATH_SIN ::sin
1304#define COLVARS_MATH_FABS ::fabs
1305#else
1306#define COLVARS_MATH_ACOS cvm::acos
1307#define COLVARS_MATH_SIN cvm::sin
1308#define COLVARS_MATH_FABS cvm::fabs
1309#endif
1310 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
1311 cvm::real const omega = COLVARS_MATH_ACOS( (cos_omega > 1.0) ? 1.0 :
1312 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
1313 cvm::real const sin_omega = COLVARS_MATH_SIN(omega);
1314
1315 if (COLVARS_MATH_FABS(sin_omega) < 1.0E-14) {
1316 // return a null 4d vector
1317 return cvm::quaternion(0.0, 0.0, 0.0, 0.0);
1318 }
1319#undef COLVARS_MATH_ACOS
1320#undef COLVARS_MATH_SIN
1321#undef COLVARS_MATH_FABS
1322 cvm::quaternion const
1323 grad1((-1.0)*sin_omega*Q2.q0 + cos_omega*(this->q0-cos_omega*Q2.q0)/sin_omega,
1324 (-1.0)*sin_omega*Q2.q1 + cos_omega*(this->q1-cos_omega*Q2.q1)/sin_omega,
1325 (-1.0)*sin_omega*Q2.q2 + cos_omega*(this->q2-cos_omega*Q2.q2)/sin_omega,
1326 (-1.0)*sin_omega*Q2.q3 + cos_omega*(this->q3-cos_omega*Q2.q3)/sin_omega);
1327
1328 if (cos_omega > 0.0) {
1329 return 2.0*omega*grad1;
1330 } else {
1331 return -2.0*(PI-omega)*grad1;
1332 }
1333 }
1334
1337 inline COLVARS_HOST_DEVICE void match(cvm::quaternion &Q2) const
1338 {
1339 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
1340 this->q2*Q2.q2 + this->q3*Q2.q3;
1341 if (cos_omega < 0.0) Q2 *= -1.0;
1342 }
1343
1346 inline COLVARS_HOST_DEVICE cvm::real inner(cvm::quaternion const &Q2) const
1347 {
1348 cvm::real const prod = this->q0*Q2.q0 + this->q1*Q2.q1 +
1349 this->q2*Q2.q2 + this->q3*Q2.q3;
1350 return prod;
1351 }
1352
1353
1354};
1355
1356#ifndef COLVARS_LAMMPS
1357namespace NR {
1358int diagonalize_matrix(cvm::real m[4][4],
1359 cvm::real eigval[4],
1360 cvm::real eigvec[4][4]);
1361}
1362#endif
1363
1364
1368{
1369private:
1372
1375
1378
1381
1384
1385public:
1388
1390 cvm::quaternion q{1.0, 0.0, 0.0, 0.0};
1391
1392 friend struct rotation_derivative;
1393 friend class cvm::atom_group;
1394
1395 cvm::real* get_S() {return (cvm::real*)S;}
1396 cvm::real* get_eigenvectors() {return (cvm::real*)S_eigvec;}
1397 cvm::real* get_eigenvalues() {return S_eigval;}
1398 cvm::quaternion* get_q() {return &q;}
1399 cvm::real* get_S_backup() {return (cvm::real*)S_backup;}
1400 cvm::rmatrix* get_C() {return &C;}
1401
1408 void debug_gradients(
1409 cvm::rotation &rot,
1410 const cvm::ag_vector_real_t &pos1,
1411 const cvm::ag_vector_real_t &pos2,
1412 const size_t num_atoms_pos1,
1413 const size_t num_atoms_pos2);
1414
1425 void calc_optimal_rotation(std::vector<atom_pos> const &pos1,
1426 std::vector<atom_pos> const &pos2);
1427 void calc_optimal_rotation_soa(
1428 cvm::ag_vector_real_t const &pos1,
1429 cvm::ag_vector_real_t const &pos2,
1430 const size_t num_atoms_pos1,
1431 const size_t num_atoms_pos2);
1432
1434 int init();
1435
1437 rotation();
1438
1440 rotation(cvm::quaternion const &qi);
1441
1443 rotation(cvm::real angle, cvm::rvector const &axis);
1444
1446 ~rotation();
1447
1449 inline cvm::rvector rotate(cvm::rvector const &v) const
1450 {
1451 return q.rotate(v);
1452 }
1453
1455 inline cvm::rotation inverse() const
1456 {
1457 return cvm::rotation(this->q.conjugate());
1458 }
1459
1461 inline cvm::rmatrix matrix() const
1462 {
1463 return q.rotation_matrix();
1464 }
1465
1468 inline cvm::real spin_angle(cvm::rvector const &axis) const
1469 {
1470 cvm::rvector const q_vec = q.get_vector();
1471 cvm::real alpha = (180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
1472 while (alpha > 180.0) alpha -= 360;
1473 while (alpha < -180.0) alpha += 360;
1474 return alpha;
1475 }
1476
1480 {
1481 cvm::rvector const q_vec = q.get_vector();
1482 cvm::real const iprod = axis * q_vec;
1483
1484 if (q.q0 != 0.0) {
1485
1486 cvm::real const dspindx =
1487 (180.0/PI) * 2.0 * (1.0 / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1488
1489 return cvm::quaternion( dspindx * (iprod * (-1.0) / (q.q0*q.q0)),
1490 dspindx * ((1.0/q.q0) * axis.x),
1491 dspindx * ((1.0/q.q0) * axis.y),
1492 dspindx * ((1.0/q.q0) * axis.z));
1493 } else {
1494 // (1/(1+x^2)) ~ (1/x)^2
1495 // The documentation of spinAngle discourages its use when q_vec and
1496 // axis are not close
1497 return cvm::quaternion((180.0/PI) * 2.0 * ((-1.0)/iprod), 0.0, 0.0, 0.0);
1498 }
1499 }
1500
1503 inline cvm::real cos_theta(cvm::rvector const &axis) const
1504 {
1505 cvm::rvector const q_vec = q.get_vector();
1506 cvm::real const alpha =
1507 (180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
1508
1509 cvm::real const cos_spin_2 = cvm::cos(alpha * (PI/180.0) * 0.5);
1510 cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ?
1511 (q.q0 / cos_spin_2) :
1512 (0.0) );
1513 // cos(2t) = 2*cos(t)^2 - 1
1514 return 2.0 * (cos_theta_2*cos_theta_2) - 1.0;
1515 }
1516
1519 {
1520 cvm::rvector const q_vec = q.get_vector();
1521 cvm::real const iprod = axis * q_vec;
1522
1523 cvm::real const cos_spin_2 = cvm::cos(cvm::atan2(iprod, q.q0));
1524
1525 if (q.q0 != 0.0) {
1526
1527 cvm::real const d_cos_theta_dq0 =
1528 (4.0 * q.q0 / (cos_spin_2*cos_spin_2)) *
1529 (1.0 - (iprod*iprod)/(q.q0*q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1530
1531 cvm::real const d_cos_theta_dqn =
1532 (4.0 * q.q0 / (cos_spin_2*cos_spin_2) *
1533 (iprod/q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1534
1535 return cvm::quaternion(d_cos_theta_dq0,
1536 d_cos_theta_dqn * axis.x,
1537 d_cos_theta_dqn * axis.y,
1538 d_cos_theta_dqn * axis.z);
1539 } else {
1540
1541 cvm::real const d_cos_theta_dqn =
1542 (4.0 / (cos_spin_2*cos_spin_2 * iprod));
1543
1544 return cvm::quaternion(0.0,
1545 d_cos_theta_dqn * axis.x,
1546 d_cos_theta_dqn * axis.y,
1547 d_cos_theta_dqn * axis.z);
1548 }
1549 }
1550
1555
1556protected:
1557
1562
1564 void build_correlation_matrix(std::vector<cvm::atom_pos> const &pos1,
1565 std::vector<cvm::atom_pos> const &pos2);
1566
1569
1572
1574 void *jacobi;
1575};
1576
1577#if defined (COLVARS_CUDA) || defined (COLVARS_HIP)
1578namespace colvars_gpu {
1579class jacobi_gpu;
1581private:
1582 // cudaStream_t stream;
1584 // cvm::rmatrix* d_C;
1597 // cvm::real* d_S_backup;
1599 // jacobi_gpu* jacobi;
1601 unsigned int* tbcount;
1606 int* discontinuous_rotation;
1613 cvm::real* h_S;
1614 cvm::real* h_S_eigval;
1615 cvm::real* h_S_eigvec;
1616public:
1618 rotation_gpu();
1620 ~rotation_gpu();
1622 bool initialized() const {return b_initialized;}
1624 int init(/*const cudaStream_t& stream_in*/);
1636 cvm::real* const d_pos1,
1637 cvm::real* const d_pos2,
1638 const size_t num_atoms_pos1,
1639 const size_t num_atoms_pos2,
1640 cudaGraph_t& graph,
1641 std::unordered_map<std::string, cudaGraphNode_t>& nodes_map);
1644 void after_sync_check() const;
1645
1646 friend struct rotation_derivative_gpu;
1647 cvm::real* get_S() const {return d_S;}
1648 cvm::real* get_eigenvectors() const {return d_S_eigvec;}
1649 cvm::real* get_eigenvalues() const {return d_S_eigval;}
1650 cvm::quaternion* get_q() const {return d_q;}
1651
1652 void to_cpu(cvm::rotation& rot) const;
1653};
1654}
1655#endif // defined(COLVARS_CUDA) || defined(COLVARS_HIP)
1656
1657#endif
Definition: colvartypes.h:385
Arbitrary size array (two dimensions) suitable for linear algebra operations (i.e....
Definition: colvartypes.h:376
matrix2d(matrix2d< T > const &m)
Copy constructor.
Definition: colvartypes.h:494
T ** c_array()
Return the 2-d C array.
Definition: colvartypes.h:543
void clear()
Deallocation routine.
Definition: colvartypes.h:463
~matrix2d()
Destructor.
Definition: colvartypes.h:504
std::vector< T > const & data_array() const
Return a reference to the data.
Definition: colvartypes.h:515
matrix2d< T > & operator=(matrix2d< T > const &m)
Assignment.
Definition: colvartypes.h:530
matrix2d()
Default constructor.
Definition: colvartypes.h:480
std::vector< T > & data_array()
Return a reference to the data.
Definition: colvartypes.h:509
void resize(size_t const ol, size_t const il)
Allocation routine, used by all constructors.
Definition: colvartypes.h:420
friend std::ostream & operator<<(std::ostream &os, matrix2d< T > const &m)
Formatted output.
Definition: colvartypes.h:670
void reset()
Set all elements to zero.
Definition: colvartypes.h:469
1-dimensional vector of real numbers with four components and a quaternion algebra
Definition: colvartypes.h:980
friend COLVARS_HOST_DEVICE cvm::quaternion operator*(cvm::quaternion const &h, cvm::quaternion const &q)
Provides the quaternion product. NOTE: for the inner product use: h.inner (q);
Definition: colvartypes.h:1151
COLVARS_HOST_DEVICE cvm::rvector rotate(cvm::rvector const &v) const
Rotate v through this quaternion (put it in the rotated reference frame)
Definition: colvartypes.h:1179
COLVARS_HOST_DEVICE cvm::real & operator[](int i)
Access the quaternion as a 4-d array (return a reference)
Definition: colvartypes.h:1030
COLVARS_HOST_DEVICE quaternion(cvm::real q0i, cvm::real q1i, cvm::real q2i, cvm::real q3i)
Constructor component by component.
Definition: colvartypes.h:992
friend std::istream & operator>>(std::istream &is, cvm::quaternion &q)
Formatted input operator.
Definition: colvartypes.cpp:125
COLVARS_HOST_DEVICE cvm::quaternion rotate(cvm::quaternion const &Q2) const
Rotate Q2 through this quaternion (put it in the rotated reference frame)
Definition: colvartypes.h:1187
COLVARS_HOST_DEVICE void match(cvm::quaternion &Q2) const
Choose the closest between Q2 and -Q2 and save it back. Not required for dist2() and dist2_grad()
Definition: colvartypes.h:1337
COLVARS_HOST_DEVICE quaternion()
Default constructor.
Definition: colvartypes.h:1004
COLVARS_HOST_DEVICE cvm::quaternion conjugate() const
Return the conjugate quaternion.
Definition: colvartypes.h:1097
COLVARS_HOST_DEVICE cvm::real norm2() const
Square norm of the quaternion.
Definition: colvartypes.h:1079
friend std::ostream & operator<<(std::ostream &os, cvm::quaternion const &q)
Formatted output operator.
Definition: colvartypes.cpp:106
COLVARS_HOST_DEVICE cvm::real norm() const
Norm of the quaternion.
Definition: colvartypes.h:1085
COLVARS_HOST_DEVICE void reset()
Set all components to zero (null quaternion)
Definition: colvartypes.h:1010
COLVARS_HOST_DEVICE cvm::real dist2(cvm::quaternion const &Q2) const
Square distance from another quaternion on the 4-dimensional unit sphere: returns the square of the a...
Definition: colvartypes.h:1277
static size_t output_width(size_t real_width)
Tell the number of characters required to print a quaternion, given that of a real number.
Definition: colvartypes.h:1016
COLVARS_HOST_DEVICE cvm::rvector get_vector() const
Return the vector component.
Definition: colvartypes.h:1131
COLVARS_HOST_DEVICE cvm::real inner(cvm::quaternion const &Q2) const
Inner product (as a 4-d vector) with Q2; requires match() if the largest overlap is looked for.
Definition: colvartypes.h:1346
COLVARS_HOST_DEVICE cvm::quaternion dist2_grad(cvm::quaternion const &Q2) const
Definition: colvartypes.h:1299
COLVARS_HOST_DEVICE cvm::rmatrix rotation_matrix() const
Return the 3x3 matrix associated to this quaternion.
Definition: colvartypes.h:1194
COLVARS_HOST_DEVICE quaternion(cvm::real const qv[4])
Constructor component by component.
Definition: colvartypes.h:987
COLVARS_HOST_DEVICE T derivative_element_wise_product_sum(const cvm::real(&C)[3][3]) const
Calculate the sums of element-wise products of a given matrix with respect to dR/dq0,...
Definition: colvartypes.h:1249
COLVARS_HOST_DEVICE cvm::real cosine(cvm::quaternion const &q) const
Return the cosine between the orientation frame associated to this quaternion and another.
Definition: colvartypes.h:1268
2-dimensional array of real numbers with three components along each dimension (works with colvarmodu...
Definition: colvartypes.h:903
COLVARS_HOST_DEVICE rmatrix(cvm::real xxi, cvm::real xyi, cvm::real xzi, cvm::real yxi, cvm::real yyi, cvm::real yzi, cvm::real zxi, cvm::real zyi, cvm::real zzi)
Constructor component by component.
Definition: colvartypes.h:917
COLVARS_HOST_DEVICE rmatrix()
Default constructor.
Definition: colvartypes.h:910
COLVARS_HOST_DEVICE cvm::real determinant() const
Return the determinant.
Definition: colvartypes.h:939
A rotation between two sets of coordinates (for the moment a wrapper for colvarmodule::quaternion)
Definition: colvartypes.h:1368
~rotation()
Destructor.
Definition: colvartypes.cpp:200
cvm::rmatrix C
Correlation matrix C (3, 3)
Definition: colvartypes.h:1371
rotation()
Default constructor.
Definition: colvartypes.cpp:162
cvm::real cos_theta(cvm::rvector const &axis) const
Return the projection of the orientation vector onto a predefined axis.
Definition: colvartypes.h:1503
cvm::real S_eigval[4]
Eigenvalues of S.
Definition: colvartypes.h:1377
cvm::real S_backup[4][4]
Used for debugging gradients.
Definition: colvartypes.h:1383
cvm::rvector rotate(cvm::rvector const &v) const
Return the rotated vector.
Definition: colvartypes.h:1449
int init()
Initialize member data.
Definition: colvartypes.cpp:153
cvm::real S[4][4]
Overlap matrix S (4, 4)
Definition: colvartypes.h:1374
cvm::quaternion dspin_angle_dq(cvm::rvector const &axis) const
Return the derivative of the spin angle with respect to the quaternion.
Definition: colvartypes.h:1479
cvm::quaternion dcos_theta_dq(cvm::rvector const &axis) const
Return the derivative of the tilt wrt the quaternion.
Definition: colvartypes.h:1518
cvm::real spin_angle(cvm::rvector const &axis) const
Return the spin angle (in degrees) with respect to the provided axis (which MUST be normalized)
Definition: colvartypes.h:1468
cvm::real S_eigvec[4][4]
Eigenvectors of S.
Definition: colvartypes.h:1380
void calc_optimal_rotation(std::vector< atom_pos > const &pos1, std::vector< atom_pos > const &pos2)
Calculate the optimal rotation and store the corresponding eigenvalue and eigenvector in the argument...
Definition: colvartypes.cpp:381
static cvm::real crossing_threshold
Threshold for the eigenvalue crossing test.
Definition: colvartypes.h:1554
cvm::quaternion q_old
Previous value of the rotation (used to warn the user when the structure changes too much,...
Definition: colvartypes.h:1561
static bool monitor_crossings
Whether to test for eigenvalue crossing.
Definition: colvartypes.h:1552
bool b_debug_gradients
Perform gradient tests.
Definition: colvartypes.h:1387
void build_correlation_matrix(std::vector< cvm::atom_pos > const &pos1, std::vector< cvm::atom_pos > const &pos2)
Build the correlation matrix C (used by calc_optimal_rotation())
Definition: colvartypes.cpp:211
cvm::rmatrix matrix() const
Return the associated 3x3 matrix.
Definition: colvartypes.h:1461
void * jacobi
Pointer to instance of Jacobi solver.
Definition: colvartypes.h:1574
void compute_overlap_matrix()
Compute the overlap matrix S (used by calc_optimal_rotation())
Definition: colvartypes.cpp:231
void debug_gradients(cvm::rotation &rot, const cvm::ag_vector_real_t &pos1, const cvm::ag_vector_real_t &pos2, const size_t num_atoms_pos1, const size_t num_atoms_pos2)
Function for debugging gradients.
Definition: colvartypes.cpp:293
void calc_optimal_rotation_impl()
Actual implementation of calc_optimal_rotation (and called by it)
Definition: colvartypes.cpp:431
cvm::rotation inverse() const
Return the inverse of this rotation.
Definition: colvartypes.h:1455
cvm::quaternion q
The rotation itself (implemented as a quaternion)
Definition: colvartypes.h:1390
vector of real numbers with three components
Definition: colvartypes.h:728
COLVARS_HOST_DEVICE void reset()
Set all components to zero.
Definition: colvartypes.h:740
COLVARS_HOST_DEVICE void set(cvm::real value)
Set all components to a scalar.
Definition: colvartypes.h:761
friend COLVARS_HOST_DEVICE cvm::real operator*(cvm::rvector const &v1, cvm::rvector const &v2)
Inner (dot) product.
Definition: colvartypes.h:875
COLVARS_HOST_DEVICE void set(cvm::real x_i, cvm::real y_i, cvm::real z_i)
Assign all components.
Definition: colvartypes.h:767
COLVARS_HOST_DEVICE cvm::real & operator[](int i)
Access cartesian components by index.
Definition: colvartypes.h:775
Arbitrary size array (one dimensions) suitable for linear algebra operations (i.e....
Definition: colvartypes.h:36
void reset()
Set all elements to zero.
Definition: colvartypes.h:95
size_t output_width(size_t real_width) const
Formatted output.
Definition: colvartypes.h:281
cvm::real norm2() const
Squared norm.
Definition: colvartypes.h:227
void sliceassign(size_t const i1, size_t const i2, vector1d< T > const &v)
Assign a vector to a slice of this vector.
Definition: colvartypes.h:267
std::vector< T > & data_array()
Return a reference to the data.
Definition: colvartypes.h:78
vector1d & operator=(const vector1d &)=default
Explicit Copy assignement.
vector1d(const vector1d &)=default
Explicit Copy constructor.
vector1d(size_t const n, T const *t)
Constructor from C array.
Definition: colvartypes.h:51
vector1d(size_t const n=0)
Default constructor.
Definition: colvartypes.h:44
T * c_array()
Return a pointer to the data location.
Definition: colvartypes.h:68
vector1d< T > const slice(size_t const i1, size_t const i2) const
Slicing.
Definition: colvartypes.h:253
std::vector< T > const & data_array() const
Return a reference to the data.
Definition: colvartypes.h:84
double real
Defining an abstract real number allows to switch precision.
Definition: colvarmodule.h:99
static int error_static(std::string const &message, int code=-1)
Definition: colvarmodule.h:770
static real cos(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:155
static real atan2(real const &x, real const &y)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:200
static real sqrt(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:143
static std::string to_str(char const *s)
Convert to string for output purposes.
Definition: colvarmodule.cpp:2541
Definition: colvartypes.h:1580
int add_optimal_rotation_nodes(cvm::real *const d_pos1, cvm::real *const d_pos2, const size_t num_atoms_pos1, const size_t num_atoms_pos2, cudaGraph_t &graph, std::unordered_map< std::string, cudaGraphNode_t > &nodes_map)
Calculate the optimal rotation and store the corresponding eigenvalue and eigenvector in the argument...
Definition: colvartypes.cpp:549
cvm::real * d_S_eigvec
Eigenvectors of S.
Definition: colvartypes.h:1595
cvm::real * d_S_eigval
Eigenvalues of S.
Definition: colvartypes.h:1588
int * max_iteration_reached
Flag for checking if eigendecomposition is failed.
Definition: colvartypes.h:1608
cvm::quaternion * d_q
The rotation itself (implemented as a quaternion)
Definition: colvartypes.h:1603
cvm::real * d_S
Correlation matrix C (3, 3)
Definition: colvartypes.h:1586
unsigned int * tbcount
Used for debugging gradients.
Definition: colvartypes.h:1601
int init()
Initialize member data.
Definition: colvartypes.cpp:520
void after_sync_check() const
Checking after synchronization ( eigendecomposition iterations and max crossing)
Definition: colvartypes.cpp:617
cvm::rmatrix * h_C
Host data for compatibility with CPU buffers.
Definition: colvartypes.h:1612
bool b_initialized
Flag for checking if initialized.
Definition: colvartypes.h:1610
~rotation_gpu()
Destructor.
Definition: colvartypes.cpp:503
cvm::quaternion * d_q_old
Crossing monitor.
Definition: colvartypes.h:1605
rotation_gpu()
Constructor.
Definition: colvartypes.cpp:493
bool initialized() const
Check if the object is initialized.
Definition: colvartypes.h:1622
Store the information of a group of atoms in a structure-of-arrays (SoA) style.
Definition: colvaratoms.h:52
Collective variables main module.
Definition: colvar_rotation_derivative.h:622
Helper class for calculating the derivative of rotation.
Definition: colvar_rotation_derivative.h:42