Skip to content

Commit 9dea1f0

Browse files
committed
added gemc_unit namespace
1 parent 870a437 commit 9dea1f0

3 files changed

Lines changed: 199 additions & 181 deletions

File tree

utilities/gemcConventions.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
#pragma once
22

33
/**
4-
* @file gemcConventions.h
5-
* @brief Conventional constants used by GEMC utility helpers.
4+
* \file gemcConventions.h
5+
* \brief Conventional constants used by GEMC utility helpers.
66
*
77
* This header defines small numeric/string constants that are used across
88
* utility routines (for example, error codes and default configuration values).
99
*/
1010

1111
/**
1212
* @defgroup gemc_utilities_conventions GEMC Utilities Conventions
13-
* @brief Constants and conventional values used by GEMC utility helpers.
13+
* \brief Constants and conventional values used by GEMC utility helpers.
1414
*
1515
* The constants in this group are used by utility helpers to provide
1616
* consistent defaults and error reporting identifiers.
1717
* @{
1818
*/
1919

2020
/**
21-
* @brief Error code used when the configured random engine name is not recognized.
21+
* \brief Error code used when the configured random engine name is not recognized.
2222
*
2323
* This error code is used by the random engine selection logic when the `randomEngine`
2424
* option does not match any supported engine name.
2525
*/
2626
#define EC__RANDOMENGINENOTFOUND 2003
2727

2828
/**
29-
* @brief Default random engine name used when no explicit selection is provided.
29+
* \brief Default random engine name used when no explicit selection is provided.
3030
*
3131
* The value is expected to match one of the CLHEP engine names handled by the
3232
* random engine selection logic.
3333
*/
3434
#define DEFAULT_RANDOM_ENGINE "RanluxEngine"
3535

