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("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("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("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(cvm::cv_prec);
335 os << (*this)[0];
336 size_t i;
337 for (i = 1; i < this->size(); i++) {
338 os << " " << (*this)[i];
339 }
340 return os.str();
341 }
342
343 inline int from_simple_string(std::string const &s)
344 {
345 std::stringstream stream(s);
346 size_t i = 0;
347 if (this->size()) {
348 while ((stream >> (*this)[i]) && (i < this->size())) {
349 i++;
350 }
351 if (i < this->size()) {
352 return COLVARS_ERROR;
353 }
354 } else {
355 T input;
356 while (stream >> input) {
357 if ((i % 100) == 0) {
358 data.reserve(data.size()+100);
359 }
360 data.resize(data.size()+1);
361 data[i] = input;
362 i++;
363 }
364 }
365 return COLVARS_OK;
366 }
367
368};
369
370
374template <class T> class colvarmodule::matrix2d
375{
376public:
377
378 friend class row;
379 size_t outer_length;
380 size_t inner_length;
381
382protected:
383
384 class row {
385 public:
386 T * data;
387 size_t length;
388 inline row(T * const row_data, size_t const inner_length)
389 : data(row_data), length(inner_length)
390 {}
391 inline T & operator [] (size_t const j) {
392 return *(data+j);
393 }
394 inline T const & operator [] (size_t const j) const {
395 return *(data+j);
396 }
397 inline operator vector1d<T>() const
398 {
399 return vector1d<T>(length, data);
400 }
401 inline int set(cvm::vector1d<T> const &v) const
402 {
403 if (v.size() != length) {
404 return cvm::error("Error: setting a matrix row from a vector of "
405 "incompatible size.\n", COLVARS_BUG_ERROR);
406 }
407 for (size_t i = 0; i < length; i++) data[i] = v[i];
408 return COLVARS_OK;
409 }
410 };
411
412 std::vector<T> data;
413 std::vector<row> rows;
414 std::vector<T *> pointers;
415
416public:
417
419 inline void resize(size_t const ol, size_t const il)
420 {
421 if ((ol > 0) && (il > 0)) {
422
423 if (data.size() > 0) {
424 // copy previous data
425 size_t i, j;
426 std::vector<T> new_data(ol * il);
427 for (i = 0; i < outer_length; i++) {
428 for (j = 0; j < inner_length; j++) {
429 new_data[il*i+j] = data[inner_length*i+j];
430 }
431 }
432 data.resize(ol * il);
433 // copy them back
434 data = new_data;
435 } else {
436 data.resize(ol * il);
437 }
438
439 outer_length = ol;
440 inner_length = il;
441
442 if (data.size() > 0) {
443 // rebuild rows
444 size_t i;
445 rows.clear();
446 rows.reserve(outer_length);
447 pointers.clear();
448 pointers.reserve(outer_length);
449 for (i = 0; i < outer_length; i++) {
450 rows.push_back(row(&(data[0])+inner_length*i, inner_length));
451 pointers.push_back(&(data[0])+inner_length*i);
452 }
453 }
454 } else {
455 // zero size
456 data.clear();
457 rows.clear();
458 }
459 }
460
462 inline void clear() {
463 rows.clear();
464 data.clear();
465 }
466
468 inline void reset()
469 {
470 data.assign(data.size(), T(0.0));
471 }
472
473 inline size_t size() const
474 {
475 return data.size();
476 }
477
479 inline matrix2d()
480 : outer_length(0), inner_length(0)
481 {
482 this->resize(0, 0);
483 }
484
485 inline matrix2d(size_t const ol, size_t const il)
486 : outer_length(ol), inner_length(il)
487 {
488 this->resize(outer_length, inner_length);
489 reset();
490 }
491
493 inline matrix2d(matrix2d<T> const &m)
494 : outer_length(m.outer_length), inner_length(m.inner_length)
495 {
496 // reinitialize data and rows arrays
497 this->resize(outer_length, inner_length);
498 // copy data
499 data = m.data;
500 }
501
503 inline ~matrix2d() {
504 this->clear();
505 }
506
508 inline std::vector<T> &data_array()
509 {
510 return data;
511 }
512
514 inline std::vector<T> const &data_array() const
515 {
516 return data;
517 }
518
519 inline row & operator [] (size_t const i)
520 {
521 return rows[i];
522 }
523 inline row const & operator [] (size_t const i) const
524 {
525 return rows[i];
526 }
527
530 {
531 if ((outer_length != m.outer_length) || (inner_length != m.inner_length)){
532 this->clear();
533 outer_length = m.outer_length;
534 inner_length = m.inner_length;
535 this->resize(outer_length, inner_length);
536 }
537 data = m.data;
538 return *this;
539 }
540
542 inline T ** c_array() {
543 if (rows.size() > 0) {
544 return &(pointers[0]);
545 } else {
546 return NULL;
547 }
548 }
549
550 inline static void check_sizes(matrix2d<T> const &m1, matrix2d<T> const &m2)
551 {
552 if ((m1.outer_length != m2.outer_length) ||
553 (m1.inner_length != m2.inner_length)) {
554 cvm::error("Error: trying to perform an operation between "
555 "matrices of different sizes, "+
556 cvm::to_str(m1.outer_length)+"x"+
557 cvm::to_str(m1.inner_length)+" and "+
558 cvm::to_str(m2.outer_length)+"x"+
559 cvm::to_str(m2.inner_length)+".\n");
560 }
561 }
562
563 inline void operator += (matrix2d<T> const &m)
564 {
565 check_sizes(*this, m);
566 size_t i;
567 for (i = 0; i < data.size(); i++) {
568 data[i] += m.data[i];
569 }
570 }
571
572 inline void operator -= (matrix2d<T> const &m)
573 {
574 check_sizes(*this, m);
575 size_t i;
576 for (i = 0; i < data.size(); i++) {
577 data[i] -= m.data[i];
578 }
579 }
580
581 inline void operator *= (cvm::real a)
582 {
583 size_t i;
584 for (i = 0; i < data.size(); i++) {
585 data[i] *= a;
586 }
587 }
588
589 inline void operator /= (cvm::real a)
590 {
591 size_t i;
592 for (i = 0; i < data.size(); i++) {
593 data[i] /= a;
594 }
595 }
596
597 inline friend matrix2d<T> operator + (matrix2d<T> const &m1,
598 matrix2d<T> const &m2)
599 {
600 check_sizes(m1, m2);
601 matrix2d<T> result(m1.outer_length, m1.inner_length);
602 size_t i;
603 for (i = 0; i < m1.data.size(); i++) {
604 result.data[i] = m1.data[i] + m2.data[i];
605 }
606 return result;
607 }
608
609 inline friend matrix2d<T> operator - (matrix2d<T> const &m1,
610 matrix2d<T> const &m2)
611 {
612 check_sizes(m1, m2);
613 matrix2d<T> result(m1.outer_length, m1.inner_length);
614 size_t i;
615 for (i = 0; i < m1.data.size(); i++) {
616 result.data[i] = m1.data[i] - m1.data[i];
617 }
618 return result;
619 }
620
621 inline friend matrix2d<T> operator * (matrix2d<T> const &m, cvm::real a)
622 {
623 matrix2d<T> result(m.outer_length, m.inner_length);
624 size_t i;
625 for (i = 0; i < m.data.size(); i++) {
626 result.data[i] = m.data[i] * a;
627 }
628 return result;
629 }
630
631 inline friend matrix2d<T> operator * (cvm::real a, matrix2d<T> const &m)
632 {
633 return m * a;
634 }
635
636 inline friend matrix2d<T> operator / (matrix2d<T> const &m, cvm::real a)
637 {
638 matrix2d<T> result(m.outer_length, m.inner_length);
639 size_t i;
640 for (i = 0; i < m.data.size(); i++) {
641 result.data[i] = m.data[i] * a;
642 }
643 return result;
644 }
645
647 inline friend vector1d<T> operator * (vector1d<T> const &v,
648 matrix2d<T> const &m)
649 {
650 vector1d<T> result(m.inner_length);
651 if (m.outer_length != v.size()) {
652 cvm::error("Error: trying to multiply a vector and a matrix "
653 "of incompatible sizes, "+
654 cvm::to_str(v.size()) + " and " +
655 cvm::to_str(m.outer_length)+"x"+cvm::to_str(m.inner_length) +
656 ".\n");
657 } else {
658 size_t i, k;
659 for (i = 0; i < m.inner_length; i++) {
660 for (k = 0; k < m.outer_length; k++) {
661 result[i] += m[k][i] * v[k];
662 }
663 }
664 }
665 return result;
666 }
667
669 friend std::ostream & operator << (std::ostream &os,
670 matrix2d<T> const &m)
671 {
672 std::streamsize const w = os.width();
673 std::streamsize const p = os.precision();
674
675 os.width(2);
676 os << "( ";
677 size_t i;
678 for (i = 0; i < m.outer_length; i++) {
679 os << " ( ";
680 size_t j;
681 for (j = 0; j < m.inner_length-1; j++) {
682 os.width(w);
683 os.precision(p);
684 os << m[i][j] << " , ";
685 }
686 os.width(w);
687 os.precision(p);
688 os << m[i][m.inner_length-1] << " )";
689 }
690
691 os << " )";
692 return os;
693 }
694
695 inline std::string to_simple_string() const
696 {
697 if (this->size() == 0) return std::string("");
698 std::ostringstream os;
699 os.setf(std::ios::scientific, std::ios::floatfield);
700 os.precision(cvm::cv_prec);
701 os << (*this)[0];
702 size_t i;
703 for (i = 1; i < data.size(); i++) {
704 os << " " << data[i];
705 }
706 return os.str();
707 }
708
709 inline int from_simple_string(std::string const &s)
710 {
711 std::stringstream stream(s);
712 size_t i = 0;
713 while ((i < data.size()) && (stream >> data[i])) {
714 i++;
715 }
716 if (i < data.size()) {
717 return COLVARS_ERROR;
718 }
719 return COLVARS_OK;
720 }
721
722};
723
724
727
728public:
729
730 cvm::real x, y, z;
731
732 inline COLVARS_HOST_DEVICE rvector()
733 {
734 reset();
735 }
736
738 inline COLVARS_HOST_DEVICE void reset()
739 {
740 set(0.0);
741 }
742
743 inline COLVARS_HOST_DEVICE rvector(cvm::real x_i, cvm::real y_i, cvm::real z_i)
744 {
745 set(x_i, y_i, z_i);
746 }
747
748 inline rvector(cvm::vector1d<cvm::real> const &v)
749 {
750 set(v[0], v[1], v[2]);
751 }
752
753 inline COLVARS_HOST_DEVICE rvector(cvm::real t)
754 {
755 set(t);
756 }
757
759 inline COLVARS_HOST_DEVICE void set(cvm::real value)
760 {
761 x = y = z = value;
762 }
763
765 inline COLVARS_HOST_DEVICE void set(cvm::real x_i, cvm::real y_i, cvm::real z_i)
766 {
767 x = x_i;
768 y = y_i;
769 z = z_i;
770 }
771
773 inline COLVARS_HOST_DEVICE cvm::real & operator [] (int i) {
774 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
775 }
776
778 inline COLVARS_HOST_DEVICE cvm::real operator [] (int i) const {
779 return (i == 0) ? x : (i == 1) ? y : (i == 2) ? z : x;
780 }
781
782 inline cvm::vector1d<cvm::real> const as_vector() const
783 {
784 cvm::vector1d<cvm::real> result(3);
785 result[0] = this->x;
786 result[1] = this->y;
787 result[2] = this->z;
788 return result;
789 }
790
791 inline COLVARS_HOST_DEVICE void operator += (cvm::rvector const &v)
792 {
793 x += v.x;
794 y += v.y;
795 z += v.z;
796 }
797
798 inline COLVARS_HOST_DEVICE void operator -= (cvm::rvector const &v)
799 {
800 x -= v.x;
801 y -= v.y;
802 z -= v.z;
803 }
804
805 inline COLVARS_HOST_DEVICE void operator *= (cvm::real v)
806 {
807 x *= v;
808 y *= v;
809 z *= v;
810 }
811
812 inline COLVARS_HOST_DEVICE void operator /= (cvm::real const& v)
813 {
814 x /= v;
815 y /= v;
816 z /= v;
817 }
818
819 inline COLVARS_HOST_DEVICE cvm::real norm2() const
820 {
821 return (x*x + y*y + z*z);
822 }
823
824 inline COLVARS_HOST_DEVICE cvm::real norm() const
825 {
826#if (!defined(__HIP_DEVICE_COMPILE__)) || (!defined (__CUDA_ARCH__))
827#define COLVARS_MATH_SQRT ::sqrt
828#else
829#define COLVARS_MATH_SQRT cvm::sqrt
830#endif
831 return COLVARS_MATH_SQRT(this->norm2());
832#undef COLVARS_MATH_SQRT
833 }
834
835 inline COLVARS_HOST_DEVICE cvm::rvector unit() const
836 {
837 const cvm::real n = this->norm();
838 return (n > 0. ? cvm::rvector(x, y, z)/n : cvm::rvector(1., 0., 0.));
839 }
840
841 static inline size_t output_width(size_t real_width)
842 {
843 return 3*real_width + 10;
844 }
845
846
847 static inline COLVARS_HOST_DEVICE
848 cvm::rvector outer(cvm::rvector const &v1,
849 cvm::rvector const &v2)
850 {
851 return cvm::rvector( v1.y*v2.z - v2.y*v1.z,
852 -v1.x*v2.z + v2.x*v1.z,
853 v1.x*v2.y - v2.x*v1.y);
854 }
855
856 friend inline COLVARS_HOST_DEVICE cvm::rvector operator - (cvm::rvector const &v)
857 {
858 return cvm::rvector(-v.x, -v.y, -v.z);
859 }
860
861 friend inline COLVARS_HOST_DEVICE cvm::rvector operator + (cvm::rvector const &v1,
862 cvm::rvector const &v2)
863 {
864 return cvm::rvector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
865 }
866 friend inline COLVARS_HOST_DEVICE cvm::rvector operator - (cvm::rvector const &v1,
867 cvm::rvector const &v2)
868 {
869 return cvm::rvector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
870 }
871
873 friend inline COLVARS_HOST_DEVICE cvm::real operator * (cvm::rvector const &v1,
874 cvm::rvector const &v2)
875 {
876 return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
877 }
878
879 friend inline COLVARS_HOST_DEVICE cvm::rvector operator * (cvm::real a, cvm::rvector const &v)
880 {
881 return cvm::rvector(a*v.x, a*v.y, a*v.z);
882 }
883
884 friend inline COLVARS_HOST_DEVICE cvm::rvector operator * (cvm::rvector const &v, cvm::real a)
885 {
886 return cvm::rvector(a*v.x, a*v.y, a*v.z);
887 }
888
889 friend inline COLVARS_HOST_DEVICE cvm::rvector operator / (cvm::rvector const &v, cvm::real a)
890 {
891 return cvm::rvector(v.x/a, v.y/a, v.z/a);
892 }
893
894 std::string to_simple_string() const;
895 int from_simple_string(std::string const &s);
896};
897
898
902
903public:
904
905 cvm::real xx, xy, xz, yx, yy, yz, zx, zy, zz;
906
908 inline COLVARS_HOST_DEVICE rmatrix()
909 {
910 reset();
911 }
912
914 inline COLVARS_HOST_DEVICE
916 cvm::real yxi, cvm::real yyi, cvm::real yzi,
917 cvm::real zxi, cvm::real zyi, cvm::real zzi)
918 {
919 xx = xxi;
920 xy = xyi;
921 xz = xzi;
922 yx = yxi;
923 yy = yyi;
924 yz = yzi;
925 zx = zxi;
926 zy = zyi;
927 zz = zzi;
928 }
929
930
931 inline COLVARS_HOST_DEVICE void reset()
932 {
933 xx = xy = xz = yx = yy = yz = zx = zy = zz = 0.0;
934 }
935
937 inline COLVARS_HOST_DEVICE cvm::real determinant() const
938 {
939 return
940 ( xx * (yy*zz - zy*yz))
941 - (yx * (xy*zz - zy*xz))
942 + (zx * (xy*yz - yy*xz));
943 }
944
945 inline COLVARS_HOST_DEVICE cvm::rmatrix transpose() const
946 {
947 return cvm::rmatrix(xx, yx, zx,
948 xy, yy, zy,
949 xz, yz, zz);
950 }
951
952 inline COLVARS_HOST_DEVICE friend cvm::rvector operator * (cvm::rmatrix const &m,
953 cvm::rvector const &r)
954 {
955 return cvm::rvector(m.xx*r.x + m.xy*r.y + m.xz*r.z,
956 m.yx*r.x + m.yy*r.y + m.yz*r.z,
957 m.zx*r.x + m.zy*r.y + m.zz*r.z);
958 }
959
960 inline COLVARS_HOST_DEVICE rmatrix& operator+=(const rmatrix& rhs) {
961 this->xx += rhs.xx;
962 this->xy += rhs.xy;
963 this->xz += rhs.xz;
964 this->yx += rhs.yx;
965 this->yy += rhs.yy;
966 this->yz += rhs.yz;
967 this->zx += rhs.zx;
968 this->zy += rhs.zy;
969 this->zz += rhs.zz;
970 return *this;
971 }
972};
973
974
975
979
980public:
981
982 cvm::real q0, q1, q2, q3;
983
985 inline COLVARS_HOST_DEVICE quaternion(cvm::real const qv[4])
986 : q0(qv[0]), q1(qv[1]), q2(qv[2]), q3(qv[3])
987 {}
988
990 inline COLVARS_HOST_DEVICE quaternion(cvm::real q0i,
991 cvm::real q1i,
992 cvm::real q2i,
993 cvm::real q3i)
994 : q0(q0i), q1(q1i), q2(q2i), q3(q3i)
995 {}
996
997 inline quaternion(cvm::vector1d<cvm::real> const &v)
998 : q0(v[0]), q1(v[1]), q2(v[2]), q3(v[3])
999 {}
1000
1002 inline COLVARS_HOST_DEVICE quaternion()
1003 {
1004 reset();
1005 }
1006
1008 inline COLVARS_HOST_DEVICE void reset()
1009 {
1010 q0 = q1 = q2 = q3 = 0.0;
1011 }
1012
1014 static inline size_t output_width(size_t real_width)
1015 {
1016 return 4*real_width + 13;
1017 }
1018
1019 std::string to_simple_string() const;
1020 int from_simple_string(std::string const &s);
1021
1023 friend std::ostream & operator << (std::ostream &os, cvm::quaternion const &q);
1025 friend std::istream & operator >> (std::istream &is, cvm::quaternion &q);
1026
1028 inline COLVARS_HOST_DEVICE cvm::real & operator [] (int i) {
1029 switch (i) {
1030 case 0:
1031 return this->q0;
1032 case 1:
1033 return this->q1;
1034 case 2:
1035 return this->q2;
1036 case 3:
1037 return this->q3;
1038 default:
1039#if !(defined(__NVCC__) || defined(__HIPCC__))
1040 cvm::error("Error: incorrect quaternion component.\n");
1041#endif
1042 return q0;
1043 }
1044 }
1045
1047 inline COLVARS_HOST_DEVICE cvm::real operator [] (int i) const {
1048 switch (i) {
1049 case 0:
1050 return this->q0;
1051 case 1:
1052 return this->q1;
1053 case 2:
1054 return this->q2;
1055 case 3:
1056 return this->q3;
1057 default:
1058#if !(defined(__NVCC__) || defined(__HIPCC__))
1059 cvm::error("Error: trying to access a quaternion "
1060 "component which is not between 0 and 3.\n");
1061#endif
1062 return 0.0;
1063 }
1064 }
1065
1066 inline cvm::vector1d<cvm::real> const as_vector() const
1067 {
1068 cvm::vector1d<cvm::real> result(4);
1069 result[0] = q0;
1070 result[1] = q1;
1071 result[2] = q2;
1072 result[3] = q3;
1073 return result;
1074 }
1075
1077 inline COLVARS_HOST_DEVICE cvm::real norm2() const
1078 {
1079 return q0*q0 + q1*q1 + q2*q2 + q3*q3;
1080 }
1081
1083 inline COLVARS_HOST_DEVICE cvm::real norm() const
1084 {
1085#if (!defined(__HIP_DEVICE_COMPILE__)) || (!defined (__CUDA_ARCH__))
1086#define COLVARS_MATH_SQRT ::sqrt
1087#else
1088#define COLVARS_MATH_SQRT cvm::sqrt
1089#endif
1090 return COLVARS_MATH_SQRT(this->norm2());
1091#undef COLVARS_MATH_SQRT
1092 }
1093
1095 inline COLVARS_HOST_DEVICE cvm::quaternion conjugate() const
1096 {
1097 return cvm::quaternion(q0, -q1, -q2, -q3);
1098 }
1099
1100 inline COLVARS_HOST_DEVICE void operator *= (cvm::real a)
1101 {
1102 q0 *= a; q1 *= a; q2 *= a; q3 *= a;
1103 }
1104
1105 inline COLVARS_HOST_DEVICE void operator /= (cvm::real a)
1106 {
1107 q0 /= a; q1 /= a; q2 /= a; q3 /= a;
1108 }
1109
1110 inline COLVARS_HOST_DEVICE void set_positive()
1111 {
1112 if (q0 > 0.0) return;
1113 q0 = -q0;
1114 q1 = -q1;
1115 q2 = -q2;
1116 q3 = -q3;
1117 }
1118
1119 inline COLVARS_HOST_DEVICE void operator += (cvm::quaternion const &h)
1120 {
1121 q0+=h.q0; q1+=h.q1; q2+=h.q2; q3+=h.q3;
1122 }
1123 inline COLVARS_HOST_DEVICE void operator -= (cvm::quaternion const &h)
1124 {
1125 q0-=h.q0; q1-=h.q1; q2-=h.q2; q3-=h.q3;
1126 }
1127
1129 inline COLVARS_HOST_DEVICE cvm::rvector get_vector() const
1130 {
1131 return cvm::rvector(q1, q2, q3);
1132 }
1133
1134
1135 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator + (cvm::quaternion const &h,
1136 cvm::quaternion const &q)
1137 {
1138 return cvm::quaternion(h.q0+q.q0, h.q1+q.q1, h.q2+q.q2, h.q3+q.q3);
1139 }
1140
1141 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator - (cvm::quaternion const &h,
1142 cvm::quaternion const &q)
1143 {
1144 return cvm::quaternion(h.q0-q.q0, h.q1-q.q1, h.q2-q.q2, h.q3-q.q3);
1145 }
1146
1149 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::quaternion const &h,
1150 cvm::quaternion const &q)
1151 {
1152 return cvm::quaternion(h.q0*q.q0 - h.q1*q.q1 - h.q2*q.q2 - h.q3*q.q3,
1153 h.q0*q.q1 + h.q1*q.q0 + h.q2*q.q3 - h.q3*q.q2,
1154 h.q0*q.q2 + h.q2*q.q0 + h.q3*q.q1 - h.q1*q.q3,
1155 h.q0*q.q3 + h.q3*q.q0 + h.q1*q.q2 - h.q2*q.q1);
1156 }
1157
1158 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::real c,
1159 cvm::quaternion const &q)
1160 {
1161 return cvm::quaternion(c*q.q0, c*q.q1, c*q.q2, c*q.q3);
1162 }
1163 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator * (cvm::quaternion const &q,
1164 cvm::real c)
1165 {
1166 return cvm::quaternion(q.q0*c, q.q1*c, q.q2*c, q.q3*c);
1167 }
1168 friend inline COLVARS_HOST_DEVICE cvm::quaternion operator / (cvm::quaternion const &q,
1169 cvm::real c)
1170 {
1171 return cvm::quaternion(q.q0/c, q.q1/c, q.q2/c, q.q3/c);
1172 }
1173
1174
1177 inline COLVARS_HOST_DEVICE cvm::rvector rotate(cvm::rvector const &v) const
1178 {
1179 return ( (*this) * cvm::quaternion(0.0, v.x, v.y, v.z) *
1180 this->conjugate() ).get_vector();
1181 }
1182
1185 inline COLVARS_HOST_DEVICE cvm::quaternion rotate(cvm::quaternion const &Q2) const
1186 {
1187 cvm::rvector const vq_rot = this->rotate(Q2.get_vector());
1188 return cvm::quaternion(Q2.q0, vq_rot.x, vq_rot.y, vq_rot.z);
1189 }
1190
1192 inline COLVARS_HOST_DEVICE cvm::rmatrix rotation_matrix() const
1193 {
1194 cvm::rmatrix R;
1195
1196 R.xx = q0*q0 + q1*q1 - q2*q2 - q3*q3;
1197 R.yy = q0*q0 - q1*q1 + q2*q2 - q3*q3;
1198 R.zz = q0*q0 - q1*q1 - q2*q2 + q3*q3;
1199
1200 R.xy = 2.0 * (q1*q2 - q0*q3);
1201 R.xz = 2.0 * (q0*q2 + q1*q3);
1202
1203 R.yx = 2.0 * (q0*q3 + q1*q2);
1204 R.yz = 2.0 * (q2*q3 - q0*q1);
1205
1206 R.zx = 2.0 * (q1*q3 - q0*q2);
1207 R.zy = 2.0 * (q0*q1 + q2*q3);
1208
1209 return R;
1210 }
1211
1246 template <typename T>
1247 inline COLVARS_HOST_DEVICE T derivative_element_wise_product_sum(const cvm::real (&C)[3][3]) const {
1248 return T{{
1249 2.0 * ( q0 * C[0][0] - q3 * C[0][1] + q2 * C[0][2] +
1250 q3 * C[1][0] + q0 * C[1][1] - q1 * C[1][2] +
1251 -q2 * C[2][0] + q1 * C[2][1] + q0 * C[2][2]),
1252 2.0 * ( q1 * C[0][0] + q2 * C[0][1] + q3 * C[0][2] +
1253 q2 * C[1][0] - q1 * C[1][1] - q0 * C[1][2] +
1254 q3 * C[2][0] + q0 * C[2][1] - q1 * C[2][2]),
1255 2.0 * (-q2 * C[0][0] + q1 * C[0][1] + q0 * C[0][2] +
1256 q1 * C[1][0] + q2 * C[1][1] + q3 * C[1][2] +
1257 -q0 * C[2][0] + q3 * C[2][1] - q2 * C[2][2]),
1258 2.0 * (-q3 * C[0][0] - q0 * C[0][1] + q1 * C[0][2] +
1259 q0 * C[1][0] - q3 * C[1][1] + q2 * C[1][2] +
1260 q1 * C[2][0] + q2 * C[2][1] + q3 * C[2][2])
1261 }};
1262 }
1263
1266 inline COLVARS_HOST_DEVICE cvm::real cosine(cvm::quaternion const &q) const
1267 {
1268 cvm::real const iprod = this->inner(q);
1269 return 2.0*iprod*iprod - 1.0;
1270 }
1271
1275 inline COLVARS_HOST_DEVICE cvm::real dist2(cvm::quaternion const &Q2) const
1276 {
1277 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
1278 this->q2*Q2.q2 + this->q3*Q2.q3;
1279#if (!defined(__HIP_DEVICE_COMPILE__)) || (!defined (__CUDA_ARCH__))
1280#define COLVARS_MATH_ACOS ::acos
1281#else
1282#define COLVARS_MATH_ACOS cvm::acos
1283#endif
1284 cvm::real const omega = COLVARS_MATH_ACOS( (cos_omega > 1.0) ? 1.0 :
1285 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
1286#undef COLVARS_MATH_ACOS
1287
1288 // get the minimum distance: x and -x are the same quaternion
1289 if (cos_omega > 0.0)
1290 return omega * omega;
1291 else
1292 return (PI-omega) * (PI-omega);
1293 }
1294
1297 inline COLVARS_HOST_DEVICE cvm::quaternion dist2_grad(cvm::quaternion const &Q2) const
1298 {
1299#if (!defined(__HIP_DEVICE_COMPILE__)) || (!defined (__CUDA_ARCH__))
1300#define COLVARS_MATH_ACOS ::acos
1301#define COLVARS_MATH_SIN ::sin
1302#define COLVARS_MATH_FABS ::fabs
1303#else
1304#define COLVARS_MATH_ACOS cvm::acos
1305#define COLVARS_MATH_SIN cvm::sin
1306#define COLVARS_MATH_FABS cvm::fabs
1307#endif
1308 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 + this->q2*Q2.q2 + this->q3*Q2.q3;
1309 cvm::real const omega = COLVARS_MATH_ACOS( (cos_omega > 1.0) ? 1.0 :
1310 ( (cos_omega < -1.0) ? -1.0 : cos_omega) );
1311 cvm::real const sin_omega = COLVARS_MATH_SIN(omega);
1312
1313 if (COLVARS_MATH_FABS(sin_omega) < 1.0E-14) {
1314 // return a null 4d vector
1315 return cvm::quaternion(0.0, 0.0, 0.0, 0.0);
1316 }
1317#undef COLVARS_MATH_ACOS
1318#undef COLVARS_MATH_SIN
1319#undef COLVARS_MATH_FABS
1320 cvm::quaternion const
1321 grad1((-1.0)*sin_omega*Q2.q0 + cos_omega*(this->q0-cos_omega*Q2.q0)/sin_omega,
1322 (-1.0)*sin_omega*Q2.q1 + cos_omega*(this->q1-cos_omega*Q2.q1)/sin_omega,
1323 (-1.0)*sin_omega*Q2.q2 + cos_omega*(this->q2-cos_omega*Q2.q2)/sin_omega,
1324 (-1.0)*sin_omega*Q2.q3 + cos_omega*(this->q3-cos_omega*Q2.q3)/sin_omega);
1325
1326 if (cos_omega > 0.0) {
1327 return 2.0*omega*grad1;
1328 } else {
1329 return -2.0*(PI-omega)*grad1;
1330 }
1331 }
1332
1335 inline COLVARS_HOST_DEVICE void match(cvm::quaternion &Q2) const
1336 {
1337 cvm::real const cos_omega = this->q0*Q2.q0 + this->q1*Q2.q1 +
1338 this->q2*Q2.q2 + this->q3*Q2.q3;
1339 if (cos_omega < 0.0) Q2 *= -1.0;
1340 }
1341
1344 inline COLVARS_HOST_DEVICE cvm::real inner(cvm::quaternion const &Q2) const
1345 {
1346 cvm::real const prod = this->q0*Q2.q0 + this->q1*Q2.q1 +
1347 this->q2*Q2.q2 + this->q3*Q2.q3;
1348 return prod;
1349 }
1350
1351
1352};
1353
1354#ifndef COLVARS_LAMMPS
1355namespace NR {
1356int diagonalize_matrix(cvm::real m[4][4],
1357 cvm::real eigval[4],
1358 cvm::real eigvec[4][4]);
1359}
1360#endif
1361
1362
1366{
1367private:
1370
1373
1376
1379
1382
1383public:
1386
1388 cvm::quaternion q{1.0, 0.0, 0.0, 0.0};
1389
1390 friend struct rotation_derivative;
1391 friend class cvm::atom_group;
1392
1393 cvm::real* get_S() {return (cvm::real*)S;}
1394 cvm::real* get_eigenvectors() {return (cvm::real*)S_eigvec;}
1395 cvm::real* get_eigenvalues() {return S_eigval;}
1396 cvm::quaternion* get_q() {return &q;}
1397 cvm::real* get_S_backup() {return (cvm::real*)S_backup;}
1398 cvm::rmatrix* get_C() {return &C;}
1399
1406 void debug_gradients(
1407 cvm::rotation &rot,
1408 const cvm::ag_vector_real_t &pos1,
1409 const cvm::ag_vector_real_t &pos2,
1410 const size_t num_atoms_pos1,
1411 const size_t num_atoms_pos2);
1412
1423 void calc_optimal_rotation(std::vector<atom_pos> const &pos1,
1424 std::vector<atom_pos> const &pos2);
1425 void calc_optimal_rotation_soa(
1426 cvm::ag_vector_real_t const &pos1,
1427 cvm::ag_vector_real_t const &pos2,
1428 const size_t num_atoms_pos1,
1429 const size_t num_atoms_pos2);
1430
1432 int init();
1433
1435 rotation();
1436
1438 rotation(cvm::quaternion const &qi);
1439
1441 rotation(cvm::real angle, cvm::rvector const &axis);
1442
1444 ~rotation();
1445
1447 inline cvm::rvector rotate(cvm::rvector const &v) const
1448 {
1449 return q.rotate(v);
1450 }
1451
1453 inline cvm::rotation inverse() const
1454 {
1455 return cvm::rotation(this->q.conjugate());
1456 }
1457
1459 inline cvm::rmatrix matrix() const
1460 {
1461 return q.rotation_matrix();
1462 }
1463
1466 inline cvm::real spin_angle(cvm::rvector const &axis) const
1467 {
1468 cvm::rvector const q_vec = q.get_vector();
1469 cvm::real alpha = (180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
1470 while (alpha > 180.0) alpha -= 360;
1471 while (alpha < -180.0) alpha += 360;
1472 return alpha;
1473 }
1474
1478 {
1479 cvm::rvector const q_vec = q.get_vector();
1480 cvm::real const iprod = axis * q_vec;
1481
1482 if (q.q0 != 0.0) {
1483
1484 cvm::real const dspindx =
1485 (180.0/PI) * 2.0 * (1.0 / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1486
1487 return cvm::quaternion( dspindx * (iprod * (-1.0) / (q.q0*q.q0)),
1488 dspindx * ((1.0/q.q0) * axis.x),
1489 dspindx * ((1.0/q.q0) * axis.y),
1490 dspindx * ((1.0/q.q0) * axis.z));
1491 } else {
1492 // (1/(1+x^2)) ~ (1/x)^2
1493 // The documentation of spinAngle discourages its use when q_vec and
1494 // axis are not close
1495 return cvm::quaternion((180.0/PI) * 2.0 * ((-1.0)/iprod), 0.0, 0.0, 0.0);
1496 }
1497 }
1498
1501 inline cvm::real cos_theta(cvm::rvector const &axis) const
1502 {
1503 cvm::rvector const q_vec = q.get_vector();
1504 cvm::real const alpha =
1505 (180.0/PI) * 2.0 * cvm::atan2(axis * q_vec, q.q0);
1506
1507 cvm::real const cos_spin_2 = cvm::cos(alpha * (PI/180.0) * 0.5);
1508 cvm::real const cos_theta_2 = ( (cos_spin_2 != 0.0) ?
1509 (q.q0 / cos_spin_2) :
1510 (0.0) );
1511 // cos(2t) = 2*cos(t)^2 - 1
1512 return 2.0 * (cos_theta_2*cos_theta_2) - 1.0;
1513 }
1514
1517 {
1518 cvm::rvector const q_vec = q.get_vector();
1519 cvm::real const iprod = axis * q_vec;
1520
1521 cvm::real const cos_spin_2 = cvm::cos(cvm::atan2(iprod, q.q0));
1522
1523 if (q.q0 != 0.0) {
1524
1525 cvm::real const d_cos_theta_dq0 =
1526 (4.0 * q.q0 / (cos_spin_2*cos_spin_2)) *
1527 (1.0 - (iprod*iprod)/(q.q0*q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1528
1529 cvm::real const d_cos_theta_dqn =
1530 (4.0 * q.q0 / (cos_spin_2*cos_spin_2) *
1531 (iprod/q.q0) / (1.0 + (iprod*iprod)/(q.q0*q.q0)));
1532
1533 return cvm::quaternion(d_cos_theta_dq0,
1534 d_cos_theta_dqn * axis.x,
1535 d_cos_theta_dqn * axis.y,
1536 d_cos_theta_dqn * axis.z);
1537 } else {
1538
1539 cvm::real const d_cos_theta_dqn =
1540 (4.0 / (cos_spin_2*cos_spin_2 * iprod));
1541
1542 return cvm::quaternion(0.0,
1543 d_cos_theta_dqn * axis.x,
1544 d_cos_theta_dqn * axis.y,
1545 d_cos_theta_dqn * axis.z);
1546 }
1547 }
1548
1553
1554protected:
1555
1560
1562 void build_correlation_matrix(std::vector<cvm::atom_pos> const &pos1,
1563 std::vector<cvm::atom_pos> const &pos2);
1564
1567
1570
1572 void *jacobi;
1573};
1574
1575#if defined (COLVARS_CUDA) || defined (COLVARS_HIP)
1576namespace colvars_gpu {
1577class jacobi_gpu;
1579private:
1580 // cudaStream_t stream;
1582 // cvm::rmatrix* d_C;
1595 // cvm::real* d_S_backup;
1597 // jacobi_gpu* jacobi;
1599 unsigned int* tbcount;
1604 int* discontinuous_rotation;
1611 cvm::real* h_S;
1612 cvm::real* h_S_eigval;
1613 cvm::real* h_S_eigvec;
1614public:
1616 rotation_gpu();
1618 ~rotation_gpu();
1620 bool initialized() const {return b_initialized;}
1622 int init(/*const cudaStream_t& stream_in*/);
1634 cvm::real* const d_pos1,
1635 cvm::real* const d_pos2,
1636 const size_t num_atoms_pos1,
1637 const size_t num_atoms_pos2,
1638 cudaGraph_t& graph,
1639 std::unordered_map<std::string, cudaGraphNode_t>& nodes_map);
1642 void after_sync_check() const;
1643
1644 friend struct rotation_derivative_gpu;
1645 cvm::real* get_S() const {return d_S;}
1646 cvm::real* get_eigenvectors() const {return d_S_eigvec;}
1647 cvm::real* get_eigenvalues() const {return d_S_eigval;}
1648 cvm::quaternion* get_q() const {return d_q;}
1649
1650 void to_cpu(cvm::rotation& rot) const;
1651};
1652}
1653#endif // defined(COLVARS_CUDA) || defined(COLVARS_HIP)
1654
1655#endif
Definition: colvartypes.h:384
Arbitrary size array (two dimensions) suitable for linear algebra operations (i.e....
Definition: colvartypes.h:375
matrix2d(matrix2d< T > const &m)
Copy constructor.
Definition: colvartypes.h:493
T ** c_array()
Return the 2-d C array.
Definition: colvartypes.h:542
void clear()
Deallocation routine.
Definition: colvartypes.h:462
~matrix2d()
Destructor.
Definition: colvartypes.h:503
std::vector< T > const & data_array() const
Return a reference to the data.
Definition: colvartypes.h:514
matrix2d< T > & operator=(matrix2d< T > const &m)
Assignment.
Definition: colvartypes.h:529
matrix2d()
Default constructor.
Definition: colvartypes.h:479
std::vector< T > & data_array()
Return a reference to the data.
Definition: colvartypes.h:508
void resize(size_t const ol, size_t const il)
Allocation routine, used by all constructors.
Definition: colvartypes.h:419
friend std::ostream & operator<<(std::ostream &os, matrix2d< T > const &m)
Formatted output.
Definition: colvartypes.h:669
void reset()
Set all elements to zero.
Definition: colvartypes.h:468
1-dimensional vector of real numbers with four components and a quaternion algebra
Definition: colvartypes.h:978
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:1149
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:1177
COLVARS_HOST_DEVICE cvm::real & operator[](int i)
Access the quaternion as a 4-d array (return a reference)
Definition: colvartypes.h:1028
COLVARS_HOST_DEVICE quaternion(cvm::real q0i, cvm::real q1i, cvm::real q2i, cvm::real q3i)
Constructor component by component.
Definition: colvartypes.h:990
friend std::istream & operator>>(std::istream &is, cvm::quaternion &q)
Formatted input operator.
Definition: colvartypes.cpp:129
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:1185
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:1335
COLVARS_HOST_DEVICE quaternion()
Default constructor.
Definition: colvartypes.h:1002
COLVARS_HOST_DEVICE cvm::quaternion conjugate() const
Return the conjugate quaternion.
Definition: colvartypes.h:1095
COLVARS_HOST_DEVICE cvm::real norm2() const
Square norm of the quaternion.
Definition: colvartypes.h:1077
friend std::ostream & operator<<(std::ostream &os, cvm::quaternion const &q)
Formatted output operator.
Definition: colvartypes.cpp:110
COLVARS_HOST_DEVICE cvm::real norm() const
Norm of the quaternion.
Definition: colvartypes.h:1083
COLVARS_HOST_DEVICE void reset()
Set all components to zero (null quaternion)
Definition: colvartypes.h:1008
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:1275
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:1014
COLVARS_HOST_DEVICE cvm::rvector get_vector() const
Return the vector component.
Definition: colvartypes.h:1129
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:1344
COLVARS_HOST_DEVICE cvm::quaternion dist2_grad(cvm::quaternion const &Q2) const
Definition: colvartypes.h:1297
COLVARS_HOST_DEVICE cvm::rmatrix rotation_matrix() const
Return the 3x3 matrix associated to this quaternion.
Definition: colvartypes.h:1192
COLVARS_HOST_DEVICE quaternion(cvm::real const qv[4])
Constructor component by component.
Definition: colvartypes.h:985
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:1247
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:1266
2-dimensional array of real numbers with three components along each dimension (works with colvarmodu...
Definition: colvartypes.h:901
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:915
COLVARS_HOST_DEVICE rmatrix()
Default constructor.
Definition: colvartypes.h:908
COLVARS_HOST_DEVICE cvm::real determinant() const
Return the determinant.
Definition: colvartypes.h:937
A rotation between two sets of coordinates (for the moment a wrapper for colvarmodule::quaternion)
Definition: colvartypes.h:1366
~rotation()
Destructor.
Definition: colvartypes.cpp:204
cvm::rmatrix C
Correlation matrix C (3, 3)
Definition: colvartypes.h:1369
rotation()
Default constructor.
Definition: colvartypes.cpp:166
cvm::real cos_theta(cvm::rvector const &axis) const
Return the projection of the orientation vector onto a predefined axis.
Definition: colvartypes.h:1501
cvm::real S_eigval[4]
Eigenvalues of S.
Definition: colvartypes.h:1375
cvm::real S_backup[4][4]
Used for debugging gradients.
Definition: colvartypes.h:1381
cvm::rvector rotate(cvm::rvector const &v) const
Return the rotated vector.
Definition: colvartypes.h:1447
int init()
Initialize member data.
Definition: colvartypes.cpp:157
cvm::real S[4][4]
Overlap matrix S (4, 4)
Definition: colvartypes.h:1372
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:1477
cvm::quaternion dcos_theta_dq(cvm::rvector const &axis) const
Return the derivative of the tilt wrt the quaternion.
Definition: colvartypes.h:1516
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:1466
cvm::real S_eigvec[4][4]
Eigenvectors of S.
Definition: colvartypes.h:1378
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:385
static cvm::real crossing_threshold
Threshold for the eigenvalue crossing test.
Definition: colvartypes.h:1552
cvm::quaternion q_old
Previous value of the rotation (used to warn the user when the structure changes too much,...
Definition: colvartypes.h:1559
static bool monitor_crossings
Whether to test for eigenvalue crossing.
Definition: colvartypes.h:1550
bool b_debug_gradients
Perform gradient tests.
Definition: colvartypes.h:1385
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:215
cvm::rmatrix matrix() const
Return the associated 3x3 matrix.
Definition: colvartypes.h:1459
void * jacobi
Pointer to instance of Jacobi solver.
Definition: colvartypes.h:1572
void compute_overlap_matrix()
Compute the overlap matrix S (used by calc_optimal_rotation())
Definition: colvartypes.cpp:235
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:297
void calc_optimal_rotation_impl()
Actual implementation of calc_optimal_rotation (and called by it)
Definition: colvartypes.cpp:435
cvm::rotation inverse() const
Return the inverse of this rotation.
Definition: colvartypes.h:1453
cvm::quaternion q
The rotation itself (implemented as a quaternion)
Definition: colvartypes.h:1388
vector of real numbers with three components
Definition: colvartypes.h:726
COLVARS_HOST_DEVICE void reset()
Set all components to zero.
Definition: colvartypes.h:738
COLVARS_HOST_DEVICE void set(cvm::real value)
Set all components to a scalar.
Definition: colvartypes.h:759
friend COLVARS_HOST_DEVICE cvm::real operator*(cvm::rvector const &v1, cvm::rvector const &v2)
Inner (dot) product.
Definition: colvartypes.h:873
COLVARS_HOST_DEVICE void set(cvm::real x_i, cvm::real y_i, cvm::real z_i)
Assign all components.
Definition: colvartypes.h:765
COLVARS_HOST_DEVICE cvm::real & operator[](int i)
Access cartesian components by index.
Definition: colvartypes.h:773
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:98
static real cos(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:148
static int error(std::string const &message, int code=-1)
Print a message to the main log and set global error code.
Definition: colvarmodule.cpp:2181
static real atan2(real const &x, real const &y)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:193
static size_t const cv_prec
Number of digits to represent a collective variables value(s)
Definition: colvarmodule.h:708
static real sqrt(real const &x)
Reimplemented to work around MS compiler issues.
Definition: colvarmodule.h:136
static std::string to_str(char const *s)
Convert to string for output purposes.
Definition: colvarmodule.cpp:2536
Definition: colvartypes.h:1578
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:553
cvm::real * d_S_eigvec
Eigenvectors of S.
Definition: colvartypes.h:1593
cvm::real * d_S_eigval
Eigenvalues of S.
Definition: colvartypes.h:1586
int * max_iteration_reached
Flag for checking if eigendecomposition is failed.
Definition: colvartypes.h:1606
cvm::quaternion * d_q
The rotation itself (implemented as a quaternion)
Definition: colvartypes.h:1601
cvm::real * d_S
Correlation matrix C (3, 3)
Definition: colvartypes.h:1584
unsigned int * tbcount
Used for debugging gradients.
Definition: colvartypes.h:1599
int init()
Initialize member data.
Definition: colvartypes.cpp:524
void after_sync_check() const
Checking after synchronization ( eigendecomposition iterations and max crossing)
Definition: colvartypes.cpp:621
cvm::rmatrix * h_C
Host data for compatibility with CPU buffers.
Definition: colvartypes.h:1610
bool b_initialized
Flag for checking if initialized.
Definition: colvartypes.h:1608
~rotation_gpu()
Destructor.
Definition: colvartypes.cpp:507
cvm::quaternion * d_q_old
Crossing monitor.
Definition: colvartypes.h:1603
rotation_gpu()
Constructor.
Definition: colvartypes.cpp:497
bool initialized() const
Check if the object is initialized.
Definition: colvartypes.h:1620
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