BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSUtilities.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSExtent.hh"
22#include "BDSGlobalConstants.hh"
23#include "BDSPhysicalConstants.hh"
24#include "BDSRunManager.hh"
25#include "BDSUtilities.hh"
26
27#include "globals.hh" // geant4 types / globals
28#include "G4String.hh"
29#include "G4ThreeVector.hh"
30#include "G4Track.hh"
31#include "G4TwoVector.hh"
32#include "G4UserLimits.hh"
33#include "G4Version.hh"
34
35#include "CLHEP/Units/SystemOfUnits.h"
36
37#include <algorithm>
38#include <cmath>
39#include <cctype>
40#include <cstdlib>
41#include <functional>
42#include <iostream>
43#include <iterator>
44#include <limits>
45#include <map>
46#include <signal.h>
47#include <sstream>
48#include <string>
49#include <unistd.h>
50#include <utility>
51#include <vector>
52
53#include <sys/resource.h>
54#include <sys/stat.h>
55
56#ifdef __APPLE__
57#include <mach-o/dyld.h> // for executable path
58#endif
59
60
61G4bool BDS::non_alpha::operator()(char c)
62{
63 return !isalpha(c);
64}
65
66G4bool BDS::StrContains(const G4String& str, const G4String& test)
67{
68#if G4VERSION_NUMBER > 1099
69 return G4StrUtil::contains(str, test);
70#else
71 return str.contains(test);
72#endif
73}
74#if G4VERSION_NUMBER > 1099
75G4int BDS::StrCompare(const G4String& str, const G4String& test, G4String::caseCompare)
76#else
77G4int BDS::StrCompare(const G4String& str, const G4String& test, G4String::caseCompare mode)
78#endif
79{
80#if G4VERSION_NUMBER > 1099
81 return G4StrUtil::icompare(str, test);
82#else
83 return str.compareTo(test, mode);
84#endif
85}
86
87G4String BDS::LowerCase(const G4String& str)
88{
89 G4String result = str;
90#if G4VERSION_NUMBER > 1099
91 G4StrUtil::to_lower(result);
92#else
93 result.toLower();
94#endif
95 return result;
96}
97
98G4String BDS::StrStrip(const G4String& str,
99 char ch,
100 StringStripType stripType)
101{
102 G4String result = str;
103 switch (stripType)
104 {
105#if G4VERSION_NUMBER > 1099
106 case StringStripType::leading:
107 {G4StrUtil::lstrip(result, ch); break;}
108 case StringStripType::trailing:
109 {G4StrUtil::rstrip(result, ch); break;}
110 case StringStripType::both:
111 {G4StrUtil::strip(result, ch); break;}
112#else
113 case StringStripType::leading:
114 {result.strip(G4String::stripType::leading, ch); break;}
115 case StringStripType::trailing:
116 {result.strip(G4String::stripType::trailing, ch); break;}
117 case StringStripType::both:
118 {result.strip(G4String::stripType::both, ch); break;}
119#endif
120 }
121 return result;
122}
123
124G4String BDS::PrepareSafeName(G4String name)
125{
126 //remove white space
127 name.erase(std::remove_if(name.begin(),name.end(),isspace),name.end());
128 //remove non alpha-numeric characters
129 std::replace_if(name.begin(),name.end(),BDS::non_alpha(),'_');
130
131 return name;
132}
133
134G4int BDS::CalculateOrientation(G4double angle)
135{
136 return angle < 0 ? 1 : -1;
137}
138
139std::pair<G4ThreeVector,G4ThreeVector> BDS::CalculateFaces(G4double angleIn,
140 G4double angleOut)
141{
144 G4int orientationIn = BDS::CalculateOrientation(angleIn);
145 G4int orientationOut = BDS::CalculateOrientation(angleOut);
146
147 G4double in_z = std::cos(std::abs(angleIn)); // calculate components of normal vectors (in the end mag(normal) = 1)
148 G4double in_x = std::sin(std::abs(angleIn)); // note full angle here as it's the exit angle
149 G4double out_z = std::cos(std::abs(angleOut));
150 G4double out_x = std::sin(std::abs(angleOut));
151 G4ThreeVector inputface = G4ThreeVector(orientationIn*in_x, 0.0, -1.0*in_z); //-1 as pointing down in z for normal
152 G4ThreeVector outputface = G4ThreeVector(orientationOut*out_x, 0.0, out_z); // no output face angle
153 return std::make_pair(inputface,outputface);
154}
155
156void BDS::EnsureInLimits(G4double& value, G4double lowerLimit, G4double upperLimit)
157{
158 if (value < lowerLimit)
159 {value = lowerLimit;}
160 if (value > upperLimit)
161 {value = upperLimit;}
162}
163
164G4bool BDS::FileExists(const G4String& fileName)
165{
166 std::ifstream infile(fileName.c_str());
167 return infile.good();
168 // note the destructor of ifstream will close the stream
169}
170
171G4bool BDS::DirectoryExists(const G4String& path)
172{
173 struct stat sb;
174 bool result = (stat(path.c_str(), &sb) == 0) && S_ISDIR(sb.st_mode);
175 return G4bool(result);
176}
177
179{
180 char currentPath[PATH_MAX]; // defined in <limits>
181 std::string currentPathString;
182
183 if (getcwd(currentPath, sizeof(currentPath)) != nullptr)
184 {currentPathString = std::string(currentPath);}
185 else
186 {throw BDSException(__METHOD_NAME__, "Cannot determine current working directory");}
187
188 return currentPathString;
189}
190
192{
193 // get path to executable (platform dependent)
194 char path[1024];
195#ifdef __linux__
196 // get path from /proc/self/exe
197 ssize_t len = ::readlink("/proc/self/exe", path, sizeof(path) - 1);
198 if (len != -1)
199 {path[len] = '\0';}
200#elif __APPLE__
201 uint32_t size = sizeof(path);
202 if (_NSGetExecutablePath(path, &size) != 0)
203 {std::cout << "buffer too small; need size " << size << std::endl;}
204#endif
205 std::string bdsimPath(path);
206 // remove executable from path
207 std::string::size_type found = bdsimPath.rfind('/'); // find the last '/'
208 if (found != std::string::npos)
209 {bdsimPath = bdsimPath.substr(0,found+1);} // the path is the bit before that, including the '/'
210 return bdsimPath;
211}
212
213G4String BDS::GetFullPath(G4String fileName, bool excludeNameFromPath, bool useCWDForPrefix)
214{
215#ifdef BDSDEBUG
216 G4cout << __METHOD_NAME__ << fileName << " strip name off?: " << excludeNameFromPath << G4endl;
217#endif
218 //Return fullPath of a file:
219 //mirror what is done in parser.l (i.e. if no environment variable set, assume base filename path is that of the gmad file).
220 // 1) if absolute path (starting with a slash) return that
221 // 2) if relative path, then
222 // 2a) return path relative to environment variable BDSIMPATH (if set)
223 // 2b) return path relative to main BDSIM input gmad file
224
225 // return value
226 G4String fullPath;
227
228 // protect against unneeded ./ at beginning of filename - strip it off
229 if (fileName.substr(0,2) == "./")
230 {fileName = fileName.substr(2);}
231
232 // split input into path and filename
233 G4String inputFilepath, inputFilename;
234 BDS::SplitPathAndFileName(fileName, inputFilepath, inputFilename);
235
236 // need to know whether it's an absolute or relative path
237 if ((fileName.substr(0,1)) == "/")
238 {fullPath = inputFilepath;}
239 else // the main file has a relative path or just the file name, add bdsimpath
240 {
241 G4String prefixPath = useCWDForPrefix ? BDS::GetCurrentDir() : BDSGlobalConstants::Instance()->BDSIMPath();
242 fullPath = prefixPath;
243 if (inputFilepath != "./") // don't insert a ./ in path
244 {fullPath += "/" + inputFilepath;}
245 }
246
247 if (fullPath.back() != '/') // ensure ends in '/'
248 {fullPath += "/";} // only add if needed
249
250 // add filename if not excluded
251 if (!excludeNameFromPath)
252 {fullPath += inputFilename;}
253#ifdef BDSDEBUG
254 G4cout << __METHOD_NAME__ << "determined full path to be: " << fullPath << G4endl;
255#endif
256 return fullPath;
257}
258
259void BDS::SplitPathAndFileName(const G4String& filePath,
260 G4String& path,
261 G4String& fileName)
262{
263 G4String::size_type found = filePath.rfind('/'); // find the last '/'
264 if (found != G4String::npos)
265 {
266 path = filePath.substr(0,found) + "/"; // the path is the bit before that
267 fileName = filePath.substr(found+1); // the rest
268 }
269 else
270 {// no slash, only file name
271 path = "./"; // use current directory
272 fileName = filePath;
273 }
274}
275
276void BDS::SplitFileAndExtension(const G4String& fileName,
277 G4String& file,
278 G4String& extension)
279{
280 G4String::size_type found = fileName.rfind("."); // fine the last '.'
281 if (found != G4String::npos)
282 {
283 file = fileName.substr(0, found);
284 extension = fileName.substr(found); // the rest
285 }
286 else
287 {
288 file = fileName;
289 extension = "";
290 }
291}
292
293void BDS::HandleAborts(int signal_number)
294{
299 // prevent recursive calling
300 static int nrOfCalls=0;
301 if (nrOfCalls>0)
302 {exit(1);}
303 nrOfCalls++;
304 std::cout << std::endl << "BDSIM is about to crash or was interrupted! " << std::endl;
305 std::cout << "With signal: " << strsignal(signal_number) << std::endl;
306
307 BDSRunManager::GetRunManager()->AbortRun();
308 std::cout << "Ave, Imperator, morituri te salutant!" << std::endl;
309}
310
311G4bool BDS::IsFinite(G4double value,
312 G4double tolerance)
313{
314 return std::abs(value) > tolerance;
315}
316
317G4bool BDS::NonZero(G4double value)
318{
319 return std::abs(value) > std::numeric_limits<double>::min();
320}
321
322G4bool BDS::IsFiniteStrength(G4double value)
323{
324 return IsFinite(value, 1e-50);
325}
326
327G4bool BDS::IsFinite(const G4ThreeVector& value,
328 G4double tolerance)
329{
330 G4bool resultX = BDS::IsFinite(value.x(), tolerance);
331 G4bool resultY = BDS::IsFinite(value.y(), tolerance);
332 G4bool resultZ = BDS::IsFinite(value.z(), tolerance);
333 return resultX || resultY || resultZ;
334}
335
336G4bool BDS::IsInteger(const char* ch, int& convertedInteger)
337{
338 // from http://stackoverflow.com/questions/2844817/how-do-i-check-if-a-c-string-is-an-int
339 // convert to string
340 std::string s(ch);
341 if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+')))
342 {return false;}
343
344 char * p;
345 convertedInteger = std::strtol(ch, &p, 10);
346
347 return (*p == 0);
348}
349
350G4bool BDS::IsNumber(const char* ch, double& convertedNumber)
351{
352 // from http://stackoverflow.com/questions/2844817/how-do-i-check-if-a-c-string-is-an-int
353 // convert to string
354 std::string s(ch);
355 if(s.empty() || ((!std::isdigit(s[0])) && (s[0] != '-') && (s[0] != '+')))
356 {return false;}
357
358 char * p;
359 convertedNumber = std::strtod(ch, &p);
360
361 return (*p == 0);
362}
363
364void BDS::PrintRotationMatrix(G4RotationMatrix* rm, G4String keyName)
365{
366 G4cout << "Rotation matrix - reference: \"" << keyName << "\"" << *rm << G4endl;
367 G4cout << "unit x -> " << G4ThreeVector(1,0,0).transform(*rm) << G4endl;
368 G4cout << "unit y -> " << G4ThreeVector(0,1,0).transform(*rm) << G4endl;
369 G4cout << "unit z -> " << G4ThreeVector(0,0,1).transform(*rm) << G4endl;
370}
371
373{
374#if G4VERSION_NUMBER > 1102
375 // Since V4.11.p03, there is just 1 environmental variable to check for
376 std::string entireDataDir = "GEANT4_DATA_DIR";
377 const char* envVar = std::getenv( entireDataDir.c_str() );
378 if (envVar)
379 {return true;}
380#endif
381
382 std::vector<G4String> variables = {//"G4ABLADATA",
383 "G4NEUTRONHPDATA",
384 "G4RADIOACTIVEDATA",
385 "G4LEDATA",
386#if G4VERSION_NUMBER < 1049
387 "G4NEUTRONXSDATA",
388#else
389 "G4PARTICLEXSDATA",
390#endif
391 "G4REALSURFACEDATA",
392 "G4LEVELGAMMADATA",
393 "G4PIIDATA",
394 "G4SAIDXSDATA"};
395
396 // here we loop through all variables - ie don't break the loop
397 G4bool result = true;
398 for (const auto& variable : variables)
399 {
400 const char* env_p = std::getenv( variable.c_str() );
401 if (!env_p)
402 {
403 result = false;
404 G4cerr << "Variable: \"" << variable << "\" not found." << G4endl;
405 }
406 }
407 return result;
408}
409
410void BDS::CheckHighPrecisionDataExists(const G4String& physicsListName)
411{
412 const char* envHPData = std::getenv("G4PARTICLEHPDATA");
413 if (!envHPData)
414 {
415 std::string msg = "The G4TENDL low energy data is not available!\n";
416 msg += "G4TENDL data is required through the environmental variable \"G4PARTICLEHPDATA\"\n;";
417 msg += "This is required for the \"" + physicsListName + "\" physics list.\n";
418 msg += "This data is an optional download from the Geant4 website. Please\n";
419 msg += "download from the Geant4 website and export the environmental variable.";
420 throw BDSException(__METHOD_NAME__, msg);
421 }
422}
423
424void BDS::CheckLowEnergyNeutronDataExists(const G4String& physicsListName)
425{
426 const char* envHPData = std::getenv("G4LENDDATA");
427 if (!envHPData)
428 {
429 std::string msg = "The Low Energy Neutron Data ('LEND') is not available!\n";
430 msg += "Data is required through the environmental variable \"G4LENDDATA\"\n";
431 msg += "This is required for the \"" + physicsListName + "\" physics list.\n";
432 msg += "This data is an optional download from the Geant4 website. Please\n";
433 msg += "download from the Geant4 website and export the environmental variable.";
434 throw BDSException(__METHOD_NAME__, msg);
435 }
436}
437
438G4double BDS::GetParameterValueDouble(G4String spec, G4String name)
439{
440 try
441 {return (G4double)std::stol(GetParameterValueString(spec,name).c_str());}
442 catch(const std::invalid_argument& e)
443 {throw;}
444}
445
446G4int BDS::GetParameterValueInt(G4String spec, G4String name)
447{
448 try
449 {return (G4int)std::stoi(GetParameterValueString(spec,name).c_str());}
450 catch (const std::invalid_argument& e)
451 {throw;}
452}
453
454G4String BDS::GetParameterValueString(G4String spec, G4String name)
455{
456 G4String value;
457 std::string param = name + "=";
458
459 int pos = spec.find(param);
460 if (pos >= 0)
461 {
462 int pos2 = spec.find("&",pos);
463 int pos3 = spec.length();
464 int tend = pos2 < 0 ? pos3 : pos2;
465 int llen = tend - pos - param.length();
466
467 value = spec.substr(pos + param.length(), llen);
468 }
469 return value;
470}
471
472std::vector<G4String> BDS::SplitOnWhiteSpace(const G4String& input)
473{
474 std::vector<G4String> result;
475 if (input.empty())
476 {return result;}
477
478 std::istringstream ss(input);
479
480 G4String word;
481 while (ss >> word)
482 {result.push_back(word);}
483 return result;
484}
485
486G4TwoVector BDS::Rotate(const G4TwoVector& vec, const G4double& angle)
487{
488 G4double xp = vec.x()*std::cos(angle) - vec.y()*std::sin(angle);
489 G4double yp = vec.x()*std::sin(angle) + vec.y()*std::cos(angle);
490 return G4TwoVector(xp,yp);
491}
492
493G4bool BDS::WillIntersect(const G4ThreeVector& incomingNormal,
494 const G4ThreeVector& outgoingNormal,
495 const G4double& zSeparation,
496 const BDSExtent& incomingExtent,
497 const BDSExtent& outgoingExtent)
498{
499 // for any two normal vectors of planes - if their cross
500 // product is zero, then they're (anti) parallel and will
501 // never intersect
502 G4ThreeVector cross = incomingNormal.cross(outgoingNormal);
503 G4double det = cross.mag2();
504 if (!BDS::IsFinite(det))
505 {return false;}
506
507 // shortcuts / copies - OG for outgoing and IC for incoming
508 const BDSExtent& eog = outgoingExtent;
509 const BDSExtent& eic = incomingExtent;
510
511 // z coordinate of points at maximum extents in x,y
512 G4double xNegYNegOG = BDS::GetZOfPointOnPlane(outgoingNormal, eog.XNeg(), eog.YNeg());
513 G4double xNegYPosOG = BDS::GetZOfPointOnPlane(outgoingNormal, eog.XNeg(), eog.YPos());
514 G4double xPosYPosOG = BDS::GetZOfPointOnPlane(outgoingNormal, eog.XPos(), eog.YPos());
515 G4double xPosYNegOG = BDS::GetZOfPointOnPlane(outgoingNormal, eog.XPos(), eog.YNeg());
516 G4double xNegYNegIC = BDS::GetZOfPointOnPlane(incomingNormal, eic.XNeg(), eic.YNeg());
517 G4double xNegYPosIC = BDS::GetZOfPointOnPlane(incomingNormal, eic.XNeg(), eic.YPos());
518 G4double xPosYPosIC = BDS::GetZOfPointOnPlane(incomingNormal, eic.XPos(), eic.YPos());
519 G4double xPosYNegIC = BDS::GetZOfPointOnPlane(incomingNormal, eic.XPos(), eic.YNeg());
520
521 // test of they'd overlap
522 G4bool xNegYNegFail = xNegYNegIC > (zSeparation + xNegYNegOG);
523 G4bool xNegYPosFail = xNegYPosIC > (zSeparation + xNegYPosOG);
524 G4bool xPosYPosFail = xPosYPosIC > (zSeparation + xPosYPosOG);
525 G4bool xPosYNegFail = xPosYNegIC > (zSeparation + xPosYNegOG);
526
527 if (xNegYNegFail || xNegYPosFail || xPosYPosFail || xPosYNegFail)
528 {return true;}
529 else // shouldn't happen
530 {return false;}
531}
532
533G4bool BDS::WillIntersect(const G4double& angleIn,
534 const G4double& angleOut,
535 const G4double& horizontalWidth,
536 const G4double& length)
537{
538 // Calculate the z component of triangle with each angle and
539 // axis along length.
540 G4double dzIn = horizontalWidth * std::tan(angleIn);
541 G4double dzOut = horizontalWidth * std::tan(angleOut);
542 if (dzIn > length - dzOut)
543 {return true;}
544 else
545 {return false;}
546}
547
548G4double BDS::GetZOfPointOnPlane(const G4ThreeVector& normal, G4double x, G4double y)
549{
550 // equation of a plane with offset v_0, normal unit n and any point on plane v
551 // n.(v-v_0) = 0
552 // for equation of plane that intercepts 0,0,0
553 // n.v = 0;
554 // exanding dot product
555 // n.x()*v.x() + n.y()*v.y() + n.z()*v.z() = 0;
556 // for given x and y can solve for z
557 // v.z = (-n.x*v.x - n.y*v.y ) / n.z;
558
559 return (-normal.x()*x - normal.y()*y) / normal.z();
560}
561
562G4ThreeVector BDS::RotateToReferenceFrame(G4ThreeVector faceNormal, G4double fullAngle)
563{
564 if (!BDS::IsFinite(fullAngle))
565 {return faceNormal;} // no angle -> no rotation
566 G4RotationMatrix rm = G4RotationMatrix();
567 rm.rotateY(fullAngle*0.5);
568 return faceNormal.transform(rm);
569}
570
571std::pair<G4String, G4String> BDS::SplitOnColon(const G4String& formatAndPath)
572{
573 if(!formatAndPath.empty())
574 {
575 std::size_t found = formatAndPath.find(":");
576 if (found == std::string::npos)
577 {
578 throw BDSException(__METHOD_NAME__, "invalid specifier \"" + formatAndPath + "\"\n"
579 + "Missing \":\" to separate format and file path");
580 }
581 else
582 {
583 G4String format = formatAndPath.substr(0,found);
584 G4String filePath = formatAndPath.substr(found+1); // get everything after ":"
585 return std::make_pair(format,filePath);
586 }
587 }
588 return std::make_pair("","");
589}
590
591G4UserLimits* BDS::CreateUserLimits(G4UserLimits* defaultUL,
592 G4double length,
593 G4double fraction)
594{
595 G4UserLimits* result = defaultUL;
596 // construct a dummy G4Track that typically isn't used for the check
597 G4Track t = G4Track();
598 if (defaultUL->GetMaxAllowedStep(t) > length)
599 {// copy and change length in UL
600 result = new G4UserLimits(*defaultUL);
601 G4double lengthScale = length * fraction;
602 lengthScale = std::max(lengthScale, 1.0*CLHEP::um); // no smaller than 1um limit
603 result->SetMaxAllowedStep(lengthScale);
604 }
605 return result;
606}
607
609{
610 struct rusage r_usage;
611 int itWorked = getrusage(RUSAGE_SELF, &r_usage);
612 if (itWorked != 0)
613 {return 0;} // failed
614 else
615 {
616 G4double maxMemory = (G4double)r_usage.ru_maxrss;
617#ifdef __APPLE__
618 maxMemory /= 1048*1048;
619#else
620 maxMemory /= 1048;
621#endif
622 return maxMemory;
623 }
624}
625
626std::map<G4String, G4String> BDS::GetUserParametersMap(const G4String& userParameters,
627 char delimiter)
628{
629 // split by white space then by colon
630 std::istringstream iss(userParameters);
631 std::vector<std::string> paramaterPairs(std::istream_iterator<std::string>{iss},
632 std::istream_iterator<std::string>{});
633
634 std::map<G4String, G4String> result;
635 for (auto& pair : paramaterPairs)
636 {
637 auto index = pair.find(delimiter);
638 std::string key = pair.substr(0, index);
639 std::string value = pair.substr(index+1);
640 result[G4String(key)] = G4String(value);
641 }
642 return result;
643}
644
645G4int BDS::VerboseEventStop(G4int verboseEventStart,
646 G4int verboseEventContinueFor)
647{
648 G4int verboseEventStop = 0;
649 if (verboseEventContinueFor < 1)
650 {verboseEventStop = std::numeric_limits<int>::max();}
651 else
652 {verboseEventStop = verboseEventStart + verboseEventContinueFor;}
653 return verboseEventStop;
654}
655
656G4bool BDS::VerboseThisEvent(G4int eventIndex,
657 G4int eventStart,
658 G4int eventStop)
659{
660 return eventIndex >= eventStart && eventIndex < eventStop;
661}
662
663G4double BDS::Rigidity(G4double momentumMagnitude,
664 G4double charge)
665{
666 return momentumMagnitude / CLHEP::GeV / BDS::cOverGeV / charge;
667}
668
669G4double BDS::CalculateSafeAngledVolumeLength(G4ThreeVector inputfaceIn,
670 G4ThreeVector outputfaceIn,
671 G4double length,
672 G4double containerWidth,
673 G4double containerHeight)
674{
675 G4double angleIn = inputfaceIn.angle();
676 G4double angleOut = outputfaceIn.angle();
677 return BDS::CalculateSafeAngledVolumeLength(angleIn, angleOut, length, containerWidth, containerHeight);
678}
679
680G4double BDS::CalculateSafeAngledVolumeLength(G4double angleIn,
681 G4double angleOut,
682 G4double length,
683 G4double containerWidth,
684 G4double containerHeight)
685{
686 G4double sLength = length;
687 if (!BDS::IsFinite(containerHeight))
688 {containerHeight = containerWidth;}
689
690 if (BDS::IsFinite(angleIn) || BDS::IsFinite(angleOut))
691 {
692 // In the case of angled faces, calculate a length so that the straight solids
693 // used in intersection are long enough to reach the edges of the angled faces.
694 // Could simply do 2x length, but for short dipole sections with strongly angled
695 // faces this doesn't work. Calculate extent along z for each angled face. This
696 // is called the 'safe' length -> sLength
697 G4double hypotenuse = std::hypot(containerWidth, containerHeight);
698 G4double dzIn = std::tan(std::abs(angleIn)) * 1.2 * hypotenuse; // 20% over estimation for safety
699 G4double dzOut = std::tan(std::abs(angleOut)) * 1.2 * hypotenuse;
700 // take the longest of different estimations (2x and 1.5x + dZs)
701 sLength = std::max(2 * length, 1.5 * length + dzIn + dzOut);
702 }
703 return sLength;
704}
General exception with possible name of object and message.
Definition: BDSException.hh:35
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
G4double XPos() const
Accessor.
Definition: BDSExtent.hh:66
G4double XNeg() const
Accessor.
Definition: BDSExtent.hh:65
G4double YNeg() const
Accessor.
Definition: BDSExtent.hh:67
G4double YPos() const
Accessor.
Definition: BDSExtent.hh:68
static BDSGlobalConstants * Instance()
Access method.
G4double Rigidity(G4double momentumMagnitude, G4double charge)
Calculate the rigidity for a total momentum and charge.
G4TwoVector Rotate(const G4TwoVector &vec, const G4double &angle)
Rotate a two vector in polar coordinates by an angle.
G4bool WillIntersect(const G4ThreeVector &incomingNormal, const G4ThreeVector &outgoingNormal, const G4double &zSeparation, const BDSExtent &incomingExtent, const BDSExtent &outgoingExtent)
G4String GetParameterValueString(G4String spec, G4String name)
Get parameter value from the specification ('spec') string.
std::pair< G4String, G4String > SplitOnColon(const G4String &formatAndPath)
void SplitFileAndExtension(const G4String &fileName, G4String &file, G4String &extension)
Split a filename.ext into filename and extension. Extension includes '.'.
std::string GetCurrentDir()
Get the current dir the program was executed from.
G4String PrepareSafeName(G4String name)
Remove white space and special characters in the name.
G4bool NonZero(G4double value)
Test whether a number is non-zero - ie abs(number) > minimum number.
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:66
G4ThreeVector RotateToReferenceFrame(G4ThreeVector faceNormal, G4double fullAngle)
static const G4double cOverGeV
speed of light / 1 GeV, used for scaling in brho calculation
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4double GetZOfPointOnPlane(const G4ThreeVector &normal, G4double x, G4double y)
G4double GetMemoryUsage()
Get the current memory usage.
G4String LowerCase(const G4String &str)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
G4bool DirectoryExists(const G4String &path)
Check if directory exists.
void PrintRotationMatrix(G4RotationMatrix *rm, G4String keyName="unknown")
G4bool Geant4EnvironmentIsSet()
Check if the geant4 environmental variables necessary for a run are set.
void EnsureInLimits(G4double &value, G4double lowerLimit, G4double upperLimit)
G4bool FileExists(const G4String &filename)
Checks if filename exists.
void CheckHighPrecisionDataExists(const G4String &physicsListName)
G4bool VerboseThisEvent(G4int eventIndex, G4int eventStart, G4int eventStop)
Logic of whether this event should be verbose or not. Code here so it's not duplicated.
StringStripType
Definition: BDSUtilities.hh:70
void HandleAborts(int signal_number)
std::vector< G4String > SplitOnWhiteSpace(const G4String &input)
Split a string on whitespace and return a vector of these 'words'.
G4double CalculateSafeAngledVolumeLength(G4double angleIn, G4double angleOut, G4double length, G4double containerWidth, G4double containerHeight=0)
Calculate safe length of an angled volume so it fills the length of its container.
G4bool IsNumber(const char *s, double &convertedNumber)
Check if character array is an integer, and returns the double by reference.
G4int VerboseEventStop(G4int verboseEventStart, G4int verboseEventContinueFor)
void CheckLowEnergyNeutronDataExists(const G4String &phhysicsListName)
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
G4bool IsFiniteStrength(G4double variable)
void SplitPathAndFileName(const G4String &filePath, G4String &path, G4String &filename)
std::string GetBDSIMExecPath()
G4bool IsInteger(const char *s, int &convertedInteger)
Check if character array is an integer, and returns the integer by reference.
G4int GetParameterValueInt(G4String spec, G4String name)
Get parameter value from the specification ('spec') string.
std::map< G4String, G4String > GetUserParametersMap(const G4String &userParameters, char delimiter=':')
Take one long string and split on space and then on colon. "key1:value1 key2:value2" etc.
G4int StrCompare(const G4String &str, const G4String &, G4String::caseCompare mode=G4String::ignoreCase)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:75
G4String StrStrip(const G4String &str, char ch, StringStripType stripType=StringStripType::both)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:98
G4int CalculateOrientation(G4double angle)
std::pair< G4ThreeVector, G4ThreeVector > CalculateFaces(G4double angleInIn, G4double angleOutIn)
Calculate input and output normal vector.
G4double GetParameterValueDouble(G4String spec, G4String name)
Get parameter value from the specification ('spec') string.
Logical not for isalpha UnaryPredicate as needed for string manipulations.
Definition: BDSUtilities.hh:54