3636
/**
37-
* @brief Sentinel value used to mark that the random seed has not been explicitly set.
37+
* \brief Sentinel value used to mark that the random seed has not been explicitly set.
3838
*
3939
* When the `seed` option matches this value, the utilities derive a seed using
4040
* time/clock/pid sources.

utilities/gemcUtilities.cc

Lines changed: 164 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -8,183 +8,199 @@
88
// geant4 headers
99
#include "G4Threading.hh"
1010
#include "G4UImanager.hh"
11+
#include "G4UnitsTable.hh"
1112

1213
// gemc
1314
#include "glogger.h"
1415
#include "gtouchable.h"
16+
#include "gutilities.h"
1517

1618
namespace gemc {
19+
// return the number of cores from options.
20+
// if 0 is given, returns max number of available cores
21+
int get_nthreads(const std::shared_ptr<GOptions>& gopts, const std::shared_ptr<GLogger>& log) {
22+
int useThreads = gopts->getScalarInt("nthreads");
1723

18-
// return the number of cores from options.
19-
// if 0 is given, returns max number of available cores
20-
int get_nthreads(const std::shared_ptr<GOptions>& gopts, const std::shared_ptr<GLogger>& log) {
21-
int useThreads = gopts->getScalarInt("nthreads");
24+
// Geant4 provides a platform-specific core count helper.
25+
int ncores = G4Threading::G4GetNumberOfCores();
2226

23-
// Geant4 provides a platform-specific core count helper.
24-
int ncores = G4Threading::G4GetNumberOfCores();
27+
// Clamp user request:
28+
// - 0 means "use all available cores"
29+
// - values larger than available cores are clamped
30+
if (useThreads == 0 || useThreads > ncores) useThreads = ncores;
2531

26-
// Clamp user request:
27-
// - 0 means "use all available cores"
28-
// - values larger than available cores are clamped
29-
if (useThreads == 0 || useThreads > ncores) useThreads = ncores;
32+
log->info(0, "Using ", useThreads, " threads out of ", ncores, " available cores.");
3033

31-
log->info(0, "Using ", useThreads, " threads out of ", ncores, " available cores.");
32-
33-
return useThreads;
34-
}
35-
36-
std::vector<std::string> verbosity_commands([[maybe_unused]] const std::shared_ptr<GOptions>& gopts, [[maybe_unused]] const std::shared_ptr<GLogger>& log) {
37-
std::vector<std::string> cmds;
38-
39-
// --- Always-quiet commands ---
40-
// These commands reduce Geant4 output noise for typical production runs.
41-
cmds.emplace_back("/control/verbose 0");
42-
cmds.emplace_back("/hit/verbose 0");
34+
return useThreads;
35+
}
4336

44-
cmds.emplace_back("/process/verbose 0");
45-
cmds.emplace_back("/process/setVerbose 0 all");
46-
cmds.emplace_back("/process/had/verbose 0");
47-
cmds.emplace_back("/process/had/deex/verbose 0");
48-
cmds.emplace_back("/process/had/cascade 0");
49-
cmds.emplace_back("/process/em/verbose 0");
50-
cmds.emplace_back("/process/eLoss/verbose 0");
37+
std::vector<std::string> verbosity_commands([[maybe_unused]] const std::shared_ptr<GOptions>& gopts,
38+
[[maybe_unused]] const std::shared_ptr<GLogger>& log) {
39+
std::vector<std::string> cmds;
5140

52-
cmds.emplace_back("/tracking/verbose 0");
53-
cmds.emplace_back("/geometry/navigator/verbose 0");
41+
// --- Always-quiet commands ---
42+
// These commands reduce Geant4 output noise for typical production runs.
43+
cmds.emplace_back("/control/verbose 0");
44+
cmds.emplace_back("/hit/verbose 0");
5445

55-
cmds.emplace_back("/event/verbose 0");
56-
cmds.emplace_back("/event/stack/verbose 0");
46+
cmds.emplace_back("/process/verbose 0");
47+
cmds.emplace_back("/process/setVerbose 0 all");
48+
cmds.emplace_back("/process/had/verbose 0");
49+
cmds.emplace_back("/process/had/deex/verbose 0");
50+
cmds.emplace_back("/process/had/cascade 0");
51+
cmds.emplace_back("/process/em/verbose 0");
52+
cmds.emplace_back("/process/eLoss/verbose 0");
5753

58-
cmds.emplace_back("/cuts/verbose 0");
54+
cmds.emplace_back("/tracking/verbose 0");
55+
cmds.emplace_back("/geometry/navigator/verbose 0");
5956

60-
cmds.emplace_back("/run/particle/verbose 0");
61-
cmds.emplace_back("/run/verbose 0");
57+
cmds.emplace_back("/event/verbose 0");
58+
cmds.emplace_back("/event/stack/verbose 0");
6259

63-
cmds.emplace_back("/material/verbose 0");
60+
cmds.emplace_back("/cuts/verbose 0");
6461

65-
cmds.emplace_back("/vis/verbose 0");
66-
cmds.emplace_back("/particle/verbose 0");
62+
cmds.emplace_back("/run/particle/verbose 0");
63+
cmds.emplace_back("/run/verbose 0");
6764

68-
// cmds.emplace_back("/control/cout/ignoreInitializationCout 1");
69-
// cmds.emplace_back("/control/cout/useBuffer 1"); // keep MT output tidy?
65+
cmds.emplace_back("/material/verbose 0");
7066

71-
return cmds;
72-
}
67+
cmds.emplace_back("/vis/verbose 0");
68+
cmds.emplace_back("/particle/verbose 0");
7369

74-
std::vector<std::string> initial_commands(const std::shared_ptr<GOptions>& gopts, [[maybe_unused]] const std::shared_ptr<GLogger>& log) {
75-
// check_overlaps is typically provided by the Geant4 system options set.
76-
auto check_overlaps = gopts->getScalarInt("check_overlaps"); // notice: from g4system options
77-
auto gui = gopts->getSwitch("gui");
70+
// cmds.emplace_back("/control/cout/ignoreInitializationCout 1");
71+
// cmds.emplace_back("/control/cout/useBuffer 1"); // keep MT output tidy?
7872

79-
std::vector<std::string> cmds;
80-
81-
// Batch mode: optionally schedule geometry overlap checks before initialization.
82-
// Geant4 overlap checks use the current "/geometry/test/..." configuration.
83-
if (check_overlaps == 2) {
84-
log->info(0, "Running /geometry/test/run with 50 points.");
85-
cmds.emplace_back("/geometry/test/resolution 50");
86-
cmds.emplace_back("/geometry/test/run");
87-
}
88-
else if (check_overlaps >= 100) {
89-
log->info(0, "Running /geometry/test/run with ", check_overlaps, " points.");
90-
cmds.emplace_back("/geometry/test/resolution " + std::to_string(check_overlaps));
91-
cmds.emplace_back("/geometry/test/run");
73+
return cmds;
9274
}
9375

94-
// A re-initialize is required when:
95-
// - physics changes
96-
// - geometry changes
97-
cmds.emplace_back("/run/initialize");
98-
99-
// If there is no GUI, initialization commands are sufficient.
100-
if (!gui) return cmds;
101-
102-
// GUI mode: set up a minimal visualization scene with trajectories and hits.
103-
cmds.emplace_back("/vis/drawVolume");
104-
105-
// Disable auto refresh and quieten vis messages whilst scene and trajectories are established.
106-
cmds.emplace_back("/vis/viewer/set/autoRefresh false");
107-
cmds.emplace_back("/vis/viewer/set/viewpointVector -1 0 0");
108-
cmds.emplace_back("/vis/viewer/set/lightsVector -1 0 0");
109-
110-
cmds.emplace_back("/vis/scene/add/trajectories smooth");
111-
cmds.emplace_back("/vis/modeling/trajectories/create/drawByCharge");
112-
cmds.emplace_back("/vis/modeling/trajectories/drawByCharge-0/default/setDrawStepPts true");
113-
cmds.emplace_back("/vis/modeling/trajectories/drawByCharge-0/default/setStepPtsSize 2");
114-
cmds.emplace_back("/vis/scene/add/hits");
115-
cmds.emplace_back("/vis/scene/endOfEventAction accumulate 10000");
116-
117-
// Background colors and root volume are the same.
118-
cmds.push_back("/vis/viewer/set/background 0.46666667 0.53333333 0.6");
119-
120-
// Re-enable refresh and flush once configuration is complete.
121-
cmds.emplace_back("/vis/viewer/set/autoRefresh true");
122-
cmds.emplace_back("/vis/viewer/flush");
76+
std::vector<std::string> initial_commands(const std::shared_ptr<GOptions>& gopts,
77+
[[maybe_unused]] const std::shared_ptr<GLogger>& log) {
78+
// check_overlaps is typically provided by the Geant4 system options set.
79+
auto check_overlaps = gopts->getScalarInt("check_overlaps"); // notice: from g4system options
80+
auto gui = gopts->getSwitch("gui");
81+
82+
std::vector<std::string> cmds;
83+
84+
// Batch mode: optionally schedule geometry overlap checks before initialization.
85+
// Geant4 overlap checks use the current "/geometry/test/..." configuration.
86+
if (check_overlaps == 2) {
87+
log->info(0, "Running /geometry/test/run with 50 points.");
88+
cmds.emplace_back("/geometry/test/resolution 50");
89+
cmds.emplace_back("/geometry/test/run");
90+
}
91+
else if (check_overlaps >= 100) {
92+
log->info(0, "Running /geometry/test/run with ", check_overlaps, " points.");
93+
cmds.emplace_back("/geometry/test/resolution " + std::to_string(check_overlaps));
94+
cmds.emplace_back("/geometry/test/run");
95+
}
96+
97+
// A re-initialize is required when:
98+
// - physics changes
99+
// - geometry changes
100+
cmds.emplace_back("/run/initialize");
101+
102+
// If there is no GUI, initialization commands are sufficient.
103+
if (!gui) return cmds;
104+
105+
// GUI mode: set up a minimal visualization scene with trajectories and hits.
106+
cmds.emplace_back("/vis/drawVolume");
107+
108+
// Disable auto refresh and quieten vis messages whilst scene and trajectories are established.
109+
cmds.emplace_back("/vis/viewer/set/autoRefresh false");
110+
cmds.emplace_back("/vis/viewer/set/viewpointVector -1 0 0");
111+
cmds.emplace_back("/vis/viewer/set/lightsVector -1 0 0");
112+
113+
cmds.emplace_back("/vis/scene/add/trajectories smooth");
114+
cmds.emplace_back("/vis/modeling/trajectories/create/drawByCharge");
115+
cmds.emplace_back("/vis/modeling/trajectories/drawByCharge-0/default/setDrawStepPts true");
116+
cmds.emplace_back("/vis/modeling/trajectories/drawByCharge-0/default/setStepPtsSize 2");
117+
cmds.emplace_back("/vis/scene/add/hits");
118+
cmds.emplace_back("/vis/scene/endOfEventAction accumulate 10000");
119+
120+
// Background colors and root volume are the same.
121+
cmds.push_back("/vis/viewer/set/background 0.46666667 0.53333333 0.6");
122+
123+
// Re-enable refresh and flush once configuration is complete.
124+
cmds.emplace_back("/vis/viewer/set/autoRefresh true");
125+
cmds.emplace_back("/vis/viewer/flush");
126+
// cmds.emplace_back("/tracking/verbose 2");
127+
128+
return cmds;
129+
}
123130

124-
return cmds;
125-
}
131+
// initialize G4MTRunManager
132+
void run_manager_commands([[maybe_unused]] const std::shared_ptr<GOptions>& gopts,
133+
const std::shared_ptr<GLogger>& log, const std::vector<std::string>& commands) {
134+
auto* g4uim = G4UImanager::GetUIpointer();
126135

127-
// initialize G4MTRunManager
128-
void run_manager_commands([[maybe_unused]] const std::shared_ptr<GOptions>& gopts, const std::shared_ptr<GLogger>& log, const std::vector<std::string>& commands) {
129-
auto* g4uim = G4UImanager::GetUIpointer();
136+
// Apply commands sequentially so the UI manager sees the same order as a macro file.
137+
for (const auto& cmd : commands) {
138+
log->info(2, "Executing UIManager command: ", cmd);
139+
g4uim->ApplyCommand(cmd);
140+
}
141+
}
130142

131-
// Apply commands sequentially so the UI manager sees the same order as a macro file.
132-
for (const auto& cmd : commands) {
133-
log->info(2, "Executing UIManager command: ", cmd);
134-
g4uim->ApplyCommand(cmd);
143+
void define_new_gemc_units() {
144+
new G4UnitDefinition("milligray", "milliGy", "Dose", gemc_units::milligray);
145+
new G4UnitDefinition("microgray", "microGy", "Dose", gemc_units::microgray);
146+
new G4UnitDefinition("nanogray", "nanoGy", "Dose", gemc_units::nanogray);
147+
new G4UnitDefinition("picogray", "picoGy", "Dose", gemc_units::picogray);
135148
}
136-
}
149+
137150

138151
#include <unistd.h> // needed for get_pid
139152

140-
void start_random_engine(const std::shared_ptr<GOptions>& gopts, const std::shared_ptr<GLogger>& log) {
141-
auto randomEngineName = gopts->getScalarString("randomEngine");
142-
auto seed = gopts->getScalarInt("seed");
143-
144-
// If the user did not set a seed, derive one using several fast-changing sources.
145-
// This helps reduce accidental seed reuse across runs.
146-
if (seed == SEEDNOTSET) {
147-
auto timed = time(NULL);
148-
auto clockd = clock();
149-
auto getpidi = getpid();
150-
seed = (G4int)(timed - clockd - getpidi);
153+
void start_random_engine(const std::shared_ptr<GOptions>& gopts, const std::shared_ptr<GLogger>& log) {
154+
auto randomEngineName = gopts->getScalarString("randomEngine");
155+
auto seed = gopts->getScalarInt("seed");
156+
157+
// If the user did not set a seed, derive one using several fast-changing sources.
158+
// This helps reduce accidental seed reuse across runs.
159+
if (seed == SEEDNOTSET) {
160+
auto timed = time(NULL);
161+
auto clockd = clock();
162+
auto getpidi = getpid();
163+
seed = (G4int)( timed - clockd - getpidi );
164+
log->info(1, "Using random seed ", seed);
165+
} else {
166+
log->info(1, "User defined seed ", seed);
167+
}
168+
169+
170+
// The names come from the CLHEP library, can be found with
171+
// grep ": public HepRandomEngine" *.h $CLHEP_BASE_DIR/include/CLHEP/Random/* | awk -Fclass '{print $2}' | awk -F: '{print $1}'
172+
//
173+
// Select the engine implementation based on the configured string.
174+
if (randomEngineName == "DRand48Engine")
175+
G4Random::setTheEngine(new CLHEP::DRand48Engine(seed));
176+
else if (randomEngineName == "DualRand")
177+
G4Random::setTheEngine(new CLHEP::DualRand(seed));
178+
else if (randomEngineName == "Hurd160Engine")
179+
G4Random::setTheEngine(new CLHEP::Hurd160Engine(seed));
180+
else if (randomEngineName == "HepJamesRandom")
181+
G4Random::setTheEngine(new CLHEP::HepJamesRandom(seed));
182+
else if (randomEngineName == "MTwistEngine")
183+
G4Random::setTheEngine(new CLHEP::MTwistEngine(seed));
184+
else if (randomEngineName == "MixMaxRng")
185+
G4Random::setTheEngine(new CLHEP::MixMaxRng(seed));
186+
else if (randomEngineName == "RandEngine")
187+
G4Random::setTheEngine(new CLHEP::RandEngine(seed));
188+
else if (randomEngineName == "RanecuEngine")
189+
G4Random::setTheEngine(new CLHEP::RanecuEngine(seed));
190+
else if (randomEngineName == "Ranlux64Engine")
191+
G4Random::setTheEngine(new CLHEP::Ranlux64Engine(seed));
192+
else if (randomEngineName == "RanluxEngine")
193+
G4Random::setTheEngine(new CLHEP::RanluxEngine(seed));
194+
else if (randomEngineName == "RanshiEngine")
195+
G4Random::setTheEngine(new CLHEP::RanshiEngine(seed));
196+
else if (randomEngineName == "Hurd288Engine")
197+
G4Random::setTheEngine(new CLHEP::Hurd288Engine(seed));
198+
else if (randomEngineName == "TripleRand")
199+
G4Random::setTheEngine(new CLHEP::TripleRand(seed));
200+
else { log->error(EC__RANDOMENGINENOTFOUND, "Random engine >", randomEngineName, "< not found. Exiting."); }
201+
202+
// Apply the seed after selecting the engine so the engine instance is active.
203+
log->info(0, "Starting random engine ", randomEngineName, " with seed ", seed);
204+
G4Random::setTheSeed(seed);
151205
}
152-
153-
// The names come from the CLHEP library, can be found with
154-
// grep ": public HepRandomEngine" *.h $CLHEP_BASE_DIR/include/CLHEP/Random/* | awk -Fclass '{print $2}' | awk -F: '{print $1}'
155-
//
156-
// Select the engine implementation based on the configured string.
157-
if (randomEngineName == "DRand48Engine")
158-
G4Random::setTheEngine(new CLHEP::DRand48Engine(seed));
159-
else if (randomEngineName == "DualRand")
160-
G4Random::setTheEngine(new CLHEP::DualRand);
161-
else if (randomEngineName == "Hurd160Engine")
162-
G4Random::setTheEngine(new CLHEP::Hurd160Engine);
163-
else if (randomEngineName == "HepJamesRandom")
164-
G4Random::setTheEngine(new CLHEP::HepJamesRandom);
165-
else if (randomEngineName == "MTwistEngine")
166-
G4Random::setTheEngine(new CLHEP::MTwistEngine);
167-
else if (randomEngineName == "MixMaxRng")
168-
G4Random::setTheEngine(new CLHEP::MixMaxRng(seed));
169-
else if (randomEngineName == "RandEngine")
170-
G4Random::setTheEngine(new CLHEP::RandEngine);
171-
else if (randomEngineName == "RanecuEngine")
172-
G4Random::setTheEngine(new CLHEP::RanecuEngine);
173-
else if (randomEngineName == "Ranlux64Engine")
174-
G4Random::setTheEngine(new CLHEP::Ranlux64Engine);
175-
else if (randomEngineName == "RanluxEngine")
176-
G4Random::setTheEngine(new CLHEP::RanluxEngine);
177-
else if (randomEngineName == "RanshiEngine")
178-
G4Random::setTheEngine(new CLHEP::RanshiEngine);
179-
else if (randomEngineName == "Hurd288Engine")
180-
G4Random::setTheEngine(new CLHEP::Hurd288Engine);
181-
else if (randomEngineName == "TripleRand")
182-
G4Random::setTheEngine(new CLHEP::TripleRand);
183-
else { log->error(EC__RANDOMENGINENOTFOUND, "Random engine >", randomEngineName, "< not found. Exiting."); }
184-
185-
// Apply the seed after selecting the engine so the engine instance is active.
186-
log->info(0, "Starting random engine ", randomEngineName, " with seed ", seed);
187-
G4Random::setTheSeed(seed);
188-
}
189-
190206
}

0 commit comments

Comments
 (0)