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