File indexing completed on 2025-01-31 09:22:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include "G4RunManager.hh"
0038 #include "GammaRayTelPrimaryGeneratorAction.hh"
0039
0040 #include "GammaRayTelDetectorConstruction.hh"
0041 #include "GammaRayTelPrimaryGeneratorMessenger.hh"
0042
0043 #include "G4PhysicalConstants.hh"
0044 #include "G4SystemOfUnits.hh"
0045 #include "G4Event.hh"
0046 #include "G4ParticleGun.hh"
0047 #include "G4GeneralParticleSource.hh"
0048 #include "G4ParticleTable.hh"
0049 #include "G4ParticleDefinition.hh"
0050 #include "Randomize.hh"
0051
0052
0053
0054 GammaRayTelPrimaryGeneratorAction::GammaRayTelPrimaryGeneratorAction() {
0055 detector = static_cast<const GammaRayTelDetectorConstruction*>(G4RunManager::GetRunManager()->GetUserDetectorConstruction());
0056
0057
0058
0059 gunMessenger = new GammaRayTelPrimaryGeneratorMessenger(this);
0060
0061 constexpr auto NUMBER_OF_PARTICLES{1};
0062 particleGun = new G4ParticleGun(NUMBER_OF_PARTICLES);
0063
0064
0065
0066 auto *particleTable = G4ParticleTable::GetParticleTable();
0067 auto *particle = particleTable->FindParticle("e-");
0068 particleGun->SetParticleDefinition(particle);
0069 particleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., -1.));
0070
0071 constexpr auto PARTICLE_ENERGY{30. * MeV};
0072 particleGun->SetParticleEnergy(PARTICLE_ENERGY);
0073
0074 auto position = 0.5 * (detector->GetWorldSizeZ());
0075 particleGun->SetParticlePosition(G4ThreeVector(0. * cm, 0. * cm, position));
0076 particleSource = new G4GeneralParticleSource();
0077 }
0078
0079
0080
0081 GammaRayTelPrimaryGeneratorAction::~GammaRayTelPrimaryGeneratorAction() {
0082 delete particleGun;
0083 delete particleSource;
0084 delete gunMessenger;
0085 }
0086
0087
0088
0089 void GammaRayTelPrimaryGeneratorAction::GeneratePrimaries(G4Event *event) {
0090 if (sourceGun) {
0091 G4cout << "Using G4ParticleGun... " << G4endl;
0092
0093
0094
0095 G4double x0 = 0. * cm;
0096 G4double y0 = 0. * cm;
0097 G4double z0 = 0.5 * (detector->GetWorldSizeZ());
0098
0099 G4ThreeVector pos0;
0100 auto vertex0 = G4ThreeVector(x0, y0, z0);
0101 auto momentumDirection0 = G4ThreeVector(0., 0., -1.);
0102
0103 G4double theta;
0104 G4double phi;
0105 G4double y = 0.;
0106 G4double f = 0.;
0107 G4double theta0 = 0.;
0108 G4double phi0 = 0.;
0109
0110 switch (sourceType) {
0111 case 0:
0112 particleGun->SetParticlePosition(vertex0);
0113 particleGun->SetParticleMomentumDirection(momentumDirection0);
0114 break;
0115 case 1:
0116
0117
0118 phi = G4UniformRand() * twopi;
0119 do {
0120 y = G4UniformRand() * 1.0;
0121 theta = G4UniformRand() * pi;
0122 f = std::sin(theta);
0123 } while (y > f);
0124 vertex0 = G4ThreeVector(1., 0., 0.);
0125 vertex0.setMag(vertexRadius);
0126 vertex0.setTheta(theta);
0127 vertex0.setPhi(phi);
0128 particleGun->SetParticlePosition(vertex0);
0129
0130 momentumDirection0 = G4ThreeVector(1., 0., 0.);
0131
0132 do {
0133 phi = G4UniformRand() * twopi;
0134 do {
0135 y = G4UniformRand() * 1.0;
0136 theta = G4UniformRand() * pi;
0137 f = std::sin(theta);
0138 } while (y > f);
0139 momentumDirection0.setPhi(phi);
0140 momentumDirection0.setTheta(theta);
0141 } while (vertex0.dot(momentumDirection0) >= -0.7 * vertex0.mag());
0142
0143 particleGun->SetParticleMomentumDirection((G4ParticleMomentum) momentumDirection0);
0144
0145 break;
0146 case 2:
0147
0148
0149 phi = G4UniformRand() * twopi;
0150
0151 do {
0152 y = G4UniformRand() * 1.0;
0153 theta = G4UniformRand() * halfpi;
0154 f = std::sin(theta) * std::cos(theta);
0155 } while (y > f);
0156
0157 vertex0 = G4ThreeVector(1., 0., 0.);
0158
0159 auto xy = detector->GetWorldSizeXY();
0160 auto z = detector->GetWorldSizeZ();
0161
0162 if (vertexRadius > xy * 0.5) {
0163 G4cout << "vertexRadius too big " << G4endl;
0164 G4cout << "vertexRadius set to " << xy * 0.45 << G4endl;
0165 vertexRadius = xy * 0.45;
0166 }
0167
0168 if (vertexRadius > z * 0.5) {
0169 G4cout << "vertexRadius too high " << G4endl;
0170 G4cout << "vertexRadius set to " << z * 0.45 << G4endl;
0171 vertexRadius = z * 0.45;
0172 }
0173
0174 vertex0.setMag(vertexRadius);
0175 vertex0.setTheta(theta);
0176 vertex0.setPhi(phi);
0177
0178
0179
0180
0181 momentumDirection0 = particleGun->GetParticleMomentumDirection();
0182 if (momentumDirection0.mag() > 0.001) {
0183 theta0 = momentumDirection0.theta();
0184 phi0 = momentumDirection0.phi();
0185 }
0186
0187 if (theta0 != 0.) {
0188 G4ThreeVector rotationAxis(1., 0., 0.);
0189 rotationAxis.setPhi(phi0 + halfpi);
0190 vertex0.rotate(theta0 + pi, rotationAxis);
0191 }
0192 particleGun->SetParticlePosition(vertex0);
0193 break;
0194 }
0195
0196 constexpr auto INITIAL_PARTICLE_ENERGY{100 * MeV};
0197 G4double particleEnergy = INITIAL_PARTICLE_ENERGY;
0198
0199 switch (spectrumType) {
0200 case 0:
0201 y = G4UniformRand();
0202 particleEnergy = y * 9.0 * GeV + 1.0 * GeV;
0203 G4cout << "Particle energy: " << particleEnergy / GeV << " LIN" << G4endl;
0204 break;
0205 case 1:
0206 y = G4UniformRand();
0207 particleEnergy = std::pow(10, y) * GeV;
0208 G4cout << "Particle energy: " << particleEnergy / GeV << " LOG" << G4endl;
0209 break;
0210 case 2:
0211 do {
0212 y = G4UniformRand() * 100000.0;
0213 particleEnergy = G4UniformRand() * 10. * GeV;
0214 f = std::pow(particleEnergy * (1 / GeV), -4.);
0215 } while (y > f);
0216
0217 break;
0218 case 3:
0219 particleEnergy = particleGun->GetParticleEnergy();
0220
0221 G4cout << "Particle energy: " << particleEnergy << " MONOCHROMATIC" << G4endl;
0222 break;
0223 }
0224 particleGun->SetParticleEnergy(particleEnergy);
0225 G4cout << "Particle: " << particleGun->GetParticleDefinition()->GetParticleName() << G4endl;
0226 particleGun->GeneratePrimaryVertex(event);
0227 } else {
0228 particleSource->GeneratePrimaryVertex(event);
0229 }
0230 }