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::_ChangeOfBasisMatrix(
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;
110 double xx = cosAlpha * cosBeta;
111 double yx = sinBeta * cosAlpha;
112 double zx = -sinAlpha;
115 double xy = -sinBeta;
120 double xz = cosBeta * sinAlpha;
121 double yz = sinBeta * sinAlpha;
122 double zz = cosAlpha;
124 retMatrix.SetMatrix(xx, xy, xz, yx, yy, yz, zx, zy, zz);
131 void GGSGunGeneratorAction::_ResetFlat() {
133 _rndmFromFlat =
false;
134 _minPosition = _maxPosition = G4ThreeVector(0., 0., 0.);
135 _shootAxis = G4ThreeVector(0, 0, 1);
140 void GGSGunGeneratorAction::_ResetSphere() {
142 _rndmFromSphere =
false;
143 _rndmSphereCenter = G4ThreeVector(0., 0., 0.);
144 _rndmSphereRadius = 0;
145 _rndmSphereCapExtRand = 0.;
146 _rndmSphereCapRotMat = G4RotationMatrix::IDENTITY;
151 void GGSGunGeneratorAction::_SetRndmFromSurface(
int surfType) {
156 }
else if (surfType == 1) {
157 if (_minPosition[0] < _maxPosition[0] && _minPosition[1] < _maxPosition[1] && _minPosition[2] == _maxPosition[2]) {
158 _rndmFromFlat =
true;
159 _shootAxis = G4ThreeVector(0, 0, 1);
160 }
else if (_minPosition[0] == _maxPosition[0] && _minPosition[1] < _maxPosition[1] &&
161 _minPosition[2] < _maxPosition[2]) {
162 _rndmFromFlat =
true;
163 _shootAxis = G4ThreeVector(1, 0, 0);
164 }
else if (_minPosition[0] < _maxPosition[0] && _minPosition[1] == _maxPosition[1] &&
165 _minPosition[2] < _maxPosition[2]) {
166 _rndmFromFlat =
true;
167 _shootAxis = G4ThreeVector(0, 1, 0);
169 _rndmFromFlat =
false;
170 _shootAxis = G4ThreeVector(0, 0, 1);
175 }
else if (surfType == 2) {
176 if (_rndmSphereRadius > 0. && _rndmSphereCapExtRand > 0.) {
177 _rndmFromSphere =
true;
179 _rndmSphereCapRotMat = _ChangeOfBasisMatrix(cos(_rndmSphereCapAlpha), sin(_rndmSphereCapAlpha),
180 cos(_rndmSphereCapBeta), sin(_rndmSphereCapBeta));
190 void GGSGunGeneratorAction::_SetRndmDirFlag() {
191 if ((_rndmMinThetaFlag && _rndmMaxThetaFlag) || (_rndmMinPhiFlag && _rndmMaxPhiFlag))
194 _rndmDirFlag =
false;
199 void GGSGunGeneratorAction::_SetRndmPosFlag() {
200 if (_rndmMinPositionFlag && _rndmMaxPositionFlag)
203 _rndmPosFlag =
false;
210 static const std::string routineName(
"GGSGunGeneratorAction::GeneratePrimaries");
211 static const G4ThreeVector xDirection(1, 0, 0);
212 static const G4ThreeVector yDirection(0, 1, 0);
217 G4ThreeVector position(_position);
218 G4ThreeVector direction(_direction);
219 G4double energy(_energy);
221 bool acceptanceCheck =
true;
230 G4double cosPhi(_cosPhi);
231 G4double sinPhi(_sinPhi);
232 if (_rndmMinPhiFlag && _rndmMaxPhiFlag) {
233 double phi = CLHEP::RandFlat::shoot(_minPhi, _maxPhi);
238 G4double sinTheta(_sinTheta);
239 G4double cosTheta(_cosTheta);
240 if (_rndmMinThetaFlag && _rndmMaxThetaFlag) {
241 if (_rndmFromFlat || _rndmFromSphere) {
243 float cos2Theta = CLHEP::RandFlat::shoot(_minCos2ThetaRand, _maxCos2ThetaRand);
244 cosTheta = sqrt(cos2Theta);
245 sinTheta = sqrt(1 - cos2Theta);
251 cosTheta = 1 - 2 * CLHEP::RandFlat::shoot(_minThetaRand, _maxThetaRand);
252 sinTheta = sqrt(1 - cosTheta * cosTheta);
257 direction[0] = -sinTheta * cosPhi;
258 direction[1] = -sinTheta * sinPhi;
259 direction[2] = -cosTheta;
264 if (_rndmMinPositionFlag && _rndmMaxPositionFlag) {
266 position[0] = CLHEP::RandFlat::shoot(_minPosition(0), _maxPosition(0));
267 position[1] = CLHEP::RandFlat::shoot(_minPosition(1), _maxPosition(1));
268 position[2] = CLHEP::RandFlat::shoot(_minPosition(2), _maxPosition(2));
275 if (_shootAxis == xDirection) {
276 double buf = direction[0];
277 direction[0] = direction[2];
278 direction[2] = direction[1];
280 }
else if (_shootAxis == yDirection) {
281 double buf = direction[0];
282 direction[0] = direction[1];
283 direction[1] = direction[2];
287 }
else if (_rndmFromSphere) {
291 float cosGamma = 1 - 2 * CLHEP::RandFlat::shoot(0., _rndmSphereCapExtRand);
292 float delta = CLHEP::RandFlat::shoot(0., 2 * CLHEP::pi);
293 float sinGamma = sqrt(1 - cosGamma * cosGamma);
294 float sinDelta = sin(delta);
295 float cosDelta = cos(delta);
298 position[0] = _rndmSphereRadius * sinGamma * cosDelta;
299 position[1] = _rndmSphereRadius * sinGamma * sinDelta;
300 position[2] = _rndmSphereRadius * cosGamma;
303 position *= _rndmSphereCapRotMat;
304 position += _rndmSphereCenter;
312 direction *= _ChangeOfBasisMatrix(cosGamma, sinGamma, cosDelta, sinDelta);
313 direction *= _rndmSphereCapRotMat;
318 if (_acceptanceFlag && (_rndmPosFlag || _rndmDirFlag)) {
322 if (!acceptanceCheck)
326 }
while (!acceptanceCheck);
329 if (_rndmMinEnergyFlag && _rndmMaxEnergyFlag) {
330 if (_spectralIndexFlag) {
331 energy = _GenSpectrumPowerLaw(_minEnergy, _maxEnergy, _spectralIndex);
333 energy = CLHEP::RandFlat::shoot(_minEnergy, _maxEnergy);
337 COUT(DEEPDEB) <<
"Generated primary:" <<
ENDL;
338 CCOUT(DEEPDEB) <<
" PDG code: " << _gunGenerator->GetParticleDefinition()->GetPDGEncoding() <<
ENDL;
339 CCOUT(DEEPDEB) <<
" position: " << position <<
ENDL;
340 CCOUT(DEEPDEB) <<
" direction: " << direction <<
ENDL;
341 CCOUT(DEEPDEB) <<
" energy: " << energy <<
ENDL;
346 _gunGenerator->SetParticlePosition(position);
347 _gunGenerator->SetParticleMomentumDirection(direction);
348 _gunGenerator->SetParticleEnergy(energy);
351 _gunGenerator->GeneratePrimaryVertex(anEvent);
356 params.
SetParam(
"generator", std::string(
"gun"));
358 params.
SetParam(
"acceptanceCheck", _acceptanceFlag);
361 params.
SetParam(
"particlePdgCode", _gunGenerator->GetParticleDefinition()->GetPDGEncoding());
365 if (_rndmMinPositionFlag && _rndmMaxPositionFlag) {
366 params.
SetParam(
"minPosition", std::vector<double>{_minPosition[0] / CLHEP::cm, _minPosition[1] / CLHEP::cm,
367 _minPosition[2] / CLHEP::cm});
368 params.
SetParam(
"maxPosition", std::vector<double>{_maxPosition[0] / CLHEP::cm, _maxPosition[1] / CLHEP::cm,
369 _maxPosition[2] / CLHEP::cm});
371 params.
SetParam(
"genPosition", std::string(
"plane"));
373 params.
SetParam(
"genPosition", std::string(
"box"));
375 }
else if (_rndmFromSphere) {
376 params.
SetParam(
"genPosition", std::string(
"sphere"));
378 std::vector<double>{_rndmSphereCenter[0] / CLHEP::cm, _rndmSphereCenter[1] / CLHEP::cm,
379 _rndmSphereCenter[2] / CLHEP::cm});
380 params.
SetParam(
"sphereCapPosition",
381 std::vector<double>{_rndmSphereCapPosition[0] / CLHEP::cm, _rndmSphereCapPosition[1] / CLHEP::cm,
382 _rndmSphereCapPosition[2] / CLHEP::cm});
383 params.
SetParam(
"sphereCapExtension", acos(-2. * _rndmSphereCapExtRand + 1) / CLHEP::rad);
386 params.
SetParam(
"genPosition", std::string(
"point"));
388 std::vector<double>{_position[0] / CLHEP::cm, _position[1] / CLHEP::cm, _position[2] / CLHEP::cm});
393 bool isotropic =
false;
394 if (_rndmMinPhiFlag && _rndmMaxPhiFlag) {
395 params.
SetParam(
"minPhi", _minPhi / CLHEP::rad);
396 params.
SetParam(
"maxPhi", _maxPhi / CLHEP::rad);
398 if (_rndmMinThetaFlag && _rndmMaxThetaFlag) {
399 params.
SetParam(
"minTheta", acos(-2. * _minThetaRand + 1) / CLHEP::rad);
400 params.
SetParam(
"maxTheta", acos(-2. * _maxThetaRand + 1) / CLHEP::rad);
401 if (_rndmFromFlat || _rndmFromSphere) {
406 params.
SetParam(
"genDirection", std::string(
"isotropic"));
408 params.
SetParam(
"genDirection", std::string(
"uniform"));
411 params.
SetParam(
"genDirection", std::string(
"fixed"));
412 params.
SetParam(
"theta", acos(_cosTheta) / CLHEP::rad);
413 params.
SetParam(
"phi", acos(_cosPhi) / CLHEP::rad);
417 if (_rndmMinEnergyFlag && _rndmMaxEnergyFlag) {
418 params.
SetParam(
"minEnergy", _minEnergy / CLHEP::GeV);
419 params.
SetParam(
"maxEnergy", _maxEnergy / CLHEP::GeV);
420 if (_spectralIndexFlag) {
421 params.
SetParam(
"genSpectrum", std::string(
"powerLaw"));
422 params.
SetParam(
"spectralIndex", _spectralIndex);
424 params.
SetParam(
"genSpectrum", std::string(
"flat"));
427 params.
SetParam(
"genSpectrum", std::string(
"monochromatic"));
428 params.
SetParam(
"energy", _energy / CLHEP::GeV);
437 G4double GGSGunGeneratorAction::_GenSpectrumPowerLaw(G4double Emin, G4double Emax, G4double gamma) {
441 energy = CLHEP::RandFlat::shoot(Emin, Emax);
444 G4double alpha = 1. + gamma;
446 energy = exp(log(Emin) + CLHEP::RandFlat::shoot(0., 1.) * (log(Emax) - log(Emin)));
451 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.