BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSIntegratorEulerOld.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 "BDSIntegratorEulerOld.hh"
20#include "BDSUtilities.hh"
21
22#include "globals.hh"
23#include "G4AffineTransform.hh"
24#include "G4Mag_EqRhs.hh"
25#include "G4ThreeVector.hh"
26
27#include <cmath>
28#include <stdexcept>
29
30BDSIntegratorEulerOld::BDSIntegratorEulerOld(G4Mag_EqRhs* eqOfMIn):
31 BDSIntegratorMag(eqOfMIn, 6)
32{;}
33
34void BDSIntegratorEulerOld::Stepper(const G4double yIn[],
35 const G4double dydx[],
36 const G4double h,
37 G4double yOut[],
38 G4double yErr[])
39{
40 // neutral particles do a linear step:
41 if (!BDS::IsFinite(eqOfM->FCof()) || zeroStrength)
42 {
43 AdvanceDriftMag(yIn, h, yOut, yErr);
44 SetDistChord(0);
45 return;
46 }
47
48 G4double yTemp[7];
49
50 G4ThreeVector pos = G4ThreeVector(yIn[0], yIn[1], yIn[2]);
51 G4ThreeVector mom = G4ThreeVector(yIn[3], yIn[4], yIn[5]);
52 G4ThreeVector momUnit = mom.unit();
53
54 auxNavigator->LocateGlobalPointAndSetup(pos);
55 G4AffineTransform GlobalAffine = auxNavigator->GetGlobalToLocalTransform();
56 G4ThreeVector localMomUnit = GlobalAffine.TransformAxis(momUnit);
57
58 if (localMomUnit.z() < 0.9 || mom.mag() < 40.0)
59 {
60 backupStepper->Stepper(yIn, dydx, h, yOut, yErr);
61 SetDistChord(backupStepper->DistChord());
62 return;
63 }
64
65 try
66 {
67 // do two half steps
68 G4double tempErr[7];
69 AdvanceHelix(yIn, 0.5*h, yTemp, tempErr);
70 AdvanceHelix(yTemp, 0.5*h, yOut, tempErr);
71
72 // do a full step
73 AdvanceHelix(yIn, h, yTemp, tempErr);
74
75 // Error is difference between two half steps and full step
76 for (G4int i = 0; i < nVariables; i++)
77 {yErr[i] = yOut[i] - yTemp[i];}
78 }
79 catch (const std::exception&)
80 {// thrown in case we should use a runge kutta
81 backupStepper->Stepper(yIn, dydx, h, yOut, yErr);
82 SetDistChord(backupStepper->DistChord());
83 }
84}
85
87 G4ThreeVector& localPos,
88 G4ThreeVector& localMom,
89 const G4ThreeVector& localA)
90{
91 // determine effective curvature
92 G4double localAMag = localA.mag();
93 if (BDS::IsFiniteStrength(localAMag))
94 {
95 // chord distance (simple quadratic approx)
96 G4double h2 = h*h;
97 G4double dc = h2*localAMag/8;
98 SetDistChord(dc);
99
100 G4double dx = localMom.x()*h + localA.x()*h2/2;
101 G4double dy = localMom.y()*h + localA.y()*h2/2;
102
103 // this can go negative for very long step queries that
104 // presumably cause a very large deflection. This results in nan
105 // and bad tracking from Geant4 / a crash. Throw exception that'll
106 // be caught higher up and the backup stepper will be used.
107 G4double dz = std::sqrt(h2*(1.-h2*localAMag*localAMag/12)-dx*dx-dy*dy);
108 if (std::isnan(dz))
109 {throw std::out_of_range("non-paraxial in old euler method");}
110
111 // check for precision problems
112 G4double ScaleFac=(dx*dx+dy*dy+dz*dz)/h2;
113 if (ScaleFac>1.0000001)
114 {
115 ScaleFac=std::sqrt(ScaleFac);
116 dx/=ScaleFac;
117 dy/=ScaleFac;
118 dz/=ScaleFac;
119 }
120
121 localPos.setX(localPos.x()+dx);
122 localPos.setY(localPos.y()+dy);
123 localPos.setZ(localPos.z()+dz);
124
125 localMom = localMom + h*localA;
126 }
127 else
128 {
129 localPos += h*localMom;
130 SetDistChord(0);
131 }
132}
static G4Navigator * auxNavigator
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[], const G4double h, G4double yOut[], G4double yErr[])
void AdvanceChord(const G4double h, G4ThreeVector &localPos, G4ThreeVector &localMom, const G4ThreeVector &localA)
virtual void AdvanceHelix(const G4double yIn[], G4double h, G4double yOut[], G4double yErr[])=0
Common functionality to BDSIM integrators.
G4Mag_EqRhs * eqOfM
void SetDistChord(G4double distChordIn)
Setter for distChord to private member.
G4MagIntegratorStepper * backupStepper
const G4int nVariables
Cache of the number of variables.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
G4bool IsFiniteStrength(G4double variable)