BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBeamlineIntegral.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2024.
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 "BDSBeamlineIntegral.hh"
20#include "BDSCavityFieldType.hh"
21#include "BDSComponentFactory.hh"
22#include "BDSDebug.hh"
23#include "BDSException.hh"
24#include "BDSFieldEMRFCavity.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSParticleDefinition.hh"
27#include "BDSUtilities.hh"
28
29#include "G4Types.hh"
30
31#include "parser/element.h"
32#include "parser/elementtype.h"
33
34#include "CLHEP/Units/PhysicalConstants.h"
35#include "CLHEP/Units/SystemOfUnits.h"
36
37#include <cmath>
38
39BDSBeamlineIntegral::BDSBeamlineIntegral(const BDSParticleDefinition& incomingParticle,
40 G4double T0In,
41 G4double integratedArcLength,
42 G4bool integrateKineticEnergyIn):
43 integrateKineticEnergy(integrateKineticEnergyIn),
44 synchronousTAtEnd(T0In),
45 synchronousTAtMiddleOfLastElement(T0In),
46 arcLength(integratedArcLength),
47 designParticle(incomingParticle),
48 changeOfEnergyEncountered(false),
49 rigidityCount(0)
50{;}
51
52BDSBeamlineIntegral::~BDSBeamlineIntegral()
53{;}
54
55void BDSBeamlineIntegral::Integrate(const GMAD::Element& componentAsDefined)
56{
57 // length
58 G4double thisComponentArcLength = componentAsDefined.l*CLHEP::m;
59 if (componentAsDefined.type == GMAD::ElementType::_RBEND)
60 {// reuse component factor code to work out angle / field and true arc length
61 G4double componentChordLength;
62 G4double field;
63 G4double angle;
65 designParticle.BRho(),
66 thisComponentArcLength,
67 componentChordLength,
68 field,
69 angle);
70 }
71 arcLength += thisComponentArcLength;
72
73 G4double v0 = designParticle.Velocity(); // current velocity at the entrance of element
74
75 // calculate change in velocity and kinetic energy
76 G4double dEk = 0;
77
78 switch (componentAsDefined.type)
79 {
80 case GMAD::ElementType::_RF:
81 {
82 G4double particleCharge = designParticle.Charge();
83 G4double phase = componentAsDefined.phase * CLHEP::rad;
84 G4double frequency = componentAsDefined.frequency * CLHEP::hertz;
85 // field model - reproduce behaviour in component factory of default in global constants
86 G4String compCFTN = componentAsDefined.cavityFieldType;
87 G4String cftName = compCFTN.empty() ? BDSGlobalConstants::Instance()->CavityFieldType() : compCFTN;
89 BDSFieldType fieldType = BDS::FieldTypeFromCavityFieldType(tp);
90 G4double eField = BDSComponentFactory::EFieldFromElement(&componentAsDefined, fieldType, thisComponentArcLength, designParticle);
91 switch (tp.underlying())
92 {
93 case BDSCavityFieldType::constantinz:
94 {
95 dEk = particleCharge * eField * thisComponentArcLength * std::cos(phase);
96 break;
97 }
98 case BDSCavityFieldType::pillbox:
99 {
100 if (!BDS::IsFinite(frequency)) // protect against zero division
101 {throw BDSException(__METHOD_NAME__, "for a pillbox cavity field, the frequency must be non-zero");}
102 G4double transitTimeFactor = BDSFieldEMRFCavity::TransitTimeFactor(frequency, phase, thisComponentArcLength, designParticle.Beta());
103 dEk = particleCharge * eField * thisComponentArcLength * transitTimeFactor;
104 break;
105 }
106 default:
107 {break;}
108 }
109 break;
110 }
111 default:
112 {break;} // no action
113 }
114
115 G4bool changeOfEnergyEncounteredThisTime = BDS::IsFinite(dEk, 1e-7);
116 changeOfEnergyEncountered = changeOfEnergyEncountered || changeOfEnergyEncounteredThisTime;
117 // count the number of times rigidity changes so we can uniquely name reused components
118 if (changeOfEnergyEncounteredThisTime)
119 {rigidityCount++;}
120
121 // momentum and therefore BRho
123 {designParticle.ApplyChangeInKineticEnergy(dEk);}
124
125 G4double v1 = designParticle.Velocity(); // velocity at the end
126 G4double vMean = (v1 + v0) / 2.0;
127 G4double dT = thisComponentArcLength / vMean;
128
129 G4double dTMiddle = 0.5*thisComponentArcLength / (0.5*(v1-v0) + v0);
130 synchronousTAtMiddleOfLastElement = synchronousTAtEnd + dTMiddle;
131
132 // time - now at the start of the next component / end of this component
133 synchronousTAtEnd += dT;
134}
135
137{
138 BDSBeamlineIntegral copy(*this);
139 copy.Integrate(*el);
140 G4double synchronousTAtMiddle = copy.synchronousTAtMiddleOfLastElement;
141 return synchronousTAtMiddle;
142}
143
145{
146 BDSBeamlineIntegral copy(*this);
147 copy.Integrate(*el);
148 G4double synchronousTAtEndLocal = copy.synchronousTAtEnd;
149 return synchronousTAtEndLocal;
150}
A class that holds the current integrated quantities along a beam line.
void Integrate(const GMAD::Element &componentAsDefined)
G4bool integrateKineticEnergy
On by default, but allow control to not integrate it for old behaviour.
G4double ProvideSynchronousTAtEndOfNextElement(const GMAD::Element *el) const
G4int rigidityCount
Which change in rigidity we're at. Starts at 0, +1 after each change. Used for naming.
G4double ProvideSynchronousTAtCentreOfNextElement(const GMAD::Element *el) const
static void CalculateAngleAndFieldRBend(const GMAD::Element *el, G4double brhoIn, G4double &arcLength, G4double &chordLength, G4double &field, G4double &angle)
static G4double EFieldFromElement(GMAD::Element const *el, BDSFieldType fieldType, G4double cavityLength, const BDSParticleDefinition &incomingParticle)
General exception with possible name of object and message.
static G4double TransitTimeFactor(G4double frequency, G4double phase, G4double zLength, G4double beta)
General function put here as it represents the equations in this class.
static BDSGlobalConstants * Instance()
Access method.
Wrapper for particle definition.
G4double Charge() const
Accessor.
G4double BRho() const
Accessor.
G4double Beta() const
Accessor.
G4double Velocity() const
Accessor.
void ApplyChangeInKineticEnergy(G4double dEk)
Utility function to update quantities by adding on dEK (can be negative).
Improve type-safety of native enum data type in C++.
type underlying() const
return underlying value (can be used in switch statement)
BDSCavityFieldType DetermineCavityFieldType(G4String cavityFieldType)
function to determine the enum type of the cavity field type (case-insensitive)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
Element class.
Definition element.h:45
std::string cavityFieldType
Name for type of field to use in a cavity.
Definition element.h:261
double phase
phase of rf cavity (rad)
Definition element.h:79
double l
length in metres
Definition element.h:51
ElementType type
element enum
Definition element.h:46
double frequency
frequency for rf cavity in Hz
Definition element.h:78