File indexing completed on 2026-09-16 08:30:29
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 #include "WLSPrimaryGeneratorAction.hh"
0030
0031 #include "WLSDetectorConstruction.hh"
0032 #include "WLSPrimaryGeneratorMessenger.hh"
0033
0034 #include "G4AutoLock.hh"
0035 #include "G4Event.hh"
0036 #include "G4GeneralParticleSource.hh"
0037 #include "G4Material.hh"
0038 #include "G4MaterialPropertiesTable.hh"
0039 #include "G4OpticalPhoton.hh"
0040 #include "G4PhysicsTable.hh"
0041 #include "G4SystemOfUnits.hh"
0042 #include "G4UImanager.hh"
0043 #include "Randomize.hh"
0044
0045 namespace
0046 {
0047 G4Mutex gen_mutex = G4MUTEX_INITIALIZER;
0048 }
0049
0050
0051
0052 G4bool WLSPrimaryGeneratorAction::fFirst = false;
0053
0054 WLSPrimaryGeneratorAction::WLSPrimaryGeneratorAction(WLSDetectorConstruction* dc)
0055 {
0056 fDetector = dc;
0057
0058 fParticleGun = new G4GeneralParticleSource();
0059 fGunMessenger = new WLSPrimaryGeneratorMessenger(this);
0060 }
0061
0062
0063
0064 WLSPrimaryGeneratorAction::~WLSPrimaryGeneratorAction()
0065 {
0066 delete fParticleGun;
0067 delete fGunMessenger;
0068 if (fIntegralTable) {
0069 fIntegralTable->clearAndDestroy();
0070 delete fIntegralTable;
0071 }
0072 }
0073
0074
0075
0076 void WLSPrimaryGeneratorAction::SetDecayTimeConstant(G4double time)
0077 {
0078 fTimeConstant = time;
0079 }
0080
0081
0082
0083 void WLSPrimaryGeneratorAction::BuildEmissionSpectrum()
0084 {
0085 if (fIntegralTable) return;
0086
0087 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
0088 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
0089
0090 if (!fIntegralTable) fIntegralTable = new G4PhysicsTable(numOfMaterials);
0091
0092 for (G4int i = 0; i < numOfMaterials; ++i) {
0093 auto vec = new G4PhysicsFreeVector();
0094
0095 G4MaterialPropertiesTable* MPT = (*theMaterialTable)[i]->GetMaterialPropertiesTable();
0096
0097 if (MPT) {
0098 G4MaterialPropertyVector* theWLSVector = MPT->GetProperty("WLSCOMPONENT");
0099
0100 if (theWLSVector) {
0101 G4double currentIN = (*theWLSVector)[0];
0102 if (currentIN >= 0.0) {
0103 G4double currentPM = theWLSVector->Energy(0);
0104 G4double currentCII = 0.0;
0105 vec->InsertValues(currentPM, currentCII);
0106 G4double prevPM = currentPM;
0107 G4double prevCII = currentCII;
0108 G4double prevIN = currentIN;
0109
0110 for (size_t j = 1; j < theWLSVector->GetVectorLength(); ++j) {
0111 currentPM = theWLSVector->Energy(j);
0112 currentIN = (*theWLSVector)[j];
0113 currentCII = 0.5 * (prevIN + currentIN);
0114 currentCII = prevCII + (currentPM - prevPM) * currentCII;
0115 vec->InsertValues(currentPM, currentCII);
0116 prevPM = currentPM;
0117 prevCII = currentCII;
0118 prevIN = currentIN;
0119 }
0120 }
0121 }
0122 }
0123 fIntegralTable->insertAt(i, vec);
0124 }
0125 }
0126
0127
0128
0129 void WLSPrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
0130 {
0131 if (!fFirst) {
0132 fFirst = true;
0133 BuildEmissionSpectrum();
0134 }
0135
0136 if (fUseSampledEnergy) {
0137 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
0138
0139 G4double sampledEnergy = 3. * eV;
0140
0141 for (size_t j = 0; j < theMaterialTable->size(); ++j) {
0142 G4Material* fMaterial = (*theMaterialTable)[j];
0143 if (fMaterial->GetName() == "PMMA") {
0144 auto WLSIntensity = fMaterial->GetMaterialPropertiesTable()->GetProperty("WLSCOMPONENT");
0145
0146 if (WLSIntensity) {
0147 auto WLSIntegral = (G4PhysicsFreeVector*)((*fIntegralTable)(fMaterial->GetIndex()));
0148
0149 G4double CIImax = WLSIntegral->GetMaxValue();
0150 G4double CIIvalue = G4UniformRand() * CIImax;
0151
0152 sampledEnergy = WLSIntegral->GetEnergy(CIIvalue);
0153 }
0154 }
0155 }
0156
0157
0158 G4String cmd = "/gun/energy " + G4UIcommand::ConvertToString(sampledEnergy / eV) + " eV";
0159 G4UImanager::GetUIpointer()->ApplyCommand(cmd);
0160 }
0161
0162
0163
0164
0165 G4AutoLock l(&gen_mutex);
0166 if (fParticleGun->GetParticleDefinition() == G4OpticalPhoton::Definition()) {
0167 SetOptPhotonPolar();
0168 SetOptPhotonTime();
0169 }
0170
0171 fParticleGun->GeneratePrimaryVertex(anEvent);
0172 }
0173
0174
0175
0176 void WLSPrimaryGeneratorAction::SetOptPhotonPolar()
0177 {
0178 G4double angle = G4UniformRand() * 360.0 * deg;
0179 SetOptPhotonPolar(angle);
0180 }
0181
0182
0183
0184 void WLSPrimaryGeneratorAction::SetOptPhotonPolar(G4double angle)
0185 {
0186 if (fParticleGun->GetParticleDefinition()->GetParticleName() != "opticalphoton") {
0187 G4cout << "-> warning from WLSPrimaryGeneratorAction::SetOptPhotonPolar()"
0188 << ": the ParticleGun is not an opticalphoton" << G4endl;
0189 return;
0190 }
0191
0192 G4ThreeVector normal(1., 0., 0.);
0193 G4ThreeVector kphoton = fParticleGun->GetParticleMomentumDirection();
0194 G4ThreeVector product = normal.cross(kphoton);
0195 G4double modul2 = product * product;
0196
0197 G4ThreeVector e_perpend(0., 0., 1.);
0198 if (modul2 > 0.) e_perpend = (1. / std::sqrt(modul2)) * product;
0199 G4ThreeVector e_paralle = e_perpend.cross(kphoton);
0200
0201 G4ThreeVector polar = std::cos(angle) * e_paralle + std::sin(angle) * e_perpend;
0202 fParticleGun->SetParticlePolarization(polar);
0203 }
0204
0205
0206
0207 void WLSPrimaryGeneratorAction::SetOptPhotonTime()
0208 {
0209 G4double time = -std::log(G4UniformRand()) * fTimeConstant;
0210 fParticleGun->SetParticleTime(time);
0211 }