Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
quaternion.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef SRC_UTILS_INCLUDE_UTILS_QUATERNION_HPP
20#define SRC_UTILS_INCLUDE_UTILS_QUATERNION_HPP
21
22/**
23 * @file
24 *
25 * @brief Quaternion implementation and trait types
26 * for boost qvm interoperability.
27 */
28
29#include <boost/qvm/deduce_quat.hpp>
30#include <boost/qvm/deduce_scalar.hpp>
31#include <boost/qvm/deduce_vec.hpp>
32#include <boost/qvm/quat.hpp>
33#include <boost/qvm/quat_access.hpp>
34#include <boost/qvm/quat_operations.hpp>
35#include <boost/qvm/quat_traits.hpp>
36#include <boost/qvm/quat_vec_operations.hpp>
37
38#include <boost/serialization/array.hpp>
39#include <boost/serialization/is_bitwise_serializable.hpp>
40#include <boost/serialization/level.hpp>
41
42#include "utils/Array.hpp"
43#include "utils/Vector.hpp"
44#include "utils/matrix.hpp"
46
47#include <cassert>
48#include <cstddef>
49#include <type_traits>
50
51namespace Utils {
52
53/**
54 * Quaternion representation.
55 * @tparam T Element data type.
56 */
57template <typename T> struct Quaternion {
58 using container = typename Utils::Array<T, 4>;
60 using pointer = typename container::pointer;
61 using const_pointer = typename container::const_pointer;
62 using value_type = typename container::value_type;
63 using reference = typename container::reference;
64
65private:
67 template <class Archive> void serialize(Archive &ar, const unsigned int) {
68 ar & m_data;
69 }
70
71public:
72 /**
73 * @brief Normalize the quaternion in place.
74 */
75 void normalize() { boost::qvm::normalize(*this); }
76
77 /**
78 * @brief Retrieve a normalized copy of the quaternion.
79 * @return Normalized quaternion.
80 */
81 Quaternion<T> normalized() const { return boost::qvm::normalized(*this); }
82
83 /**
84 * @brief Element access (const).
85 * @param i Element index.
86 * @return Value of element @p i.
87 */
88 value_type operator[](std::size_t i) const { return m_data[i]; }
89 /**
90 * @brief Element access (non const).
91 * @param i Element index.
92 * @return Value of element @p i.
93 */
94 reference operator[](std::size_t i) { return m_data[i]; }
95
96 /**
97 * @brief Retrieve the norm of the quaternion.
98 * @return The norm.
99 */
100 value_type norm() const { return boost::qvm::mag(*this); }
101 /**
102 * @brief Retrieve the square of the norm of the quaternion.
103 * @return The squared norm.
104 */
105 value_type norm2() const { return boost::qvm::mag_sqr(*this); }
106
107 /**
108 * @brief Construct an identity quaternion.
109 * @return Identity quaternion.
110 */
111 static Quaternion<T> identity() { return boost::qvm::identity_quat<T>(); }
112
113 /**
114 * @brief Construct a zero quaternion.
115 * @return Quaternion with all elements set to zero.
116 */
117 static Quaternion<T> zero() { return boost::qvm::zero_quat<T>(); }
118
119 /**
120 * @brief Access to the underlying data (non const).
121 * @return Pointer to the first data member.
122 */
123 constexpr pointer data() { return m_data.data(); }
124
125 /**
126 * @brief Access to the underlying data (const).
127 * @return Pointer to the first data member.
128 */
129 constexpr const_pointer data() const noexcept { return m_data.data(); }
130};
131
132/**
133 * @brief Product quaternion and arithmetic type.
134 * @tparam T Data type of quaternion @p a.
135 * @tparam U Type of multiplier @p b.
136 * @param b Quaternion.
137 * @param a Multiplier.
138 * @return Multiplied quaternion.
139 */
140template <typename T, typename U,
141 std::enable_if_t<std::is_arithmetic_v<U>, bool> = true>
142Quaternion<T> operator*(const U &b, const Quaternion<T> &a) {
143 return boost::qvm::operator*(a, b);
144}
145
146/**
147 * @brief Convert quaternion to rotation matrix.
148 * @tparam T Data type of quaternion.
149 * @param q Quaternion.
150 * @return Rotation matrix.
151 */
152template <typename T> Matrix<T, 3, 3> rotation_matrix(Quaternion<T> const &q) {
153 auto const normed_q = q.normalized();
154 auto const id_mat = Utils::identity_mat<double, 3, 3>();
155 auto const v1 = normed_q * id_mat.col<0>();
156 auto const v2 = normed_q * id_mat.col<1>();
157 auto const v3 = normed_q * id_mat.col<2>();
158 return {{v1[0], v2[0], v3[0]}, {v1[1], v2[1], v3[1]}, {v1[2], v2[2], v3[2]}};
159}
160
161using boost::qvm::operator*;
162using boost::qvm::operator*=;
163using boost::qvm::operator==;
164using boost::qvm::dot;
165using boost::qvm::operator/;
166using boost::qvm::operator/=;
167using boost::qvm::operator+;
168using boost::qvm::operator+=;
169using boost::qvm::operator-;
170using boost::qvm::operator-=;
171
172} // namespace Utils
173
174namespace boost {
175
176namespace qvm {
177
178template <class T> struct quat_traits<Utils::Quaternion<T>> {
180 using scalar_type = T;
181
182 template <std::size_t I>
183 static constexpr inline scalar_type &write_element(quat_type &q) {
184 static_assert(I < 4, "Invalid index into quaternion.");
185 return q[I];
186 }
187
188 template <std::size_t I>
189 static constexpr inline scalar_type read_element(quat_type const &q) {
190 static_assert(I < 4, "Invalid index into quaternion.");
191 return q[I];
192 }
193
194 static inline scalar_type read_element_idx(std::size_t i,
195 quat_type const &q) {
196 assert(i < 4);
197 return q[i];
198 }
199
200 static inline scalar_type &write_element_idx(std::size_t i, quat_type &q) {
201 assert(i < 4);
202 return q[i];
203 }
204};
205
206template <typename T, typename U>
207struct deduce_scalar<Utils::Quaternion<T>, Utils::Quaternion<U>> {
208 using type = std::common_type_t<T, U>;
209};
210
211template <typename T, typename U, std::size_t N>
212struct deduce_scalar<Utils::Quaternion<T>, Utils::Vector<U, N>> {
213 using type = std::common_type_t<T, U>;
214};
215
216template <typename T, typename U>
217struct deduce_vec2<Utils::Quaternion<T>, Utils::Vector<U, 3>, 3> {
219};
220
221template <typename T> struct deduce_quat<Utils::Quaternion<T>> {
222 using type = typename Utils::Quaternion<T>;
223};
224
225template <typename T, typename U>
226struct deduce_quat2<Utils::Quaternion<T>, Utils::Quaternion<U>> {
228};
229
230} // namespace qvm
231
232} // namespace boost
233
235UTILS_ARRAY_BOOST_BIT_S(Utils::Quaternion, 0)
236UTILS_ARRAY_BOOST_CLASS(Utils::Quaternion, 0, object_serializable)
237UTILS_ARRAY_BOOST_TRACK(Utils::Quaternion, 0, track_never)
238
239#endif // SRC_UTILS_INCLUDE_UTILS_QUATERNION_HPP
Array implementation with CUDA support.
Vector implementation and trait types for boost qvm interoperability.
#define UTILS_ARRAY_BOOST_MPI_T(Container, N)
Mark array types as MPI data types.
Definition array.hpp:50
#define UTILS_ARRAY_BOOST_BIT_S(Container, N)
Mark array types as MPI bitwise serializable.
Definition array.hpp:63
#define UTILS_ARRAY_BOOST_CLASS(Container, N, ImplementationLevel)
Redefinition of BOOST_CLASS_IMPLEMENTATION for array types.
Definition array.hpp:78
#define UTILS_ARRAY_BOOST_TRACK(Container, N, TrackingLevel)
Redefinition of BOOST_CLASS_TRACKING for array types.
Definition array.hpp:97
Matrix implementation and trait types for boost qvm interoperability.
Quaternion< T > operator*(const U &b, const Quaternion< T > &a)
Product quaternion and arithmetic type.
Matrix< T, 3, 3 > rotation_matrix(Quaternion< T > const &q)
Convert quaternion to rotation matrix.
Matrix representation with static size.
Definition matrix.hpp:65
Quaternion representation.
typename container::const_pointer const_pointer
constexpr pointer data()
Access to the underlying data (non const).
typename container::pointer pointer
typename Utils::Array< T, 4 > container
static Quaternion< T > zero()
Construct a zero quaternion.
static Quaternion< T > identity()
Construct an identity quaternion.
value_type norm2() const
Retrieve the square of the norm of the quaternion.
Quaternion< T > normalized() const
Retrieve a normalized copy of the quaternion.
reference operator[](std::size_t i)
Element access (non const).
typename container::reference reference
value_type operator[](std::size_t i) const
Element access (const).
void normalize()
Normalize the quaternion in place.
typename container::value_type value_type
friend class boost::serialization::access
constexpr const_pointer data() const noexcept
Access to the underlying data (const).
value_type norm() const
Retrieve the norm of the quaternion.
typename Utils::Quaternion< std::common_type_t< T, U > > type
typename Utils::Vector< std::common_type_t< T, U >, 3 > type
static scalar_type read_element_idx(std::size_t i, quat_type const &q)
static scalar_type & write_element_idx(std::size_t i, quat_type &q)
static constexpr scalar_type & write_element(quat_type &q)
static constexpr scalar_type read_element(quat_type const &q)