BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldEMMuonCooler.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 "BDSDebug.hh"
19#include "BDSException.hh"
20#include "BDSFieldEMMuonCooler.hh"
21#include "BDSFieldInfoExtra.hh"
22#include "BDSFieldMagSolenoidBlock.hh"
23#include "BDSFieldMagSolenoidSheet.hh"
24#include "BDSFieldMagSolenoidLoop.hh"
25#include "BDSFieldMagDipoleEnge.hh"
26#include "BDSFieldMagDipoleHardEdgeMuonCooler.hh"
27#include "BDSFieldMagVectorSum.hh"
28#include "BDSFieldMag.hh"
29#include "BDSFieldEMVectorSum.hh"
30#include "BDSFieldEMRFCavity.hh"
31#include "BDSFieldType.hh"
32
33#include "G4ThreeVector.hh"
34#include "G4Types.hh"
35
36#include <utility>
37
38BDSFieldEMMuonCooler::BDSFieldEMMuonCooler(const BDSFieldInfoExtraMuonCooler* info,
39 G4double /*brho*/):
40 coilField(nullptr),
41 dipoleField(nullptr),
42 rfField(nullptr)
43{
44 BuildMagnets(info);
45 BuildDipoles(info);
46 BuildRF(info);
47}
48
49void BDSFieldEMMuonCooler::BuildMagnets(const BDSFieldInfoExtraMuonCooler* info)
50{
51 switch (info->magneticFieldType.underlying())
52 {
53 case BDSFieldType::solenoidblock:
54 {
55 const auto& coilInfos = info->coilInfos;
56 std::vector<BDSFieldMag*> fields;
57 std::vector<G4ThreeVector> fieldOffsets;
58 for (const auto& ci : coilInfos)
59 {
60 fields.push_back(new BDSFieldMagSolenoidBlock(ci.current,
61 true,
62 ci.innerRadius,
63 ci.radialThickness,
64 ci.fullLengthZ,
65 ci.onAxisTolerance,
66 ci.nSheets));
67 fieldOffsets.emplace_back(0,0,ci.offsetZ);
68 }
69 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
70 break;
71 }
72 case BDSFieldType::solenoidsheet:
73 {
74 const auto& coilInfos = info->coilInfos;
75 std::vector<BDSFieldMag*> fields;
76 std::vector<G4ThreeVector> fieldOffsets;
77 for (const auto& ci : coilInfos)
78 {
79 fields.push_back(new BDSFieldMagSolenoidSheet(ci.current,
80 true,
81 ci.innerRadius + 0.5*ci.radialThickness,
82 ci.fullLengthZ,
83 ci.onAxisTolerance));
84 fieldOffsets.emplace_back(0,0,ci.offsetZ);
85 }
86 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
87 break;
88 }
89 case BDSFieldType::solenoidloop:
90 {
91 const auto& coilInfos = info->coilInfos;
92 std::vector<BDSFieldMag*> fields;
93 std::vector<G4ThreeVector> fieldOffsets;
94 for (const auto& ci : coilInfos)
95 {
96 fields.push_back(new BDSFieldMagSolenoidLoop(ci.current,
97 true,
98 ci.innerRadius + 0.5*ci.radialThickness));
99 fieldOffsets.emplace_back(0,0,ci.offsetZ);
100 }
101 coilField = new BDSFieldMagVectorSum(fields, fieldOffsets);
102 break;
103 }
104 default:
105 {
106 G4String msg = "\"" + info->magneticFieldType.ToString();
107 msg += "\" is not a valid field model for a muon cooler B field";
108 throw BDSException(__METHOD_NAME__, msg);
109 break;
110 }
111 }
112}
113
114void BDSFieldEMMuonCooler::BuildDipoles(const BDSFieldInfoExtraMuonCooler* info)
115{
116 switch (info->dipoleFieldType.underlying())
117 {
118 case BDSFieldType::dipole:
119 {
120 const auto& dipoleInfos = info->dipoleInfos;
121 std::vector<BDSFieldMag*> fields;
122 std::vector<G4ThreeVector> fieldOffsets;
123 for (const auto& di : dipoleInfos)
124 {
125 fields.push_back(new BDSFieldMagDipoleHardEdgeMuonCooler(di.fieldStrength,
126 di.apertureRadius,
127 di.fullLengthZ));
128 fieldOffsets.emplace_back(0,0,di.offsetZ);
129 }
130 dipoleField = new BDSFieldMagVectorSum(fields, fieldOffsets);
131 break;
132 }
133 case BDSFieldType::dipoleenge:
134 {
135 const auto& dipoleInfos = info->dipoleInfos;
136 std::vector<BDSFieldMag*> fields;
137 std::vector<G4ThreeVector> fieldOffsets;
138 for (const auto& di : dipoleInfos)
139 {
140 fields.push_back(new BDSFieldMagDipoleEnge(di.fieldStrength,
141 di.apertureRadius,
142 di.fullLengthZ,
143 di.engeCoefficient));
144 fieldOffsets.emplace_back(0,0,di.offsetZ);
145 }
146 dipoleField = new BDSFieldMagVectorSum(fields, fieldOffsets);
147 break;
148 }
149 default:
150 {
151 G4String msg = "\"" + info->dipoleFieldType.ToString();
152 msg += "\" is not a valid dipole field model for a muon cooler B field";
153 throw BDSException(__METHOD_NAME__, msg);
154 break;
155 }
156 }
157}
158
159void BDSFieldEMMuonCooler::BuildRF(const BDSFieldInfoExtraMuonCooler* info)
160{
161 const auto& cavityInfos = info->cavityInfos;
162 std::vector<G4ThreeVector> fieldOffsets;
164 for (const auto& ci : cavityInfos)
165 {
167 ci.peakEField,
168 ci.frequency,
169 ci.phaseOffset,
170 ci.cavityRadius,
171 0.0 // We provide a global tOffset instead
172 );
173 double lengthZ = ci.lengthZ;
174 G4ThreeVector posOffset(0.0, 0.0, ci.offsetZ);
175 double tOffset = ci.globalTimeOffset;
176 emSum->PushBackField(posOffset, tOffset, lengthZ, rfCav);
177 }
178 rfField = emSum;
179}
180
181BDSFieldEMMuonCooler::~BDSFieldEMMuonCooler()
182{
183 delete coilField;
184 delete dipoleField;
185 delete rfField;
186}
187
188std::pair<G4ThreeVector, G4ThreeVector> BDSFieldEMMuonCooler::GetField(const G4ThreeVector& position,
189 const G4double t) const
190{
191 auto result = rfField->GetField(position, t); // result is a pair like <Bfield, Efield>
192 G4ThreeVector solfieldOut = coilField->GetField(position, t);
193 G4ThreeVector dipolefieldOut = dipoleField->GetField(position, t);
194 result.first += solfieldOut;
195 result.first += dipolefieldOut;
196 return result;
197}
General exception with possible name of object and message.
virtual std::pair< G4ThreeVector, G4ThreeVector > GetField(const G4ThreeVector &position, const G4double t) const
Function to get B and E field.
Pill box cavity electromagnetic field.
A vector sum of multiple displaced EM fields.
virtual std::pair< G4ThreeVector, G4ThreeVector > GetField(const G4ThreeVector &position, const G4double t=0) const =0
necessary extra information for a muon cooler field.
BDSFieldType dipoleFieldType
Type of the dipole sub-field.
BDSFieldType magneticFieldType
Type of the magnetic sub-field.
A dipole field with Enge-type fringes. This follows the model and parameterisation described in: http...
This class represents a hard-edge dipole field. The field is calculated in cartesian coordinates.
Class that provides the magnetic field due to a square annulus of current.
Class that provides the magnetic field due to a cylinder of current.
Class that provides the magnetic field due to a cylinder of current.
A vector sum of multiple displaced magnetic fields.
virtual G4ThreeVector GetField(const G4ThreeVector &position, const G4double t=0) const =0
type underlying() const
return underlying value (can be used in switch statement)