200 const double qoverm,
const double vmag,
double bx,
double by,
double bz,
201 std::array<double, 3>& dir) {
203 double bmag = sqrt(bx * bx + by * by + bz * bz);
204 if (bmag < Garfield::Small) {
205 const double step = vmag * dt;
206 return {step * dir[0], step * dir[1], step * dir[2]};
208 std::array<std::array<double, 3>, 3> rot = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
213 const double bt = by * by + bz * bz;
214 if (bt > Garfield::Small) {
215 const double btInv = 1. / bt;
221 rot[1][1] = (bx * by * by + bz * bz) * btInv;
222 rot[2][2] = (bx * bz * bz + by * by) * btInv;
223 rot[1][2] = rot[2][1] = (bx - 1.) * by * bz * btInv;
224 }
else if (bx < 0.) {
229 bmag *= Garfield::Tesla2Internal;
230 const double omega = qoverm * Garfield::OmegaCyclotronOverB * bmag *
231 Garfield::ElectronMass;
232 const double cphi = cos(omega * dt);
233 const double sphi = sin(omega * dt);
236 std::array<double, 3> v0;
237 v0[0] = rot[0][0] * dir[0] + rot[0][1] * dir[1] + rot[0][2] * dir[2];
238 v0[1] = rot[1][0] * dir[0] + rot[1][1] * dir[1] + rot[1][2] * dir[2];
239 v0[2] = rot[2][0] * dir[0] + rot[2][1] * dir[1] + rot[2][2] * dir[2];
242 std::array<double, 3> v1;
244 v1[1] = v0[1] * cphi + v0[2] * sphi;
245 v1[2] = v0[2] * cphi - v0[1] * sphi;
248 dir[0] = rot[0][0] * v1[0] + rot[1][0] * v1[1] + rot[2][0] * v1[2];
249 dir[1] = rot[0][1] * v1[0] + rot[1][1] * v1[1] + rot[2][1] * v1[2];
250 dir[2] = rot[0][2] * v1[0] + rot[1][2] * v1[1] + rot[2][2] * v1[2];
253 const double rho = vmag / omega;
254 const double u = vmag * v0[0] * dt;
255 const double v = rho * (v0[1] * sphi + v0[2] * (1. - cphi));
256 const double w = rho * (v0[2] * sphi - v0[1] * (1. - cphi));
258 std::array<double, 3> pos;
259 pos[0] = rot[0][0] * u + rot[1][0] * v + rot[2][0] * w;
260 pos[1] = rot[0][1] * u + rot[1][1] * v + rot[2][1] * w;
261 pos[2] = rot[0][2] * u + rot[1][2] * v + rot[2][2] * w;
static std::array< double, 3 > StepBfield(const double dt, const double qoverm, const double vmag, double bx, double by, double bz, std::array< double, 3 > &dir)