Version: SMASH-3.4
threevector.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2015,2017-2020,2022,2024-2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_THREEVECTOR_H_
11 #define SRC_INCLUDE_SMASH_THREEVECTOR_H_
12 
13 #include <array>
14 #include <cmath>
15 #include <ostream>
16 
17 #include "constants.h"
18 
19 namespace smash {
20 
21 /**
22  * \ingroup data
23  *
24  * The ThreeVector class represents a physical three-vector
25  * \f$ \mathbf{x} = (x_1,x_2,x_3)\f$
26  * with the components \f$ x_1,x_2,x_3 \f$.
27  * It is related to the classes FourVector and Angles,
28  * both of which can be converted into a ThreeVector using
29  * the 'threevec()' method.
30  */
31 class ThreeVector {
32  public:
33  /// default constructor (nulls all components)
34  ThreeVector() : x_({0., 0., 0.}) {}
35 
36  /**
37  * Constructor for ThreeVector that takes 3 doubles to set up a ThreeVector
38  * with desired values for the components
39  *
40  * \param[in] y1 value of the first component
41  * \param[in] y2 value of the second component
42  * \param[in] y3 value of the third component
43  */
44  ThreeVector(double y1, double y2, double y3) : x_({y1, y2, y3}) {}
45 
46  /**
47  * Constructor for ThreeVector that takes an array of 3 doubles to set up a
48  * ThreeVector with desired values for the components
49  *
50  * \param[in] arr the 3-component array
51  */
52  explicit ThreeVector(std::array<double, 3> arr)
53  : x_({arr[0], arr[1], arr[2]}) {}
54 
55  /// access the component at offset \p i.
56  double &operator[](std::size_t i) { return x_[i]; }
57  /// const overload of the above.
58  double operator[](std::size_t i) const { return x_[i]; }
59 
60  /// \return first component
61  double inline x1() const;
62  /// set first component
63  void inline set_x1(double x);
64  /// \return second component
65  double inline x2() const;
66  /// set second component
67  void inline set_x2(double y);
68  /// \return third component
69  double inline x3() const;
70  /// set third component
71  void inline set_x3(double z);
72  /// \return the square of the vector (which is a scalar)
73  double inline sqr() const;
74  /// \return the absolute value
75  double inline abs() const;
76  /// \return the azimuthal angle phi
77  double inline get_phi() const;
78  /// \return the polar angle theta
79  double inline get_theta() const;
80  /**
81  * Rotate vector by the given Euler angles phi, theta, psi. If we
82  * assume the standard basis x, y, z, then this means applying the
83  * matrix for a rotation by phi about the z-axis, followed by the matrix for
84  * a rotation by theta about the rotated x-axis. Last, psi is a rotation
85  * about the rotated z-axis. To reverse the rotation one has to
86  * therefore exchange phi and psi and use the negative values for all angles.
87  * \param[in] phi angle by which the first rotation is done about the z-axis.
88  * Range: \f$[0,2\pi]\f$
89  * \param[in] theta angle by which the second rotation is done
90  * about the rotated x-axis. Range: \f$[0,\pi]\f$
91  * \param[in] psi angle by which the third rotation is done
92  * about the rotated z-axis. Range: \f$[0,2\pi]\f$
93  *
94  * Euler angles are used to make rotation of several (different) position
95  * vectors belonging to one rigid body easy. A ThreeVector could be rotated
96  * via only two angles, but then the angles for rotating a rigid body
97  * consisting of multiple particles would require a different pair of rotation
98  * angles for every position.
99  */
100  void inline rotate(double phi, double theta, double psi);
101  /**
102  * Rotate the vector around the y axis by the given angle theta.
103  * \param[in] theta angle by which the rotation is done about y axis.
104  */
105  void inline rotate_around_y(double theta);
106  /**
107  * Rotate the vector around the z axis by the given angle theta.
108  * \param[in] theta angle by which the rotation is done about z axis.
109  */
110  void inline rotate_around_z(double theta);
111  /**
112  * Rotate the z-axis onto the vector r.
113  * \param[in] r direction in which new z-axis is aligned
114  */
115  void inline rotate_z_axis_to(ThreeVector &r);
116  /// Negation: Returns \f$-\mathbf{x}\f$
117  ThreeVector inline operator-() const;
118  /**
119  * Increase this vector by \f$\mathbf{v}\f$:
120  * \f$ \mathbf{x}^\prime = \mathbf{x} + \mathbf{v} \f$
121  */
122  ThreeVector inline operator+=(const ThreeVector &v);
123  /**
124  * Decrease this vector by \f$\mathbf{v}\f$:
125  * \f$ \mathbf{x}^\prime = \mathbf{x} - \mathbf{v} \f$
126  */
127  ThreeVector inline operator-=(const ThreeVector &v);
128  /**
129  * Scale this vector by \f$a\f$:
130  * \f$ \mathbf{x}^\prime = a \cdot \mathbf{x} \f$
131  */
132  ThreeVector inline operator*=(const double &a);
133  /**
134  * Divide this vector by \f$a\f$:
135  * \f$ \mathbf x^\prime = \frac{1}{a} \cdot \mathbf{x}\f$
136  */
137  ThreeVector inline operator/=(const double &a);
138 
139  /// \return whether the vector is identical to another vector
140  bool operator==(const ThreeVector &rhs) const { return x_ == rhs.x_; }
141  /// \return whether the vector is different from another vector
142  bool operator!=(const ThreeVector &rhs) const { return x_ != rhs.x_; }
143 
144  /**
145  * \return cross product of this vector \f$\mathbf{x}\f$ and another vector:
146  * \f$ \mathbf{x} \times \mathbf{b} \f$
147  */
148  ThreeVector inline cross_product(const ThreeVector &b) const;
149  /// iterates over the components
150  using iterator = std::array<double, 3>::iterator;
151  /// iterates over the components
152  using const_iterator = std::array<double, 3>::const_iterator;
153 
154  /**
155  * \return an iterator starting at the 0th component.
156  *
157  * The iterator implements the randomIterator concept. Thus, you can simply
158  * write `begin() + 1` to get an iterator that points to the 1st component.
159  */
160  iterator begin() { return x_.begin(); }
161 
162  /// \return an iterator pointing after the 4th component.
163  iterator end() { return x_.end(); }
164 
165  /// const overload of the above
166  const_iterator begin() const { return x_.begin(); }
167  /// const overload of the above
168  const_iterator end() const { return x_.end(); }
169 
170  /// \see begin
171  const_iterator cbegin() const { return x_.cbegin(); }
172  /// \see end
173  const_iterator cend() const { return x_.cend(); }
174 
175  private:
176  /// the internal storage of the components.
177  std::array<double, 3> x_;
178 };
179 
180 /**
181  * \ingroup logging
182  * Writes the three components of the vector to the output stream.
183  */
184 std::ostream &operator<<(std::ostream &, const ThreeVector &);
185 
186 double inline ThreeVector::x1() const { return x_[0]; }
187 
188 void inline ThreeVector::set_x1(const double x) { x_[0] = x; }
189 
190 double inline ThreeVector::x2() const { return x_[1]; }
191 
192 void inline ThreeVector::set_x2(const double y) { x_[1] = y; }
193 
194 double inline ThreeVector::x3() const { return x_[2]; }
195 
196 void inline ThreeVector::set_x3(const double z) { x_[2] = z; }
197 
199  ThreeVector neg(-x_[0], -x_[1], -x_[2]);
200  return neg;
201 }
202 
204  x_[0] += v.x_[0];
205  x_[1] += v.x_[1];
206  x_[2] += v.x_[2];
207  return *this;
208 }
209 
210 /// \return sum of two three-vectors: \f$ \mathbf{a} + \mathbf{b} \f$.
212  a += b;
213  return a;
214 }
215 
217  x_[0] -= v.x_[0];
218  x_[1] -= v.x_[1];
219  x_[2] -= v.x_[2];
220  return *this;
221 }
222 
223 /// \return difference between two three-vectors: \f$\mathbf{a}-\mathbf{b}\f$.
225  a -= b;
226  return a;
227 }
228 
229 ThreeVector inline ThreeVector::operator*=(const double &a) {
230  x_[0] *= a;
231  x_[1] *= a;
232  x_[2] *= a;
233  return *this;
234 }
235 
236 /// multiply a three-vector by constant factor: \f$ b\cdot\mathbf{a} \f$.
237 inline ThreeVector operator*(ThreeVector a, const double &b) {
238  a *= b;
239  return a;
240 }
241 
242 /// multiply a three-vector by constant factor: \f$ a\cdot\mathbf{b} \f$.
243 inline ThreeVector operator*(const double &a, ThreeVector b) {
244  b *= a;
245  return b;
246 }
247 
248 /**
249  * \return inner product of two three-vectors: \f$\mathbf{a}\cdot\mathbf{b}\f$.
250  */
251 inline double operator*(ThreeVector a, const ThreeVector &b) {
252  return a.x1() * b.x1() + a.x2() * b.x2() + a.x3() * b.x3();
253 }
254 
256  return ThreeVector(x_[1] * b.x3() - x_[2] * b.x2(),
257  x_[2] * b.x1() - x_[0] * b.x3(),
258  x_[0] * b.x2() - x_[1] * b.x1());
259 }
260 
261 ThreeVector inline ThreeVector::operator/=(const double &a) {
262  const double a_inv = 1.0 / a;
263  x_[0] *= a_inv;
264  x_[1] *= a_inv;
265  x_[2] *= a_inv;
266  return *this;
267 }
268 
269 /// divide a three-vector by constant factor: \f$\mathbf{a}/b\f$.
270 ThreeVector inline operator/(ThreeVector a, const double &b) {
271  a /= b;
272  return a;
273 }
274 
275 double inline ThreeVector::sqr() const { return (*this) * (*this); }
276 
277 double inline ThreeVector::abs() const { return std::sqrt((*this) * (*this)); }
278 
279 double inline ThreeVector::get_phi() const {
280  if (std::abs(x1()) < really_small && std::abs(x2()) < really_small) {
281  return 0.;
282  } else {
283  return std::atan2(x2(), x1());
284  }
285 }
286 
287 double inline ThreeVector::get_theta() const {
288  double r = abs();
289  return (r > 0.) ? std::acos(x3() / r) : 0.;
290 }
291 
292 void inline ThreeVector::rotate(double phi, double theta, double psi) {
293  // Compute the cosine and sine for each angle.
294  const double cos_phi = std::cos(phi);
295  const double sin_phi = std::sin(phi);
296  const double cos_theta = std::cos(theta);
297  const double sin_theta = std::sin(theta);
298  const double cos_psi = std::cos(psi);
299  const double sin_psi = std::sin(psi);
300  // Get original coordinates.
301  std::array<double, 3> x_old = x_;
302  // Compute new coordinates.
303  x_[0] = (cos_phi * cos_psi - sin_phi * cos_theta * sin_psi) * x_old[0] +
304  (-cos_phi * sin_psi - sin_phi * cos_theta * cos_psi) * x_old[1] +
305  (sin_phi * sin_theta) * x_old[2];
306  x_[1] = (sin_phi * cos_psi + cos_phi * cos_theta * sin_psi) * x_old[0] +
307  (-sin_phi * sin_psi + cos_phi * cos_theta * cos_psi) * x_old[1] +
308  (-cos_phi * sin_theta) * x_old[2];
309  x_[2] = (sin_theta * sin_psi) * x_old[0] + (sin_theta * cos_psi) * x_old[1] +
310  (cos_theta)*x_old[2];
311 }
312 
313 void inline ThreeVector::rotate_around_y(double theta) {
314  const double cost = std::cos(theta);
315  const double sint = std::sin(theta);
316  // Get original coordinates.
317  std::array<double, 3> x_old = x_;
318  // Compute new coordinates.
319  x_[0] = cost * x_old[0] + sint * x_old[2];
320  // x_[1] is unchanged
321  x_[2] = -sint * x_old[0] + cost * x_old[2];
322 }
323 
324 void inline ThreeVector::rotate_around_z(double theta) {
325  const double cost = std::cos(theta);
326  const double sint = std::sin(theta);
327  // Get original coordinates.
328  std::array<double, 3> x_old = x_;
329  // Compute new coordinates.
330  x_[0] = cost * x_old[0] - sint * x_old[1];
331  x_[1] = sint * x_old[0] + cost * x_old[1];
332  // x_[2] is unchanged
333 }
334 
338 }
339 
340 } // namespace smash
341 
342 #endif // SRC_INCLUDE_SMASH_THREEVECTOR_H_
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
std::array< double, 3 > x_
the internal storage of the components.
Definition: threevector.h:177
double get_phi() const
Definition: threevector.h:279
ThreeVector operator-=(const ThreeVector &v)
Decrease this vector by : .
Definition: threevector.h:216
void set_x1(double x)
set first component
Definition: threevector.h:188
ThreeVector(double y1, double y2, double y3)
Constructor for ThreeVector that takes 3 doubles to set up a ThreeVector with desired values for the ...
Definition: threevector.h:44
double abs() const
Definition: threevector.h:277
double sqr() const
Definition: threevector.h:275
std::array< double, 3 >::iterator iterator
iterates over the components
Definition: threevector.h:150
iterator begin()
Definition: threevector.h:160
void rotate_around_y(double theta)
Rotate the vector around the y axis by the given angle theta.
Definition: threevector.h:313
double x3() const
Definition: threevector.h:194
const_iterator begin() const
const overload of the above
Definition: threevector.h:166
bool operator!=(const ThreeVector &rhs) const
Definition: threevector.h:142
const_iterator cbegin() const
Definition: threevector.h:171
void rotate_around_z(double theta)
Rotate the vector around the z axis by the given angle theta.
Definition: threevector.h:324
void set_x3(double z)
set third component
Definition: threevector.h:196
void rotate(double phi, double theta, double psi)
Rotate vector by the given Euler angles phi, theta, psi.
Definition: threevector.h:292
ThreeVector operator*=(const double &a)
Scale this vector by : .
Definition: threevector.h:229
double x2() const
Definition: threevector.h:190
double get_theta() const
Definition: threevector.h:287
void set_x2(double y)
set second component
Definition: threevector.h:192
bool operator==(const ThreeVector &rhs) const
Definition: threevector.h:140
void rotate_z_axis_to(ThreeVector &r)
Rotate the z-axis onto the vector r.
Definition: threevector.h:335
double x1() const
Definition: threevector.h:186
ThreeVector(std::array< double, 3 > arr)
Constructor for ThreeVector that takes an array of 3 doubles to set up a ThreeVector with desired val...
Definition: threevector.h:52
double & operator[](std::size_t i)
access the component at offset i.
Definition: threevector.h:56
ThreeVector operator+=(const ThreeVector &v)
Increase this vector by : .
Definition: threevector.h:203
ThreeVector operator/=(const double &a)
Divide this vector by : .
Definition: threevector.h:261
const_iterator cend() const
Definition: threevector.h:173
ThreeVector cross_product(const ThreeVector &b) const
Definition: threevector.h:255
double operator[](std::size_t i) const
const overload of the above.
Definition: threevector.h:58
ThreeVector()
default constructor (nulls all components)
Definition: threevector.h:34
const_iterator end() const
const overload of the above
Definition: threevector.h:168
ThreeVector operator-() const
Negation: Returns .
Definition: threevector.h:198
std::array< double, 3 >::const_iterator const_iterator
iterates over the components
Definition: threevector.h:152
Collection of useful constants that are known at compile time.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:546
Definition: action.h:24
EnergyMomentumTensor operator-(EnergyMomentumTensor a, const EnergyMomentumTensor &b)
Direct subtraction operator.
EnergyMomentumTensor operator*(EnergyMomentumTensor a, const double b)
Direct multiplication operator.
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:41
EnergyMomentumTensor operator+(EnergyMomentumTensor a, const EnergyMomentumTensor &b)
Direct addition operator.
EnergyMomentumTensor operator/(EnergyMomentumTensor a, const double b)
Direct division operator.