File indexing completed on 2025-02-23 09:21:55
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 #include "PrimaryGeneratorAction.hh"
0031
0032 #include "G4Event.hh"
0033 #include "G4ParticleGun.hh"
0034 #include "G4PhysicalConstants.hh"
0035 #include "G4SystemOfUnits.hh"
0036 #include "Randomize.hh"
0037
0038 #include <fstream>
0039
0040 PrimaryGeneratorAction::PrimaryGeneratorAction(DetectorConstruction* detector)
0041 : G4VUserPrimaryGeneratorAction(), fDetector(detector)
0042 {
0043 fpParticleGun = std::make_unique<G4ParticleGun>();
0044 fpParticleGun->SetParticleEnergy(-1);
0045 }
0046
0047
0048
0049 void PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
0050 {
0051
0052 G4double energy = fpParticleGun->GetParticleEnergy();
0053
0054
0055
0056 if (energy == -1) {
0057
0058
0059 fMonoEnergetic = false;
0060 }
0061
0062 if (!fMonoEnergetic) {
0063 energy = GenerateParticleEnergy();
0064 }
0065
0066 fpParticleGun->SetParticleEnergy(energy);
0067 fpParticleGun->SetParticlePosition(GenerateParticlePosition());
0068 fpParticleGun->SetParticleMomentumDirection(
0069 GenerateParticleDirection());
0070
0071 fpParticleGun->GeneratePrimaryVertex(anEvent);
0072 }
0073
0074
0075
0076 G4double PrimaryGeneratorAction::GenerateParticleEnergy()
0077 {
0078 if (fEnergySpectrum_length == 0) {
0079 std::ifstream fin(fEnergySpectrumFilename);
0080 G4String len, gain, offset, counts;
0081 fin >> len >> gain >> offset;
0082 fEnergySpectrum_length = std::stoi(len);
0083 fEnergySpectrum_gain = std::stod(gain);
0084 fEnergySpectrum_offset = std::stod(offset);
0085
0086 fEnergySpectrum_counts.resize(fEnergySpectrum_length);
0087 for (G4int i = 0; i < fEnergySpectrum_length; i++) {
0088 fin >> counts;
0089 fEnergySpectrum_counts[i] = std::stoi(counts);
0090 }
0091 }
0092
0093 auto max_en_counter = fEnergySpectrum_counts[fEnergySpectrum_length - 1] - 1;
0094 auto rand_count = 1 + G4int(G4UniformRand() * max_en_counter);
0095
0096
0097
0098 G4int en_id = 0;
0099 for (; rand_count > fEnergySpectrum_counts[en_id]; en_id++)
0100 ;
0101
0102 G4int left = fEnergySpectrum_counts[en_id - 1];
0103 G4int right = fEnergySpectrum_counts[en_id];
0104
0105 G4double en_left = (en_id - 1) * fEnergySpectrum_gain + fEnergySpectrum_offset;
0106 G4double en_right = en_id * fEnergySpectrum_gain + fEnergySpectrum_offset;
0107
0108
0109 G4double slope = (en_right - en_left) / (right - left);
0110 return (en_left + slope * (rand_count - left)) * MeV;
0111 }
0112
0113
0114
0115 G4ThreeVector PrimaryGeneratorAction::GenerateParticlePosition()
0116 {
0117
0118 G4double r = std::sqrt(G4UniformRand()) * fDetector->GetCollDiameter() / 2.;
0119 G4double phi = G4UniformRand() * twopi;
0120
0121 G4double x = fDetector->GetCollExitPosistion() - fDetector->GetCollLength();
0122 G4double y = r * std::cos(phi);
0123 G4double z = r * std::sin(phi);
0124
0125 return {x, y, z};
0126 }
0127
0128
0129
0130 G4ThreeVector PrimaryGeneratorAction::GenerateParticleDirection()
0131 {
0132 G4double phi, theta;
0133 G4double px, py, pz;
0134
0135 phi = G4UniformRand() * twopi;
0136
0137
0138
0139
0140
0141
0142
0143 G4double cos_max_theta =
0144 std::cos(std::atan(fDetector->GetCollDiameter() / fDetector->GetCollLength()));
0145 theta = std::acos(cos_max_theta + G4UniformRand() * (1 - cos_max_theta));
0146
0147 px = std::cos(theta);
0148 py = std::sin(theta) * std::sin(phi);
0149 pz = std::sin(theta) * std::cos(phi);
0150
0151 return {px, py, pz};
0152 }
0153