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