MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
RotationMatrix.cc
1
4//
5// This file is part of MARLEY (Model of Argon Reaction Low Energy Yields)
6//
7// MARLEY is free software: you can redistribute it and/or modify it under the
8// terms of version 3 of the GNU General Public License as published by the
9// Free Software Foundation.
10//
11// For the full text of the license please see COPYING or
12// visit http://opensource.org/licenses/GPL-3.0
13//
14// Please respect the MCnet academic usage guidelines. See GUIDELINES
15// or visit https://www.montecarlonet.org/GUIDELINES for details.
16
17// Standard library includes
18#include <array>
19#include <cmath>
20#include <string>
21
22// HepMC3 includes
23#include "HepMC3/FourVector.h"
24#include "HepMC3/GenParticle.h"
25
26// MARLEY includes
27#include "marley/Error.hh"
28#include "marley/RotationMatrix.hh"
29#include "marley/hepmc3_utils.hh"
30
31using ThreeVector = std::array<double, 3>;
32
33// Anonymous namespace for helper functions
34namespace {
35
36 // Loads the 3-vector dest with the cross product v1 x v2
37 void cross_product(ThreeVector& dest,
38 const ThreeVector& v1, const ThreeVector& v2)
39 {
40 dest[0] = v1[1] * v2[2] - v1[2] * v2[1];
41 dest[1] = v1[2] * v2[0] - v1[0] * v2[2];
42 dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
43 }
44
45 // Returns the dot product v1 . v2
46 double dot_product(const ThreeVector& v1,
47 const ThreeVector& v2)
48 {
49 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
50 }
51
52 // Loads the 3-vector dest with the difference v1 - v2
53 void subtract(ThreeVector& dest,
54 const ThreeVector& v1, const ThreeVector& v2)
55 {
56 dest[0] = v1[0] - v2[0];
57 dest[1] = v1[1] - v2[1];
58 dest[2] = v1[2] - v2[2];
59 }
60
61}
62
64 : matrix_{{ {{ 1., 0., 0.}}, {{ 0., 1., 0.}}, {{ 0., 0., 1.}} }}
65{}
66
67// Returns a copy of the 3-vector v normalized to have unit magnitude
68ThreeVector marley::RotationMatrix::normalize(const ThreeVector& v)
69{
70 static ThreeVector nv({0., 0., 0.});
71 double norm_factor = std::sqrt(std::pow(v[0], 2) + std::pow(v[1], 2)
72 + std::pow(v[2], 2));
73 if (norm_factor <= 0.) throw marley::Error(std::string("Invalid vector")
74 + " magnitude encountered in marley::RotationMatrix::normalize()");
75 else norm_factor = 1. / norm_factor;
76 nv[0] = norm_factor * v[0];
77 nv[1] = norm_factor * v[1];
78 nv[2] = norm_factor * v[2];
79 return nv;
80}
81
82// Returns a rotated copy of the 3-vector v
83ThreeVector marley::RotationMatrix::rotate_copy(const ThreeVector& v)
84{
85 ThreeVector rv = {0., 0., 0.};
86 for (unsigned i = 0; i < 3; ++i) rv[i] = dot_product(matrix_[i], v);
87 return rv;
88}
89
90// Rotates a 3-vector v in place
92{
93 ThreeVector rv = {0., 0., 0.};
94 for (unsigned i = 0; i < 3; ++i) rv[i] = dot_product(matrix_[i], v);
95 v = rv;
96}
97
98// Rotates the 3-momentum of a HepMC3::GenParticle in place
100{
101 HepMC3::FourVector mom4 = p.momentum();
102
103 ThreeVector rv = { 0., 0., 0. };
104 ThreeVector three_momentum = { mom4.px(), mom4.py(), mom4.pz() };
105
106 for (unsigned i = 0; i < 3; ++i)
107 rv[i] = dot_product( matrix_[i], three_momentum );
108
109 mom4.set_px( rv[0] );
110 mom4.set_py( rv[1] );
111 mom4.set_pz( rv[2] );
112
113 p.set_momentum( mom4 );
114}
115
122marley::RotationMatrix::RotationMatrix(const ThreeVector& from_vec,
123 const ThreeVector& to_vec)
124{
125 static constexpr ThreeVector null_three_vector = { 0., 0., 0. };
126
127 if (from_vec == null_three_vector)
128 throw marley::Error(std::string("Null from vector")
129 + " passed to constructor of marley::RotationMatrix");
130 else if (to_vec == null_three_vector)
131 throw marley::Error(std::string("Null to vector")
132 + " passed to constructor of marley::RotationMatrix");
133
134 // The from and to vectors must be normalized to use this method, so make any
135 // necessary adjustments now.
136 ThreeVector from = normalize(from_vec);
137 ThreeVector to = normalize(to_vec);
138
139 double e = dot_product(from, to);
140 double f = std::abs(e);
141
142 static constexpr double EPSILON = 0.000001;
143 if (f > 1.0 - EPSILON) { // "from" and "to" vectors are almost parallel
144
145 // Temporary storage vectors
146 ThreeVector v;
147 ThreeVector u;
148
149 // Find the standard unit vector x most nearly orthogonal to "from"
150 ThreeVector x;
151 x[0] = std::abs(from[0]);
152 x[1] = std::abs(from[1]);
153 x[2] = std::abs(from[2]);
154
155 if (x[0] < x[1])
156 {
157 if (x[0] < x[2])
158 {
159 x[0] = 1.0; x[1] = x[2] = 0.0;
160 }
161 else
162 {
163 x[2] = 1.0; x[0] = x[1] = 0.0;
164 }
165 }
166 else
167 {
168 if (x[1] < x[2])
169 {
170 x[1] = 1.0; x[0] = x[2] = 0.0;
171 }
172 else
173 {
174 x[2] = 1.0; x[0] = x[1] = 0.0;
175 }
176 }
177
178 // u = x - from
179 subtract(u, x, from);
180
181 // v = x - to
182 subtract(v, x, to);
183
184 // coefficients for later use
185 double c1 = 2.0 / dot_product(u, u);
186 double c2 = 2.0 / dot_product(v, v);
187 double c3 = c1 * c2 * dot_product(u, v);
188
189 for (unsigned i = 0; i < 3; ++i) {
190 for (unsigned j = 0; j < 3; ++j) {
191 matrix_[i][j] = - c1 * u[i] * u[j] - c2 * v[i] * v[j]
192 + c3 * v[i] * u[j];
193 }
194 matrix_[i][i] += 1.0;
195 }
196 }
197 else // the most common case, unless "from" = "to", or "from" = -"to"
198 {
199 ThreeVector v;
200 cross_product(v, from, to); // v = from x to
201
202 // hand-optimized version (9 mults less than original)
203 // optimization by Gottfried Chen
204 double hvx, hvz, hvxy, hvxz, hvyz;
205 double h = 1.0 / (1.0 + e);
206 hvx = h * v[0];
207 hvz = h * v[2];
208 hvxy = hvx * v[1];
209 hvxz = hvx * v[2];
210 hvyz = hvz * v[1];
211
212 matrix_[0][0] = e + hvx * v[0];
213 matrix_[0][1] = hvxy - v[2];
214 matrix_[0][2] = hvxz + v[1];
215
216 matrix_[1][0] = hvxy + v[2];
217 matrix_[1][1] = e + h * v[1] * v[1];
218 matrix_[1][2] = hvyz - v[0];
219
220 matrix_[2][0] = hvxz - v[1];
221 matrix_[2][1] = hvyz + v[0];
222 matrix_[2][2] = e + hvz * v[2];
223 }
224}
Generic 4-vector.
Definition FourVector.h:36
void set_py(double pyy)
Set y-component of momentum.
Definition FourVector.h:123
void set_px(double pxx)
Set x-component of momentum.
Definition FourVector.h:116
double px() const
x-component of momentum
Definition FourVector.h:114
double py() const
y-component of momentum
Definition FourVector.h:121
double pz() const
z-component of momentum
Definition FourVector.h:128
void set_pz(double pzz)
Set z-component of momentum.
Definition FourVector.h:130
Stores particle-related information.
Definition GenParticle.h:34
void set_momentum(const FourVector &momentum)
Set momentum.
const FourVector & momentum() const
Get momentum.
Definition GenParticle.h:97
Base class for all exceptions thrown by MARLEY functions.
Definition Error.hh:26
void rotate_inplace(ThreeVector &v)
Rotate a 3-vector v in place.
RotationMatrix()
Creates a 3×3 identity matrix.
void rotate_particle_inplace(HepMC3::GenParticle &p)
Rotate the 3-momentum of a marley::Particle in place.
ThreeVector rotate_copy(const ThreeVector &v)
Create a rotated copy of the 3-vector v.
ThreeThreeMatrix matrix_
3×3 rotation matrix