20 #include "G4IonTable.hh"
21 #include "G4ParticleDefinition.hh"
22 #include "G4ParticleGun.hh"
23 #include "G4SystemOfUnits.hh"
24 #include "G4UImanager.hh"
25 #include "Randomize.hh"
34 : _shootAxis(0, 0, 1), _acceptanceFlag(false), _rndmMinPositionFlag(false), _rndmMaxPositionFlag(false),
35 _rndmFromFlat(false), _rndmFromSphere(false), _rndmSphereCenter(0., 0., 0.), _rndmSphereCapExtRand(0.),
36 _rndmSphereCapAlpha(0.), _rndmSphereCapBeta(0.), _rndmSphereCapRotMat(G4RotationMatrix::IDENTITY),
37 _rndmSphereRadius(0.), _rndmMinEnergyFlag(false), _rndmMaxEnergyFlag(false), _spectralIndexFlag(false),
38 _rndmMinThetaFlag(false), _rndmMaxThetaFlag(false), _rndmMinPhiFlag(false), _rndmMaxPhiFlag(false),
39 _rndmPosFlag(false), _rndmDirFlag(false), _position(0., 0., 0.), _minPosition(0., 0., 0.),
40 _maxPosition(0., 0., 0.), _energy(10. * GeV), _minEnergy(10. * GeV), _maxEnergy(10. * GeV), _spectralIndex(-3.2),
41 _sinTheta(0.), _cosTheta(1.), _minThetaRand(0.), _maxThetaRand(.5), _minCos2ThetaRand(0.), _maxCos2ThetaRand(1.),
42 _sinPhi(0.), _cosPhi(1.), _minPhi(0.), _maxPhi(2 * CLHEP::pi), _direction(0., 0., 0.) {
46 _gunGenerator =
new G4ParticleGun(1);
47 _gunGenerator->SetParticleDefinition(G4ParticleTable::GetParticleTable()->FindParticle(
"geantino"));
63 if (particle ==
"C12") {
65 G4ParticleDefinition *c12 = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon(6, 12, 0.);
66 ((G4ParticleGun *)_gunGenerator)->SetParticleDefinition(c12);
67 ((G4ParticleGun *)_gunGenerator)->SetParticleCharge(6 * eplus);
68 }
else if (particle ==
"Fe56") {
70 G4ParticleDefinition *fe56 = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon(26, 56, 0.);
71 ((G4ParticleGun *)_gunGenerator)->SetParticleDefinition(fe56);
72 ((G4ParticleGun *)_gunGenerator)->SetParticleCharge(26 * eplus);
74 G4UImanager::GetUIpointer()->ApplyCommand(G4String(
"/gun/particle ").append(particle));
79 G4RotationMatrix &GGSGunGeneratorAction::_ComputeRotMatrix(
double cosAlpha,
double sinAlpha,
double cosBeta,
83 class Rot3 :
public G4RotationMatrix {
85 void SetMatrix(
double mxx,
double mxy,
double mxz,
double myx,
double myy,
double myz,
double mzx,
double mzy,
99 static Rot3 retMatrix;
124 double xx = cosAlpha * cosBeta * cosBeta + sinBeta * sinBeta;
125 double xy = cosBeta * cosAlpha * sinBeta - cosBeta * sinBeta;
126 double xz = cosBeta * sinAlpha;
127 double yx = sinBeta * cosAlpha * cosBeta - sinBeta * cosBeta;
128 double yy = sinBeta * cosAlpha * sinBeta + cosBeta * cosBeta;
129 double yz = sinBeta * sinAlpha;
130 double zx = -sinAlpha * cosBeta;
131 double zy = -sinAlpha * sinBeta;
132 double zz = cosAlpha;
134 retMatrix.SetMatrix(xx, xy, xz, yx, yy, yz, zx, zy, zz);
141 void GGSGunGeneratorAction::_ResetFlat() {
143 _rndmFromFlat =
false;
144 _minPosition = _maxPosition = G4ThreeVector(0., 0., 0.);
145 _shootAxis = G4ThreeVector(0, 0, 1);
150 void GGSGunGeneratorAction::_ResetSphere() {
152 _rndmFromSphere =
false;
153 _rndmSphereCenter = G4ThreeVector(0., 0., 0.);
154 _rndmSphereRadius = 0;
155 _rndmSphereCapExtRand = 0.;
156 _rndmSphereCapRotMat = G4RotationMatrix::IDENTITY;
161 void GGSGunGeneratorAction::_SetRndmFromSurface(
int surfType) {
166 }
else if (surfType == 1) {
167 if (_minPosition[0] < _maxPosition[0] && _minPosition[1] < _maxPosition[1] && _minPosition[2] == _maxPosition[2]) {
168 _rndmFromFlat =
true;
169 _shootAxis = G4ThreeVector(0, 0, 1);
170 }
else if (_minPosition[0] == _maxPosition[0] && _minPosition[1] < _maxPosition[1] &&
171 _minPosition[2] < _maxPosition[2]) {
172 _rndmFromFlat =
true;
173 _shootAxis = G4ThreeVector(1, 0, 0);
174 }
else if (_minPosition[0] < _maxPosition[0] && _minPosition[1] == _maxPosition[1] &&
175 _minPosition[2] < _maxPosition[2]) {
176 _rndmFromFlat =
true;
177 _shootAxis = G4ThreeVector(0, 1, 0);
179 _rndmFromFlat =
false;
180 _shootAxis = G4ThreeVector(0, 0, 1);
185 }
else if (surfType == 2) {
186 if (_rndmSphereRadius > 0. && _rndmSphereCapExtRand > 0.) {
187 _rndmFromSphere =
true;
189 _rndmSphereCapRotMat = _ComputeRotMatrix(cos(_rndmSphereCapAlpha), sin(_rndmSphereCapAlpha),
190 cos(_rndmSphereCapBeta), sin(_rndmSphereCapBeta));
200 void GGSGunGeneratorAction::_SetRndmDirFlag() {
201 if ((_rndmMinThetaFlag && _rndmMaxThetaFlag) || (_rndmMinPhiFlag && _rndmMaxPhiFlag))
204 _rndmDirFlag =
false;
209 void GGSGunGeneratorAction::_SetRndmPosFlag() {
210 if (_rndmMinPositionFlag && _rndmMaxPositionFlag)
213 _rndmPosFlag =
false;
220 static const std::string routineName(
"GGSGunGeneratorAction::GeneratePrimaries");
221 static const G4ThreeVector xDirection(1, 0, 0);
222 static const G4ThreeVector yDirection(0, 1, 0);
227 G4ThreeVector position(_position);
228 G4ThreeVector direction(_direction);
229 G4double energy(_energy);
231 bool acceptanceCheck =
true;
240 G4double cosPhi(_cosPhi);
241 G4double sinPhi(_sinPhi);
242 if (_rndmMinPhiFlag && _rndmMaxPhiFlag) {
243 double phi = CLHEP::RandFlat::shoot(_minPhi, _maxPhi);
248 G4double sinTheta(_sinTheta);
249 G4double cosTheta(_cosTheta);
250 if (_rndmMinThetaFlag && _rndmMaxThetaFlag) {
251 if (_rndmFromFlat || _rndmFromSphere) {
253 float cos2Theta = CLHEP::RandFlat::shoot(_minCos2ThetaRand, _maxCos2ThetaRand);
254 cosTheta = sqrt(cos2Theta);
255 sinTheta = sqrt(1 - cos2Theta);
261 cosTheta = 1 - 2 * CLHEP::RandFlat::shoot(_minThetaRand, _maxThetaRand);
262 sinTheta = sqrt(1 - cosTheta * cosTheta);
267 direction[0] = -sinTheta * cosPhi;
268 direction[1] = -sinTheta * sinPhi;
269 direction[2] = -cosTheta;
274 if (_rndmMinPositionFlag && _rndmMaxPositionFlag) {
276 position[0] = CLHEP::RandFlat::shoot(_minPosition(0), _maxPosition(0));
277 position[1] = CLHEP::RandFlat::shoot(_minPosition(1), _maxPosition(1));
278 position[2] = CLHEP::RandFlat::shoot(_minPosition(2), _maxPosition(2));
285 if (_shootAxis == xDirection) {
286 double buf = direction[0];
287 direction[0] = direction[2];
288 direction[2] = direction[1];
290 }
else if (_shootAxis == yDirection) {
291 double buf = direction[0];
292 direction[0] = direction[1];
293 direction[1] = direction[2];
297 }
else if (_rndmFromSphere) {
301 float cosGamma = 1 - 2 * CLHEP::RandFlat::shoot(0., _rndmSphereCapExtRand);
302 float delta = CLHEP::RandFlat::shoot(0., 2 * CLHEP::pi);
303 float sinGamma = sqrt(1 - cosGamma * cosGamma);
304 float sinDelta = sin(delta);
305 float cosDelta = cos(delta);
308 position[0] = _rndmSphereRadius * sinGamma * cosDelta;
309 position[1] = _rndmSphereRadius * sinGamma * sinDelta;
310 position[2] = _rndmSphereRadius * cosGamma;
313 position *= _rndmSphereCapRotMat;
314 position += _rndmSphereCenter;
322 direction *= _ComputeRotMatrix(cosGamma, sinGamma, cosDelta, sinDelta);
323 direction *= _rndmSphereCapRotMat;
328 if (_acceptanceFlag && (_rndmPosFlag || _rndmDirFlag)) {
332 if (!acceptanceCheck)
336 }
while (!acceptanceCheck);
339 if (_rndmMinEnergyFlag && _rndmMaxEnergyFlag) {
340 if (_spectralIndexFlag) {
341 energy = _GenSpectrumPowerLaw(_minEnergy, _maxEnergy, _spectralIndex);
343 energy = CLHEP::RandFlat::shoot(_minEnergy, _maxEnergy);
347 COUT(DEEPDEB) <<
"Generated primary:" <<
ENDL;
348 CCOUT(DEEPDEB) <<
" PDG code: " << _gunGenerator->GetParticleDefinition()->GetPDGEncoding() <<
ENDL;
349 CCOUT(DEEPDEB) <<
" position: " << position <<
ENDL;
350 CCOUT(DEEPDEB) <<
" direction: " << direction <<
ENDL;
351 CCOUT(DEEPDEB) <<
" energy: " << energy <<
ENDL;
356 _gunGenerator->SetParticlePosition(position);
357 _gunGenerator->SetParticleMomentumDirection(direction);
358 _gunGenerator->SetParticleEnergy(energy);
361 _gunGenerator->GeneratePrimaryVertex(anEvent);
366 params.
SetParam(
"generator", std::string(
"gun"));
368 params.
SetParam(
"acceptanceCheck", _acceptanceFlag);
371 params.
SetParam(
"particlePdgCode", _gunGenerator->GetParticleDefinition()->GetPDGEncoding());
375 if (_rndmMinPositionFlag && _rndmMaxPositionFlag) {
376 params.
SetParam(
"minPosition", std::vector<double>{_minPosition[0] / CLHEP::cm, _minPosition[1] / CLHEP::cm,
377 _minPosition[2] / CLHEP::cm});
378 params.
SetParam(
"maxPosition", std::vector<double>{_maxPosition[0] / CLHEP::cm, _maxPosition[1] / CLHEP::cm,
379 _maxPosition[2] / CLHEP::cm});
381 params.
SetParam(
"genPosition", std::string(
"plane"));
383 params.
SetParam(
"genPosition", std::string(
"box"));
385 }
else if (_rndmFromSphere) {
386 params.
SetParam(
"genPosition", std::string(
"sphere"));
388 std::vector<double>{_rndmSphereCenter[0] / CLHEP::cm, _rndmSphereCenter[1] / CLHEP::cm,
389 _rndmSphereCenter[2] / CLHEP::cm});
390 params.
SetParam(
"sphereCapPosition",
391 std::vector<double>{_rndmSphereCapPosition[0] / CLHEP::cm, _rndmSphereCapPosition[1] / CLHEP::cm,
392 _rndmSphereCapPosition[2] / CLHEP::cm});
393 params.
SetParam(
"sphereCapExtension", acos(-2. * _rndmSphereCapExtRand + 1) / CLHEP::rad);
396 params.
SetParam(
"genPosition", std::string(
"point"));
398 std::vector<double>{_position[0] / CLHEP::cm, _position[1] / CLHEP::cm, _position[2] / CLHEP::cm});
403 bool isotropic =
false;
404 if (_rndmMinPhiFlag && _rndmMaxPhiFlag) {
405 params.
SetParam(
"minPhi", _minPhi / CLHEP::rad);
406 params.
SetParam(
"maxPhi", _maxPhi / CLHEP::rad);
408 if (_rndmMinThetaFlag && _rndmMaxThetaFlag) {
409 params.
SetParam(
"minTheta", acos(-2. * _minThetaRand + 1) / CLHEP::rad);
410 params.
SetParam(
"maxTheta", acos(-2. * _maxThetaRand + 1) / CLHEP::rad);
411 if (_rndmFromFlat || _rndmFromSphere) {
416 params.
SetParam(
"genDirection", std::string(
"isotropic"));
418 params.
SetParam(
"genDirection", std::string(
"uniform"));
421 params.
SetParam(
"genDirection", std::string(
"fixed"));
422 params.
SetParam(
"theta", acos(_cosTheta) / CLHEP::rad);
423 params.
SetParam(
"phi", acos(_cosPhi) / CLHEP::rad);
427 if (_rndmMinEnergyFlag && _rndmMaxEnergyFlag) {
428 params.
SetParam(
"minEnergy", _minEnergy / CLHEP::GeV);
429 params.
SetParam(
"maxEnergy", _maxEnergy / CLHEP::GeV);
430 if (_spectralIndexFlag) {
431 params.
SetParam(
"genSpectrum", std::string(
"powerLaw"));
432 params.
SetParam(
"spectralIndex", _spectralIndex);
434 params.
SetParam(
"genSpectrum", std::string(
"flat"));
437 params.
SetParam(
"genSpectrum", std::string(
"monochromatic"));
438 params.
SetParam(
"energy", _energy / CLHEP::GeV);
447 G4double GGSGunGeneratorAction::_GenSpectrumPowerLaw(G4double Emin, G4double Emax, G4double gamma) {
451 energy = CLHEP::RandFlat::shoot(Emin, Emax);
454 G4double alpha = 1. + gamma;
456 energy = exp(log(Emin) + CLHEP::RandFlat::shoot(0., 1.) * (log(Emax) - log(Emin)));
461 pow((CLHEP::RandFlat::shoot(0., 1.) * (pow(Emax, alpha) - pow(Emin, alpha)) + pow(Emin, alpha)), 1. / alpha);
GGSGunGeneratorAction()
Constructor.
#define COUT(level)
Smart log macro. It writes on stdout only if the specified verbosity level is lesser than the maximum...
Class for GGS detector construction.
void SetMaxPhi(G4double val)
Sets the maximum value for phi.
Messenger class for gun generator action.
A single-particle generator.
void SetParam(const std::string &name, T value)
Sets a parameter.
Class for storing parameters.
const GGSVGeometryConstruction * GetGeometry() const
Returns a pointer to the geometry.
#define CCOUT(level)
Smart log utility which prints no header at the beginning of the line.
void SetGunParticle(const G4String &particle)
Sets the particle to be used by G4ParticleGun.
GGSParameters GetParameters() const
Gets the generation parameters.
static GGSRunManager * GetRunManager()
Static getter function the run manager.
~GGSGunGeneratorAction()
Destructor.
#define RegisterGA(gaClassName, gaName)
Macro for registration of user generator actions.
void GeneratePrimaries(G4Event *)
GeneratePrimaries.
void SetMinPhi(G4double val)
Sets the minimum value for phi.
virtual bool IsInsideAcceptance(const G4ThreeVector &, const G4ThreeVector &) const
Checks if a particle is inside the instrument's acceptance.