// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // /// \file Run.cc /// \brief Implementation of the Run class // // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... #include "Run.hh" #include "DetectorConstruction.hh" #include "PrimaryGeneratorAction.hh" #include "HistoManager.hh" #include "G4Threading.hh" #include "G4AutoLock.hh" #include "G4UnitsTable.hh" #include "G4SystemOfUnits.hh" // mutex in a file scope namespace { //Mutex to lock updating the global ion map G4Mutex ionIdMapMutex = G4MUTEX_INITIALIZER; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... std::map Run::fgIonMap; G4int Run::fgIonId = kMaxHisto1; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Run::Run(DetectorConstruction* det) : G4Run(), fDetector(det), fParticle(nullptr), fEkin(0.) { fEnergyDeposit = fEnergyDeposit2 = 0.; fEnergyFlow = fEnergyFlow2 = 0.; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Run::~Run() { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::Merge(std::map& destinationMap, const std::map& sourceMap) const { for ( const auto& particleData : sourceMap ) { G4String name = particleData.first; const ParticleData& localData = particleData.second; if ( destinationMap.find(name) == destinationMap.end()) { destinationMap[name] = ParticleData(localData.fCount, localData.fEmean, localData.fEmin, localData.fEmax, localData.fTmean); } else { ParticleData& data = destinationMap[name]; data.fCount += localData.fCount; data.fEmean += localData.fEmean; G4double emin = localData.fEmin; if (emin < data.fEmin) data.fEmin = emin; G4double emax = localData.fEmax; if (emax > data.fEmax) data.fEmax = emax; data.fTmean = localData.fTmean; } } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::SetPrimary(G4ParticleDefinition* particle, G4double energy) { fParticle = particle; fEkin = energy; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::CountProcesses(const G4VProcess* process) { G4String procName = process->GetProcessName(); std::map::iterator it = fProcCounter.find(procName); if ( it == fProcCounter.end()) { fProcCounter[procName] = 1; } else { fProcCounter[procName]++; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::ParticleCount(G4String name, G4double Ekin, G4double meanLife) { std::map::iterator it = fParticleDataMap1.find(name); if ( it == fParticleDataMap1.end()) { fParticleDataMap1[name] = ParticleData(1, Ekin, Ekin, Ekin, meanLife); } else { ParticleData& data = it->second; data.fCount++; data.fEmean += Ekin; //update min max G4double emin = data.fEmin; if (Ekin < emin) data.fEmin = Ekin; G4double emax = data.fEmax; if (Ekin > emax) data.fEmax = Ekin; data.fTmean = meanLife; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::AddEdep(G4double edep) { fEnergyDeposit += edep; fEnergyDeposit2 += edep*edep; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::AddEflow(G4double eflow) { fEnergyFlow += eflow; fEnergyFlow2 += eflow*eflow; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::ParticleFlux(G4String name, G4double Ekin) { std::map::iterator it = fParticleDataMap2.find(name); if ( it == fParticleDataMap2.end()) { fParticleDataMap2[name] = ParticleData(1, Ekin, Ekin, Ekin, -1*ns); } else { ParticleData& data = it->second; data.fCount++; data.fEmean += Ekin; //update min max G4double emin = data.fEmin; if (Ekin < emin) data.fEmin = Ekin; G4double emax = data.fEmax; if (Ekin > emax) data.fEmax = Ekin; data.fTmean = -1*ns; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4int Run::GetIonId(G4String ionName) { G4AutoLock lock(&ionIdMapMutex); // updating the global ion map needs to be locked std::map::const_iterator it = fgIonMap.find(ionName); if ( it == fgIonMap.end()) { fgIonMap[ionName] = fgIonId; if (fgIonId < kMaxHisto2) fgIonId++; } return fgIonMap[ionName]; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::Merge(const G4Run* run) { const Run* localRun = static_cast(run); //primary particle info // fParticle = localRun->fParticle; fEkin = localRun->fEkin; // accumulate sums // fEnergyDeposit += localRun->fEnergyDeposit; fEnergyDeposit2 += localRun->fEnergyDeposit2; fEnergyFlow += localRun->fEnergyFlow; fEnergyFlow2 += localRun->fEnergyFlow2; //map: processes count for ( const auto& procCounter : localRun->fProcCounter ) { G4String procName = procCounter.first; G4int localCount = procCounter.second; if ( fProcCounter.find(procName) == fProcCounter.end()) { fProcCounter[procName] = localCount; } else { fProcCounter[procName] += localCount; } } //map: created particles count Merge(fParticleDataMap1, localRun->fParticleDataMap1); //map: particles flux count Merge(fParticleDataMap2, localRun->fParticleDataMap2); G4Run::Merge(run); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::EndOfRun() { G4int prec = 5, wid = prec + 2; G4int dfprec = G4cout.precision(prec); //run condition // G4Material* material = fDetector->GetAbsorMaterial(); G4double density = material->GetDensity(); G4String Particle = fParticle->GetParticleName(); G4cout << "\n The run is " << numberOfEvent << " "<< Particle << " of " << G4BestUnit(fEkin,"Energy") << " through " << G4BestUnit(fDetector->GetAbsorThickness(),"Length") << " of " << material->GetName() << " (density: " << G4BestUnit(density,"Volumic Mass") << ")" << G4endl; if (numberOfEvent == 0) { G4cout.precision(dfprec); return;} //frequency of processes // G4cout << "\n Process calls frequency :" << G4endl; G4int index = 0; for ( const auto& procCounter : fProcCounter ) { G4String procName = procCounter.first; G4int count = procCounter.second; G4String space = " "; if (++index%3 == 0) space = "\n"; G4cout << " " << std::setw(20) << procName << "="<< std::setw(7) << count << space; } G4cout << G4endl; //particles count // G4cout << "\n List of generated particles:" << G4endl; for ( const auto& particleData : fParticleDataMap1 ) { G4String name = particleData.first; ParticleData data = particleData.second; G4int count = data.fCount; G4double eMean = data.fEmean/count; G4double eMin = data.fEmin; G4double eMax = data.fEmax; G4double meanLife = data.fTmean; G4cout << " " << std::setw(13) << name << ": " << std::setw(7) << count << " Emean = " << std::setw(wid) << G4BestUnit(eMean, "Energy") << "\t( " << G4BestUnit(eMin, "Energy") << " --> " << G4BestUnit(eMax, "Energy") << ")"; if (meanLife >= 0.) G4cout << "\tmean life = " << G4BestUnit(meanLife, "Time") << G4endl; else G4cout << "\tstable" << G4endl; } // compute mean Energy deposited and rms // G4int TotNbofEvents = numberOfEvent; fEnergyDeposit /= TotNbofEvents; fEnergyDeposit2 /= TotNbofEvents; G4double rmsEdep = fEnergyDeposit2 - fEnergyDeposit*fEnergyDeposit; if (rmsEdep>0.) rmsEdep = std::sqrt(rmsEdep); else rmsEdep = 0.; G4cout << "\n Mean energy deposit per event = " << G4BestUnit(fEnergyDeposit,"Energy") << "; rms = " << G4BestUnit(rmsEdep, "Energy") << G4endl; // compute mean Energy flow and rms // fEnergyFlow /= TotNbofEvents; fEnergyFlow2 /= TotNbofEvents; G4double rmsEflow = fEnergyFlow2 - fEnergyFlow*fEnergyFlow; if (rmsEflow>0.) rmsEflow = std::sqrt(rmsEflow); else rmsEflow = 0.; G4cout << " Mean energy flow per event = " << G4BestUnit(fEnergyFlow,"Energy") << "; rms = " << G4BestUnit(rmsEflow, "Energy") << G4endl; //particles flux // G4cout << "\n List of particles emerging from the target :" << G4endl; for ( const auto& particleData : fParticleDataMap2 ) { G4String name = particleData.first; ParticleData data = particleData.second; G4int count = data.fCount; G4double eMean = data.fEmean/count; G4double eMin = data.fEmin; G4double eMax = data.fEmax; G4double Eflow = data.fEmean/TotNbofEvents; G4cout << " " << std::setw(13) << name << ": " << std::setw(7) << count << " Emean = " << std::setw(wid) << G4BestUnit(eMean, "Energy") << "\t( " << G4BestUnit(eMin, "Energy") << " --> " << G4BestUnit(eMax, "Energy") << ") \tEflow/event = " << G4BestUnit(Eflow, "Energy") << G4endl; } //histogram Id for populations // G4cout << "\n histo Id for populations :" << G4endl; // Update the histogram titles according to the ion map // and print new titles G4AnalysisManager* analysisManager = G4AnalysisManager::Instance(); for ( const auto& ionMapElement : fgIonMap ) { G4String ionName = ionMapElement.first; G4int h1Id = ionMapElement.second; // print new titles G4cout << " " << std::setw(20) << ionName << " id = "<< std::setw(3) << h1Id << G4endl; // update histogram ids if ( ! analysisManager->GetH1(h1Id) ) continue; // Skip inactive histograms, this is not necessary // but it makes the code safe wrt modifications in future G4String title = analysisManager->GetH1Title(h1Id); title = ionName + title; analysisManager->SetH1Title(h1Id, title); } G4cout << G4endl; //normalize histograms G4int ih = 2; G4double binWidth = analysisManager->GetH1Width(ih); G4double fac = (1./(numberOfEvent*binWidth))*(mm/MeV); analysisManager->ScaleH1(ih,fac); for (ih=14; ih<24; ih++) { binWidth = analysisManager->GetH1Width(ih); G4double unit = analysisManager->GetH1Unit(ih); fac = (second/(binWidth*unit)); analysisManager->ScaleH1(ih,fac); } //remove all contents in fProcCounter, fCount fProcCounter.clear(); fParticleDataMap1.clear(); fParticleDataMap2.clear(); fgIonMap.clear(); //restore default format G4cout.precision(dfprec); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......