// // ******************************************************************** // * 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 "PrimaryGeneratorAction.hh" #include "HistoManager.hh" #include "G4SystemOfUnits.hh" #include "G4UnitsTable.hh" #include "G4PhysicalConstants.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Run::Run() : G4Run(), fParticle(0), fEkin(0.), fDecayCount(0), fTimeCount(0), fPrimaryTime(0.), fTimeWindow1(0.), fTimeWindow2(0.) { fEkinTot[0] = fPbalance[0] = fEventTime[0] = fEvisEvent[0] = 0. ; fEkinTot[1] = fPbalance[1] = fEventTime[1] = fEvisEvent[1] = DBL_MAX; fEkinTot[2] = fPbalance[2] = fEventTime[2] = fEvisEvent[2] = 0. ; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... Run::~Run() { } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::SetPrimary(G4ParticleDefinition* particle, G4double energy) { fParticle = particle; fEkin = energy; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::ParticleCount(G4String name, G4double Ekin, G4double meanLife) { std::map::iterator it = fParticleDataMap.find(name); if ( it == fParticleDataMap.end()) { fParticleDataMap[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::SetTimeWindow(G4double t1, G4double t2) { fTimeWindow1 = t1; fTimeWindow2 = t2; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::CountInTimeWindow(G4String name, G4bool life1, G4bool life2, G4bool decay) { std::map::iterator it = fActivityMap.find(name); if ( it == fActivityMap.end()) { G4int n1(0), n2(0), nd(0); if(life1) n1 = 1; if(life2) n2 = 1; if(decay) nd = 1; fActivityMap[name] = ActivityData(n1, n2, nd); } else { ActivityData& data = it->second; if(life1) data.fNlife_t1++; if(life2) data.fNlife_t2++; if(decay) data.fNdecay_t1t2++; } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::Balance(G4double Ekin, G4double Pbal) { fDecayCount++; fEkinTot[0] += Ekin; //update min max if (fDecayCount == 1) fEkinTot[1] = fEkinTot[2] = Ekin; if (Ekin < fEkinTot[1]) fEkinTot[1] = Ekin; if (Ekin > fEkinTot[2]) fEkinTot[2] = Ekin; fPbalance[0] += Pbal; //update min max if (fDecayCount == 1) fPbalance[1] = fPbalance[2] = Pbal; if (Pbal < fPbalance[1]) fPbalance[1] = Pbal; if (Pbal > fPbalance[2]) fPbalance[2] = Pbal; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::EventTiming(G4double time) { fTimeCount++; fEventTime[0] += time; if (fTimeCount == 1) fEventTime[1] = fEventTime[2] = time; if (time < fEventTime[1]) fEventTime[1] = time; if (time > fEventTime[2]) fEventTime[2] = time; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::PrimaryTiming(G4double ptime) { fPrimaryTime += ptime; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::EvisEvent(G4double Evis) { fEvisEvent[0] += Evis; if (fTimeCount == 1) fEvisEvent[1] = fEvisEvent[2] = Evis; if (Evis < fEvisEvent[1]) fEvisEvent[1] = Evis; if (Evis > fEvisEvent[2]) fEvisEvent[2] = Evis; } //....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 // fDecayCount += localRun->fDecayCount; fTimeCount += localRun->fTimeCount; fPrimaryTime += localRun->fPrimaryTime; fEkinTot[0] += localRun->fEkinTot[0]; fPbalance[0] += localRun->fPbalance[0]; fEventTime[0] += localRun->fEventTime[0]; fEvisEvent[0] += localRun->fEvisEvent[0]; G4double min,max; min = localRun->fEkinTot[1]; max = localRun->fEkinTot[2]; if (fEkinTot[1] > min) fEkinTot[1] = min; if (fEkinTot[2] < max) fEkinTot[2] = max; // min = localRun->fPbalance[1]; max = localRun->fPbalance[2]; if (fPbalance[1] > min) fPbalance[1] = min; if (fPbalance[2] < max) fPbalance[2] = max; // min = localRun->fEventTime[1]; max = localRun->fEventTime[2]; if (fEventTime[1] > min) fEventTime[1] = min; if (fEventTime[2] < max) fEventTime[2] = max; // min = localRun->fEvisEvent[1]; max = localRun->fEvisEvent[2]; if (fEvisEvent[1] > min) fEvisEvent[1] = min; if (fEvisEvent[2] < max) fEvisEvent[2] = max; //maps std::map::const_iterator itn; for (itn = localRun->fParticleDataMap.begin(); itn != localRun->fParticleDataMap.end(); ++itn) { G4String name = itn->first; const ParticleData& localData = itn->second; if ( fParticleDataMap.find(name) == fParticleDataMap.end()) { fParticleDataMap[name] = ParticleData(localData.fCount, localData.fEmean, localData.fEmin, localData.fEmax, localData.fTmean); } else { ParticleData& data = fParticleDataMap[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; } } //activity fTimeWindow1 = localRun->fTimeWindow1; fTimeWindow2 = localRun->fTimeWindow2; std::map::const_iterator ita; for (ita = localRun->fActivityMap.begin(); ita != localRun->fActivityMap.end(); ++ita) { G4String name = ita->first; const ActivityData& localData = ita->second; if ( fActivityMap.find(name) == fActivityMap.end()) { fActivityMap[name] = ActivityData(localData.fNlife_t1, localData.fNlife_t2, localData.fNdecay_t1t2); } else { ActivityData& data = fActivityMap[name]; data.fNlife_t1 += localData.fNlife_t1; data.fNlife_t2 += localData.fNlife_t2; data.fNdecay_t1t2 += localData.fNdecay_t1t2; } } G4Run::Merge(run); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void Run::EndOfRun() { G4int nbEvents = numberOfEvent; G4String partName = fParticle->GetParticleName(); G4cout << "\n ======================== run summary ======================"; G4cout << "\n The run was " << nbEvents << " " << partName << " of " << G4BestUnit(fEkin,"Energy"); G4cout << "\n ===========================================================\n"; G4cout << G4endl; if (nbEvents == 0) { return; } G4int prec = 4, wid = prec + 2; G4int dfprec = G4cout.precision(prec); //particle count // G4cout << " Nb of generated particles: \n" << G4endl; std::map::iterator it; for (it = fParticleDataMap.begin(); it != fParticleDataMap.end(); it++) { G4String name = it->first; ParticleData data = it->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(15) << 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 if (meanLife < 0.) G4cout << "\tstable" << G4endl; else G4cout << G4endl; } //energy momentum balance // if (fDecayCount > 0) { G4double Ebmean = fEkinTot[0]/fDecayCount; G4double Pbmean = fPbalance[0]/fDecayCount; G4cout << "\n Ekin Total (Q single decay): mean = " << std::setw(wid) << G4BestUnit(Ebmean, "Energy") << "\t( " << G4BestUnit(fEkinTot[1], "Energy") << " --> " << G4BestUnit(fEkinTot[2], "Energy") << ")" << G4endl; G4cout << "\n Momentum balance (excluding gamma desexcitation): mean = " << std::setw(wid) << G4BestUnit(Pbmean, "Energy") << "\t( " << G4BestUnit(fPbalance[1], "Energy") << " --> " << G4BestUnit(fPbalance[2], "Energy") << ")" << G4endl; } //total time of life // if (fTimeCount > 0) { G4double Tmean = fEventTime[0]/fTimeCount; G4double halfLife = Tmean*std::log(2.); G4cout << "\n Total time of life (full chain): mean = " << std::setw(wid) << G4BestUnit(Tmean, "Time") << " half-life = " << std::setw(wid) << G4BestUnit(halfLife, "Time") << " ( " << G4BestUnit(fEventTime[1], "Time") << " --> " << G4BestUnit(fEventTime[2], "Time") << ")" << G4endl; } //total visible Energy // if (fTimeCount > 0) { G4double Evmean = fEvisEvent[0]/fTimeCount; G4cout << "\n Total visible energy (full chain) : mean = " << std::setw(wid) << G4BestUnit(Evmean, "Energy") << " ( " << G4BestUnit(fEvisEvent[1], "Energy") << " --> " << G4BestUnit(fEvisEvent[2], "Energy") << ")" << G4endl; } //activity of primary ion // G4double pTimeMean = fPrimaryTime/nbEvents; G4double molMass = fParticle->GetAtomicMass()*g/mole; G4double nAtoms_perUnitOfMass = Avogadro/molMass; G4double Activity_perUnitOfMass = 0.0; if (pTimeMean > 0.0) { Activity_perUnitOfMass = nAtoms_perUnitOfMass/pTimeMean; } G4cout << "\n Activity of " << partName << " = " << std::setw(wid) << Activity_perUnitOfMass*g/becquerel << " Bq/g (" << Activity_perUnitOfMass*g/curie << " Ci/g) \n" << G4endl; //activities in time window // if (fTimeWindow2 > 0.) { G4double dt = fTimeWindow2 - fTimeWindow1; G4cout << " Activities in time window [t1, t2] = [" << G4BestUnit(fTimeWindow1, "Time") << ", " << G4BestUnit(fTimeWindow2, "Time") << "] (delta time = " << G4BestUnit(dt, "Time") << ") : \n" << G4endl; std::map::iterator ita; for (ita = fActivityMap.begin(); ita != fActivityMap.end(); ita++) { G4String name = ita->first; ActivityData data = ita->second; G4int n1 = data.fNlife_t1; G4int n2 = data.fNlife_t2; G4int ndecay = data.fNdecay_t1t2; G4double actv = ndecay/dt; G4cout << " " << std::setw(15) << name << ": " << " n(t1) = " << std::setw(7) << n1 << "\tn(t2) = " << std::setw(7) << n2 << "\t decays = " << std::setw(7) << ndecay << " ---> = " << G4BestUnit(actv, "Activity") << "\n"; } } G4cout << G4endl; //normalize histograms // G4AnalysisManager* analysisManager = G4AnalysisManager::Instance(); G4double factor = 100./nbEvents; analysisManager->ScaleH1(1,factor); analysisManager->ScaleH1(2,factor); analysisManager->ScaleH1(3,factor); analysisManager->ScaleH1(4,factor); analysisManager->ScaleH1(5,factor); // remove all contents in fParticleDataMap // fParticleDataMap.clear(); fActivityMap.clear(); // restore default precision // G4cout.precision(dfprec); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......