BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSIntegratorEuler.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSIntegratorEuler.hh"
20#include "BDSUtilities.hh"
21
22#include "globals.hh" // geant4 types / globals
23#include "G4Mag_EqRhs.hh"
24#include "G4ThreeVector.hh"
25
26#include <cmath>
27
28BDSIntegratorEuler::BDSIntegratorEuler(G4Mag_EqRhs* eqOfMIn):
29 BDSIntegratorMag(eqOfMIn, 6)
30{;}
31
32void BDSIntegratorEuler::Stepper(const G4double yIn[],
33 const G4double dydx[],
34 G4double h,
35 G4double yOut[],
36 G4double yErr[])
37{
38 // In case of zero field or neutral particles do a linear step:
40 {
41 AdvanceDriftMag(yIn, h, yOut, yErr);
42 SetDistChord(0);
43 return;
44 }
45
46 const G4ThreeVector a_start = G4ThreeVector(dydx[3], dydx[4], dydx[5]);
47 if (a_start.mag2() < 1e-60)
48 {// no potential as no magnetic field - use drift routine
49 AdvanceDriftMag(yIn, h, yOut, yErr);
50 SetDistChord(0);
51 return;
52 }
53
54 const G4ThreeVector pos = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
55 const G4ThreeVector mom = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
56 // unit momentum already provided for us
57 const G4ThreeVector momU = G4ThreeVector(dydx[0], dydx[1], dydx[2]);
58 const G4double hSqrd = std::pow(h, 2);
59 const G4double hHalf = h*0.5;
60
61 // calcualte the position half step length for drifting with no force
62 // 'phalf' => plus half step
63 G4ThreeVector pos_phalf = pos + momU*hHalf;
64
65 // calculate the mid point if the particle were to drift. Momentum
66 // stays the same of course.
67 G4double midPointDrift[8];
68 G4double midPointDriftErr[8];
69 AdvanceDriftMag(yIn, hHalf, midPointDrift, midPointDriftErr);
70
71 G4double potential[8]; // output array for g4 query
72 RightHandSide(midPointDrift, potential); // query field and calculate vector potential
73 // get the vector potential bit from the array
74 G4ThreeVector a_phalf = G4ThreeVector(potential[3], potential[4], potential[5]);
75
76 // new coordinates
77 // pos_new = pos + p.unit()*h + (A*h^2)/2*p.mag()
78 // mom_new = mom + A*h
79 G4double factor = hSqrd*0.5/mom.mag(); // calculate common factors first
80 G4ThreeVector pos_new = pos + momU*h + a_phalf*factor;
81 G4ThreeVector mom_new = mom + a_phalf*h;
82
83 // error calculation
84 // use the difference in potential from beginning and midpoint to estimate
85 // how different output coordinates would've been
86 G4ThreeVector a_diff = a_phalf - a_start;
87 G4ThreeVector pos_err = a_diff*factor; // proportional to h^2
88 G4ThreeVector mom_err = a_diff*h;
89
90 // write out output values and errors to arrays
91 for (G4int i = 0; i < 3; i++)
92 {
93 yOut[i] = pos_new[i];
94 yOut[i+3] = mom_new[i];
95 yErr[i] = std::abs(pos_err[i]);
96 yErr[i+3] = std::abs(mom_err[i]);
97 }
98
99 // ((average of new and old) - mid point from drift ) .mag()
100 // both are straight lines, but it's an approximately close
101 G4double dc = (0.5*(pos_new + pos) - pos_phalf).mag();
102 SetDistChord(dc);
103}
void AdvanceDriftMag(const G4double yIn[], const G4double h, G4double yOut[], G4double yErr[]) const
Error array [6] all 0.
virtual void Stepper(const G4double yIn[], const G4double dydx[], G4double h, G4double yOut[], G4double yErr[])
Calculate output coordinates.
BDSIntegratorEuler()=delete
Private default constructor to force use of provided one.
Common functionality to BDSIM integrators.
G4Mag_EqRhs * eqOfM
void SetDistChord(G4double distChordIn)
Setter for distChord to private member.
G4bool IsFiniteStrength(G4double variable)