BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSGlobalConstants.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 "BDSBeamPipeInfo.hh"
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSGlobalConstants.hh"
22#include "BDSFieldInfo.hh"
23#include "BDSIntegratorSetType.hh"
24#include "BDSOutputType.hh"
25#include "BDSPTCOneTurnMap.hh"
26#include "BDSParser.hh"
27#include "BDSSamplerCustom.hh"
28#include "BDSSamplerPlane.hh"
29#include "BDSSamplerRegistry.hh"
30#include "BDSTrajectoryFilter.hh"
31#include "BDSTrajectoryOptions.hh"
32#include "BDSTunnelInfo.hh"
33#include "BDSUtilities.hh"
34#include "BDSWarning.hh"
35
36#include "parser/options.h"
37
38#include "globals.hh"
39#include "G4Colour.hh"
40#include "G4RotationMatrix.hh"
41#include "G4ThreeVector.hh"
42#include "G4Transform3D.hh"
43#include "G4UserLimits.hh"
44#include "G4Version.hh"
45#include "G4VisAttributes.hh"
46
47#include "CLHEP/Units/SystemOfUnits.h"
48#include "CLHEP/Vector/EulerAngles.h"
49
50#include <cstdlib>
51#include <limits>
52#include <sstream>
53#include <string>
54#include <stdexcept>
55#include <utility>
56
58
70
72 options(opt),
73 turnsTaken(0)
74{
77
79
80 samplerDiameter = G4double(options.samplerDiameter)*CLHEP::m;
81 curvilinearDiameter = 5*CLHEP::m;
82 curvilinearDiameterShrunkForBends = false;
83
84 // beam pipe
86 options.aper1 * CLHEP::m,
87 options.aper2 * CLHEP::m,
88 options.aper3 * CLHEP::m,
89 options.aper4 * CLHEP::m,
91 options.beampipeThickness * CLHEP::m,
93
94 // magnet geometry
95 G4double horizontalWidth = options.horizontalWidth * CLHEP::m;
97 {
98 G4cerr << __METHOD_NAME__ << "Error: option \"horizontalWidth\" " << horizontalWidth
99 << " must be greater than 2x (\"aper1\" + \"beamPipeThickness\") ("
100 << defaultBeamPipeModel->aper1 << " + " << defaultBeamPipeModel->beamPipeThickness << ")" << G4endl;
101 throw BDSException(__METHOD_NAME__,"error in beam pipe defaults");
102 }
104
105 // tunnel
107 options.tunnelThickness * CLHEP::m,
108 options.tunnelSoilThickness * CLHEP::m,
112 options.tunnelFloorOffset * CLHEP::m,
113 options.tunnelAper1 * CLHEP::m,
114 options.tunnelAper2 * CLHEP::m,
115 options.storeElossTunnel,
117
118 // defaults - parameters of the laserwire process
119 itsLaserwireWavelength = 0.532 * CLHEP::micrometer;
120 itsLaserwireDir = G4ThreeVector(1,0,0);
121 itsLaserwireTrackPhotons = true;
122 itsLaserwireTrackElectrons = true;
123
124 // initialise the default vis attributes and user limits that
125 // can be copied by various bits of geometry
126 InitVisAttributes();
127 InitDefaultUserLimits();
128
130
132
133 if (options.lengthSafetyLarge <= options.lengthSafety)
134 {throw BDSException(__METHOD_NAME__, "\"lengthSafetyLarge\" must be > \"lengthSafety\"");}
135
136 BDSSamplerPlane::chordLength = 10*LengthSafety();
137 BDSSamplerCustom::chordLength = 10*BDSSamplerPlane::chordLength;
138
140
141 // mark which trajectory filters have been set
142 trajectoryFiltersSet[BDSTrajectoryFilter::depth] = options.HasBeenSet("storeTrajectoryDepth");
143 trajectoryFiltersSet[BDSTrajectoryFilter::particle] = options.HasBeenSet("storeTrajectoryParticle") ||
144 options.HasBeenSet("storeTrajectoryParticleID");
145 trajectoryFiltersSet[BDSTrajectoryFilter::energyThreshold] = options.HasBeenSet("storeTrajectoryEnergyThreshold");
146 trajectoryFiltersSet[BDSTrajectoryFilter::sampler] = options.HasBeenSet("storeTrajectorySamplerID");
147 trajectoryFiltersSet[BDSTrajectoryFilter::elossSRange] = options.HasBeenSet("storeTrajectoryElossSRange");
148 trajectoryFiltersSet[BDSTrajectoryFilter::minimumZ] = options.HasBeenSet("trajCutGTZ");
149 trajectoryFiltersSet[BDSTrajectoryFilter::maximumR] = options.HasBeenSet("trajCutLTR");
150 trajectoryFiltersSet[BDSTrajectoryFilter::secondary] = options.HasBeenSet("storeTrajectorySecondaryParticles");
151
152 if (StoreMinimalData())
153 {
154 G4cout << "\nGlobal option> storing minimal data\n" << G4endl;
155 // these options are made with respect to the defaults in parser/optionsBase.cc - i.e. no need ot set false
156 // for a default that is false -> saves code
157 // the one on the right MUST be the one returned by this class in the getter function in the header
158 auto& o = options;
159 std::map<std::string, bool*> otc = {
160 {"storeApertureImpacts", &o.storeApertureImpacts},
161 {"storeApertureImpactsHistograms", &o.storeApertureImpactsHistograms},
162 {"storeCollimatorInfo", &o.storeCollimatorInfo},
163 {"storeCollimatorHits", &o.storeCollimatorHits},
164 {"storeCollimatorHitsLinks", &o.storeCollimatorHitsLinks},
165 {"storeCollimatorHitsIons", &o.storeCollimatorHitsIons},
166 {"storeCollimatorHitsAll", &o.storeCollimatorHitsAll},
167 {"storePrimaryHistograms", &o.storePrimaryHistograms},
168 {"storeTrajectoryTransportationSteps", &o.storeTrajectoryTransportationSteps},
169 {"storeModel", &o.storeModel}
170 };
171 for (auto& no : otc)
172 {
173 if (!options.HasBeenSet(no.first))
174 {*no.second = false;}
175 }
176 // try again for options that have multiple versions and check if any are set
177 // even though there's only one member bool we turn on / off in the options
178 std::map<std::set<std::string>, bool*> otcMultiple = {
179 {{"storeELoss", "storeEloss"}, &o.storeEloss},
180 {{"storeELoss","storeEloss"}, &o.storeEloss},
181 {{"storeELossHistograms", "storeElossHistograms"}, &o.storeElossHistograms},
182 {{"storeTrajectory", "storeTrajectories"}, &o.storeTrajectory},
183 {{"storeParticleData","storeGeant4Data"}, &o.storeParticleData},
184 {{"storePrimaries", "writePrimaries"}, &o.storePrimaries},
185 };
186 for (auto& no : otcMultiple)
187 {
188 bool hasBeenSet = false;
189 for (auto& op : no.first)
190 {hasBeenSet = hasBeenSet || options.HasBeenSet(op);}
191 if (!hasBeenSet)
192 {*no.second = false;}
193 }
194 }
195
196 // TBC
197 if (options.HasBeenSet("fieldModulator"))
198 {throw BDSException(__METHOD_NAME__, "the option \"fieldModulator\" cannot be used currently - in development");}
199
200
201 // uproot
202 if (options.uprootCompatible == 1)
203 {
204 options.samplersSplitLevel = 1;
205 options.modelSplitLevel = 2;
206 }
207
208#if G4VERSION_NUMBER > 1079
209 if (options.HasBeenSet("scintYieldFactor"))
210 {BDS::Warning("The option \"scintYieldFactor\" has no effect with Geant4 11.0 onwards");}
211#endif
212}
213
215{
216 G4ThreeVector offset = G4ThreeVector(options.beamlineX * CLHEP::m,
217 options.beamlineY * CLHEP::m,
218 options.beamlineZ * CLHEP::m);
219
220 G4RotationMatrix rm;
222 {
223 G4ThreeVector axis = G4ThreeVector(options.beamlineAxisX,
226
227 rm = G4RotationMatrix(axis, options.beamlineAngle * CLHEP::rad);
228 }
229 else
230 {
231 G4double phi = options.beamlinePhi * CLHEP::rad;
232 G4double theta = options.beamlineTheta * CLHEP::rad;
233 G4double psi = options.beamlinePsi * CLHEP::rad;
234 CLHEP::HepEulerAngles ang = CLHEP::HepEulerAngles(phi, theta, psi);
235 rm = G4RotationMatrix(ang);
236 }
237
238 beamlineTransform = G4Transform3D(rm, offset);
239}
240
241void BDSGlobalConstants::InitVisAttributes()
242{
243 //for vacuum volumes
244 invisibleVisAttr = new G4VisAttributes(G4Colour::Black());
245 invisibleVisAttr->SetVisibility(false);
246 invisibleVisAttr->SetForceLineSegmentsPerCircle(options.nSegmentsPerCircle);
247
248 //for normally invisible volumes like marker / container volumes in debug mode
249 visibleDebugVisAttr = new G4VisAttributes(); //green
250 visibleDebugVisAttr->SetColour(0,0.6,0,0.1);
251 visibleDebugVisAttr->SetVisibility(true);
252 visibleDebugVisAttr->SetForceLineSegmentsPerCircle(options.nSegmentsPerCircle);
253}
254
255void BDSGlobalConstants::InitDefaultUserLimits()
256{
257 auto pteAsVector = BDS::SplitOnWhiteSpace(ParticlesToExcludeFromCuts());
258 // construct the set of PDG IDs
259 for (G4int i = 0; i < (G4int)pteAsVector.size(); i++)
260 {
261 try
262 {
263 G4int pdgID = std::stoi(pteAsVector[i]);
264 particlesToExcludeFromCutsAsSet.insert(pdgID);
265 }
266 catch (std::logic_error& e)
267 {
268 G4String msg = "Particle ID " + pteAsVector[i] + " at index " + std::to_string(i);
269 msg += " in the option particlesToExcludeFromCutsAsSet cannot be converted to an integer";
270 throw BDSException(__METHOD_NAME__, msg);
271 }
272 }
273
274 defaultUserLimits = new G4UserLimits("default_cuts");
275 const G4double maxTime = MaxTime();
276 if (maxTime > 0)
277 {
278 G4cout << __METHOD_NAME__ << "Setting maximum tracking time to " << maxTime << " ns" << G4endl;
279 defaultUserLimits->SetUserMaxTime(maxTime);
280 }
281 defaultUserLimits->SetMaxAllowedStep(MaxStepLength());
282 defaultUserLimits->SetUserMaxTrackLength(MaxTrackLength());
283 G4double minEK = MinimumKineticEnergy();
284 defaultUserLimits->SetUserMinEkine(minEK);
285 if (minEK > 0)
286 {G4cout << __METHOD_NAME__ << "Default minimum kinetic energy for model: " << minEK/CLHEP::GeV << " GeV" << G4endl;}
287 G4double minR = MinimumRange();
288 defaultUserLimits->SetUserMinRange(minR);
289 if (minR > 0)
290 {G4cout << __METHOD_NAME__ << "Default minimum range for user limits: " << minR/CLHEP::mm << " mm" << G4endl;}
291
292
293 BDSFieldInfo::defaultUL = defaultUserLimits; // update static member for field definitions
294
295 defaultUserLimitsTunnel = new G4UserLimits(*defaultUserLimits);
296 defaultUserLimitsTunnel->SetType("default_cuts_tunnel");
297 if (BDS::IsFinite(MinimumKineticEnergyTunnel()))
298 {defaultUserLimitsTunnel->SetUserMinEkine(MinimumKineticEnergyTunnel());}
299 if (TunnelIsInfiniteAbsorber())
300 {defaultUserLimitsTunnel->SetUserMinEkine(std::numeric_limits<double>::max());}
301}
302
303G4int BDSGlobalConstants::PrintModuloEvents() const
304{
305 G4int nGenerate = NGenerate();
306 G4double fraction = PrintFractionEvents();
307 G4int printModulo = (G4int)ceil(nGenerate * fraction);
308 if (printModulo < 0)
309 {printModulo = 1;}
310
311 if (!Batch())
312 {printModulo = 1;} // interactive -> print every event
313 return printModulo;
314}
315
316G4int BDSGlobalConstants::PrintModuloTurns() const
317{
318 G4int nTurns = TurnsToTake();
319 G4double fraction = PrintFractionTurns();
320 G4int printModulo = (G4int)ceil(nTurns * fraction);
321 if (printModulo < 0)
322 {printModulo = 1;}
323
324 if (!Batch())
325 {printModulo = 1;} // interactive -> print every turn
326 return printModulo;
327}
328
329BDSGlobalConstants::~BDSGlobalConstants()
330{
332 delete tunnelInfo;
333 delete defaultUserLimits;
334 delete defaultUserLimitsTunnel;
335 delete invisibleVisAttr;
336 delete visibleDebugVisAttr;
337
338 instance = nullptr;
339}
340
342{
343 if (options.storeTrajectoryELossSRange.empty())
344 {return;}
345 std::istringstream is(options.storeTrajectoryELossSRange);
346 std::string tok;
347 while (is >> tok)
348 {
349 std::size_t loc = tok.find(':',0);
350 if (loc == std::string::npos)
351 {throw BDSException(__METHOD_NAME__, "Error: no ':' character found in option storeTrajectoryELossSRange \"" + options.storeTrajectoryELossSRange + "\" - invalid range.");}
352 G4double rstart = 0;
353 G4double rend = 0;
354 try
355 {
356 rstart = std::stod(tok.substr(0, loc));
357 rend = std::stod(tok.substr(loc+1,tok.size()));
358 }
359 catch (const std::invalid_argument& e)
360 {
361 G4cerr << "Invalid value \"" << tok << "\" in option storeTrajectoryELossSRange." << G4endl;
362 throw BDSException(__METHOD_NAME__, "Error: can't convert string to number for option storeTrajectoryELossSRange.");
363 }
364 if (rend < rstart)
365 {
366 G4String message = "Error in option storeTrajectoryElossSRange - end point "
367 + std::to_string(rend) + " is less than beginning " + std::to_string(rstart) + ".";
368 throw BDSException(__METHOD_NAME__, message);
369 }
370 elossSRange.emplace_back(rstart*CLHEP::m, rend*CLHEP::m);
371 }
372}
373
375{
376 // only if true we let this option take precedence
378 {return false;}
379 else
380 {return options.storeTrajectoryTransportationSteps;}
381}
382
384{
386 StoreTrajectoryKineticEnergy(),
387 StoreTrajectoryMomentumVector(),
388 StoreTrajectoryProcesses(),
389 StoreTrajectoryTime(),
390 StoreTrajectoryLocal(),
391 StoreTrajectoryLinks(),
392 StoreTrajectoryIon(),
393 StoreTrajectoryMaterial()};
394
395 if (StoreTrajectoryAllVariables())
396 {
397 result.storeKineticEnergy = true;
398 result.storeMomentumVector = true;
399 result.storeProcesses = true;
400 result.storeTime = true;
401 result.storeLocal = true;
402 result.storeLinks = true;
403 result.storeIon = true;
404 result.storeMaterial = true;
405 }
406 return result;
407}
Holder class for all information required to describe a beam pipe model.
G4double aper1
Public member for direct access.
G4double beamPipeThickness
Public member for direct access.
General exception with possible name of object and message.
static G4UserLimits * defaultUL
Cache of default user limits.
A class that holds global options and constants.
GMAD::Options options
Options instance that this is largely based on and extends.
void ProcessTrajectoryELossSRange()
Process the option string and fill the below vector.
G4double curvilinearDiameter
Curvilinear diameter for CL volumes - defaults to samplerDiameter.
BDSTunnelInfo * tunnelInfo
Tunnel model.
std::bitset< BDS::NTrajectoryFilters > trajectoryFiltersSet
Which filters were used in the options.
static BDSGlobalConstants * Instance()
Access method.
BDSOutputType outputType
Output type enum for output format to be used.
BDSIntegratorSetType integratorSet
Integrator type enum for integrator set to be used.
std::vector< std::pair< G4double, G4double > > elossSRange
Pairs of S ranges to link trajectories to.
BDS::TrajectoryOptions StoreTrajectoryOptions() const
options that require some implementation.
BDSBeamPipeInfo * defaultBeamPipeModel
Default beam pipe model information.
void InitialiseBeamlineTransform()
Prepare the G4Transform3D instance from the options for the initial beam line transform.
BDSGlobalConstants()=delete
Unused default constructors.
BDSMagnetGeometryType magnetGeometryType
Magnet geometry.
G4double samplerDiameter
Cache of sampler diameter in this class so it can be updated.
G4Transform3D beamlineTransform
Transform for start of beam line.
G4int numberToGenerate
Number of particles to generate can be set from outside (by e.g. BDSBunchPtc)
G4bool StoreTrajectoryTransportationSteps() const
options that require some implementation.
void ResetTurnNumber()
Setter.
static BDSGlobalConstants * instance
Singleton instance.
static BDSParser * Instance()
Access method.
Definition BDSParser.cc:29
static bool IsInitialised()
Returns if parser is initialised.
Definition BDSParser.cc:50
static G4double chordLength
The chord length for all is fixed and can be static.
Holder struct of all information required to create a section of tunnel.
std::string magnetGeometryType
default magnet geometry parameters
double beamlineZ
Initial beam line transform w.r.t. the world coordinate frame.
int nGenerate
The number of primary events to simulate.
Definition optionsBase.h:93
double beamlineAngle
Initial beam line transform w.r.t. the world coordinate frame.
double tunnelSoilThickness
tunnel geometry parameters
std::string outputFormat
Parameter for output format.
Definition optionsBase.h:49
bool beamlineAxisAngle
Initial beam line transform w.r.t. the world coordinate frame.
double tunnelFloorOffset
tunnel geometry parameters
std::string tunnelMaterial
tunnel geometry parameters
int nSegmentsPerCircle
Number of facets per 2pi in visualisation.
std::string soilMaterial
tunnel geometry parameters
double aper1
default beampipe parameters
double aper2
default beampipe parameters
double beamlinePhi
Initial beam line transform w.r.t. the world coordinate frame.
std::string vacMaterial
vacuum material
bool buildTunnelFloor
tunnel geometry parameters
double beamlineAxisY
Initial beam line transform w.r.t. the world coordinate frame.
double tunnelAper1
tunnel geometry parameters
std::string beampipeMaterial
default beampipe parameters
double beampipeThickness
default beampipe parameters
double beamlineX
Initial beam line transform w.r.t. the world coordinate frame.
std::string apertureType
default beampipe parameters
double tunnelAper2
tunnel geometry parameters
double beamlineY
Initial beam line transform w.r.t. the world coordinate frame.
double beamlineAxisX
Initial beam line transform w.r.t. the world coordinate frame.
double tunnelThickness
tunnel geometry parameters
double aper4
default beampipe parameters
double aper3
default beampipe parameters
std::string tunnelType
tunnel geometry parameters
double beamlineAxisZ
Initial beam line transform w.r.t. the world coordinate frame.
double beamlinePsi
Initial beam line transform w.r.t. the world coordinate frame.
bool trajNoTransportation
kept only for backwards compatibility.
bool tunnelVisible
tunnel geometry parameters
double beamlineTheta
Initial beam line transform w.r.t. the world coordinate frame.
Options class.
Definition options.h:43
bool HasBeenSet(const std::string &name) const
Whether a parameter has been set using the set_value method or not.
Definition options.cc:138
BDSMagnetGeometryType DetermineMagnetGeometryType(G4String geometryType)
function to determine the enum type of the magnet geometry (case-insensitive)
BDSIntegratorSetType DetermineIntegratorSetType(G4String integratorSet)
Function that gives corresponding enum value for string (case-insensitive)
BDSOutputType DetermineOutputType(G4String outputType)
Determine the output format to be used from the input string.
std::vector< G4String > SplitOnWhiteSpace(const G4String &input)
Split a string on whitespace and return a vector of these 'words'.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())