Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // G4GeneralParticleSource class implementation 27 // 28 // Author: Fan Lei, QinetiQ ltd - 05/02/2004 29 // Customer: ESA/ESTEC 30 // Version: 2.0 31 // -------------------------------------------------------------------- 32 33 #include "G4Event.hh" 34 #include "Randomize.hh" 35 #include "G4GeneralParticleSource.hh" 36 #include "G4SingleParticleSource.hh" 37 #include "G4UnitsTable.hh" 38 39 #include "G4GeneralParticleSourceData.hh" 40 41 #include "G4Threading.hh" 42 #include "G4AutoLock.hh" 43 44 namespace 45 { 46 G4Mutex messangerInit = G4MUTEX_INITIALIZER; 47 } 48 49 G4GeneralParticleSource::G4GeneralParticleSource() 50 { 51 GPSData = G4GeneralParticleSourceData::Instance(); 52 // currentSource = GPSData->GetCurrentSource(); 53 // currentSourceIdx = G4int(GPSData->GetSourceVectorSize() - 1); 54 55 // Messenger is special, only a worker should instantiate it. 56 // Singleton pattern 57 // 58 theMessenger = G4GeneralParticleSourceMessenger::GetInstance(this); 59 60 // Some initialization should be done only once 61 // 62 G4AutoLock l(&messangerInit); 63 static G4bool onlyOnce = false; 64 if ( !onlyOnce ) 65 { 66 theMessenger->SetParticleGun(GPSData->GetCurrentSource()); 67 IntensityNormalization(); 68 onlyOnce = true; 69 } 70 } 71 72 G4GeneralParticleSource::~G4GeneralParticleSource() 73 { 74 theMessenger->Destroy(); 75 } 76 77 void G4GeneralParticleSource::AddaSource(G4double aV) 78 { 79 GPSData->Lock(); 80 81 GPSData->AddASource(aV); 82 theMessenger->SetParticleGun(GPSData->GetCurrentSource()); 83 84 // TODO: But do we really normalize here after each source? 85 IntensityNormalization(); 86 87 GPSData->Unlock(); 88 } 89 90 void G4GeneralParticleSource::IntensityNormalization() 91 { 92 GPSData->IntensityNormalise(); 93 normalised=GPSData->Normalised(); 94 } 95 96 void G4GeneralParticleSource::ListSource() 97 { 98 G4cout << "The number of particle sources is: " 99 << GPSData->GetIntensityVectorSize() << G4endl; 100 G4cout << " Multiple Vertex sources: " << GPSData->GetMultipleVertex(); 101 G4cout << " Flat Sampling flag: " << GPSData->GetFlatSampling() << G4endl; 102 const G4int currentIdx = GPSData->GetCurrentSourceIdx(); 103 for(G4int i=0; i<GPSData->GetIntensityVectorSize(); ++i) 104 { 105 G4cout << "\tsource " << i << " with intensity: " 106 << GPSData->GetIntensity(i) << G4endl; 107 const G4SingleParticleSource* thisSrc = GPSData->GetCurrentSource(i); 108 G4cout << " \t\tNum Particles: "<<thisSrc->GetNumberOfParticles() 109 << "; Particle type: " 110 << thisSrc->GetParticleDefinition()->GetParticleName() << G4endl; 111 G4cout << " \t\tEnergy: " 112 << G4BestUnit(thisSrc->GetEneDist()->GetMonoEnergy(),"Energy") << G4endl; 113 G4cout << " \t\tDirection: " 114 << thisSrc->GetAngDist()->GetDirection() << "; Position: "; 115 G4cout << G4BestUnit(thisSrc->GetPosDist()->GetCentreCoords(),"Length") 116 << G4endl; 117 G4cout << " \t\tAngular Distribution: " 118 << thisSrc->GetAngDist()->GetDistType() << G4endl; 119 G4cout << " \t\tEnergy Distribution: " 120 << thisSrc->GetEneDist()->GetEnergyDisType() << G4endl; 121 G4cout << " \t\tPosition Distribution Type: " 122 << thisSrc->GetPosDist()->GetPosDisType(); 123 G4cout << "; Position Shape: " 124 << thisSrc->GetPosDist()->GetPosDisShape() << G4endl; 125 } 126 127 // Set back previous source 128 GPSData->GetCurrentSource(currentIdx); 129 } 130 131 void G4GeneralParticleSource::SetCurrentSourceto(G4int aV) 132 { 133 G4int id = aV; 134 if ( id < GPSData->GetIntensityVectorSize() ) 135 { 136 // currentSourceIdx = aV; 137 // currentSource = GPSData->GetCurrentSource(id); 138 theMessenger->SetParticleGun(GPSData->GetCurrentSource(id)); 139 } 140 else 141 { 142 G4ExceptionDescription msg; 143 msg << "Trying to set source to index " << aV << " but only " 144 << GPSData->GetIntensityVectorSize() << " sources are defined."; 145 G4Exception("G4GeneralParticleSoruce::SetCurrentSourceto", "G4GPS004", 146 FatalException, msg); 147 } 148 } 149 150 void G4GeneralParticleSource::SetCurrentSourceIntensity(G4double aV) 151 { 152 GPSData->Lock(); 153 GPSData->SetCurrentSourceIntensity(aV); 154 GPSData->Unlock(); 155 normalised = GPSData->Normalised(); 156 } 157 158 void G4GeneralParticleSource::ClearAll() 159 { 160 GPSData->ClearSources(); 161 normalised=GPSData->Normalised(); 162 } 163 164 void G4GeneralParticleSource::DeleteaSource(G4int aV) 165 { 166 G4int id = aV; 167 if ( id <= GPSData->GetIntensityVectorSize() ) 168 { 169 GPSData->DeleteASource(aV); 170 normalised=GPSData->Normalised(); 171 } 172 else 173 { 174 G4cout << " source index is invalid " << G4endl; 175 G4cout << " it shall be <= " 176 << GPSData->GetIntensityVectorSize() << G4endl; 177 } 178 } 179 180 void G4GeneralParticleSource::GeneratePrimaryVertex(G4Event* evt) 181 { 182 if (!GPSData->GetMultipleVertex()) 183 { 184 G4SingleParticleSource* currentSource = GPSData->GetCurrentSource(); 185 if (GPSData->GetIntensityVectorSize() > 1) 186 { 187 // Try to minimize locks 188 if (! normalised ) 189 { 190 // According to local variable, normalization is needed 191 // Check with underlying shared resource, another 192 // thread could have already normalized this 193 GPSData->Lock(); 194 G4bool norm = GPSData->Normalised(); 195 if (!norm) 196 { 197 IntensityNormalization(); 198 } 199 // This takes care of the case in which the local variable 200 // is False and the underlying resource is true. 201 normalised = GPSData->Normalised(); 202 GPSData->Unlock(); 203 } 204 G4double rndm = G4UniformRand(); 205 G4int i = 0 ; 206 if (! GPSData->GetFlatSampling() ) 207 { 208 while ( rndm > GPSData->GetSourceProbability(i) ) ++i; 209 currentSource = GPSData->GetCurrentSource(i); 210 } 211 else 212 { 213 i = G4int (GPSData->GetIntensityVectorSize()*rndm); 214 currentSource = GPSData->GetCurrentSource(i); 215 } 216 } 217 currentSource->GeneratePrimaryVertex(evt); 218 } 219 else 220 { 221 for (G4int i = 0; i < GPSData->GetIntensityVectorSize(); ++i) 222 { 223 GPSData->GetCurrentSource(i)->GeneratePrimaryVertex(evt); 224 } 225 } 226 } 227