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