Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:21:50

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // This example is provided by the Geant4-DNA collaboration
0027 // chem6 example is derived from chem4 and chem5 examples
0028 //
0029 // Any report or published results obtained using the Geant4-DNA software
0030 // shall cite the following Geant4-DNA collaboration publication:
0031 // J. Appl. Phys. 125 (2019) 104301
0032 // Med. Phys. 45 (2018) e722-e739
0033 // J. Comput. Phys. 274 (2014) 841-882
0034 // Med. Phys. 37 (2010) 4692-4708
0035 // Int. J. Model. Simul. Sci. Comput. 1 (2010) 157-178
0036 // The Geant4-DNA web site is available at http://geant4-dna.org
0037 //
0038 // Authors: W. G. Shin and S. Incerti (CENBG, France)
0039 //
0040 // $Id$
0041 //
0042 /// \file ScoreSpecies.cc
0043 /// \brief Implementation of the ScoreSpecies class
0044 
0045 #include "ScoreSpecies.hh"
0046 
0047 #include "G4AnalysisManager.hh"
0048 #include "G4Event.hh"
0049 #include "G4Scheduler.hh"
0050 #include "G4TScoreNtupleWriter.hh"
0051 #include "G4UImessenger.hh"
0052 #include "G4UnitsTable.hh"
0053 
0054 #include <G4EventManager.hh>
0055 #include <G4MolecularConfiguration.hh>
0056 #include <G4MoleculeCounter.hh>
0057 #include <G4SystemOfUnits.hh>
0058 #include <globals.hh>
0059 
0060 /**
0061  \file ScoreSpecies.cc
0062  \class ScoreSpecies
0063   This is a primitive scorer class for molecular species.
0064   The number of species is recorded for all times (predetermined or
0065   user chosen). It also scores the energy deposition in order to compute the
0066   radiochemical yields.
0067 */
0068 extern std::ofstream out;
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0071 
0072 ScoreSpecies::ScoreSpecies(G4String name, G4int depth)
0073   : G4VPrimitiveScorer(name, depth),
0074     G4UImessenger(),
0075     fEdep(0),
0076     fOutputType("root"),  // other options: "csv", "hdf5", "xml"
0077     fHCID(-1),
0078     fEvtMap(0)
0079 {
0080   fSpeciesdir = new G4UIdirectory("/scorer/species/");
0081   fSpeciesdir->SetGuidance("ScoreSpecies commands");
0082 
0083   fAddTimeToRecordcmd = new G4UIcmdWithADoubleAndUnit("/scorer/species/addTimeToRecord", this);
0084 
0085   fTimeBincmd = new G4UIcmdWithAnInteger("/scorer/species/nOfTimeBins", this);
0086 
0087   fEdep = 0;
0088   fNEvent = 0;
0089   fRunID = 0;
0090   G4MoleculeCounter::Instance()->ResetCounter();
0091 }
0092 
0093 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0094 
0095 ScoreSpecies::~ScoreSpecies()
0096 {
0097   delete fSpeciesdir;
0098   delete fAddTimeToRecordcmd;
0099   delete fTimeBincmd;
0100 }
0101 
0102 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0103 
0104 void ScoreSpecies::SetNewValue(G4UIcommand* command, G4String newValue)
0105 {
0106   if (command == fAddTimeToRecordcmd) {
0107     G4double cmdTime = fAddTimeToRecordcmd->GetNewDoubleValue(newValue);
0108     AddTimeToRecord(cmdTime);
0109   }
0110   if (command == fTimeBincmd) {
0111     ClearTimeToRecord();
0112     G4int cmdBins = fTimeBincmd->GetNewIntValue(newValue);
0113     G4double timeMin = 1 * ps;
0114     G4double timeMax = G4Scheduler::Instance()->GetEndTime() - 1 * ps;
0115     G4double timeLogMin = std::log10(timeMin);
0116     G4double timeLogMax = std::log10(timeMax);
0117     for (G4int i = 0; i < cmdBins; i++) {
0118       AddTimeToRecord(std::pow(10, timeLogMin + i * (timeLogMax - timeLogMin) / (cmdBins - 1)));
0119     }
0120   }
0121 }
0122 
0123 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0124 
0125 G4bool ScoreSpecies::ProcessHits(G4Step* aStep, G4TouchableHistory*)
0126 {
0127   G4double edep = aStep->GetTotalEnergyDeposit();
0128 
0129   if (edep == 0.) return FALSE;
0130 
0131   edep *= aStep->GetPreStepPoint()->GetWeight();  // (Particle Weight)
0132   G4int index = GetIndex(aStep);
0133   fEvtMap->add(index, edep);
0134   fEdep += edep;
0135 
0136   return TRUE;
0137 }
0138 
0139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0140 
0141 void ScoreSpecies::Initialize(G4HCofThisEvent* HCE)
0142 {
0143   fEvtMap = new G4THitsMap<G4double>(GetMultiFunctionalDetector()->GetName(), GetName());
0144 
0145   if (fHCID < 0) {
0146     fHCID = GetCollectionID(0);
0147   }
0148 
0149   HCE->AddHitsCollection(fHCID, (G4VHitsCollection*)fEvtMap);
0150   G4MoleculeCounter::Instance()->ResetCounter();
0151 }
0152 
0153 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0154 
0155 void ScoreSpecies::EndOfEvent(G4HCofThisEvent*)
0156 {
0157   if (G4EventManager::GetEventManager()->GetConstCurrentEvent()->IsAborted()) {
0158     fEdep = 0.;
0159     G4MoleculeCounter::Instance()->ResetCounter();
0160     return;
0161   }
0162 
0163   auto species = G4MoleculeCounter::Instance()->GetRecordedMolecules();
0164 
0165   if (species.get() == 0 || species->size() == 0) {
0166     G4cout << "No molecule recorded, energy deposited= " << G4BestUnit(fEdep, "Energy") << G4endl;
0167     ++fNEvent;
0168     fEdep = 0.;
0169     G4MoleculeCounter::Instance()->ResetCounter();
0170     return;
0171   }
0172 
0173   //  G4cout << "ScoreSpecies::EndOfEvent"<<G4endl;
0174   //  G4cout << "End of event, deposited energy: "
0175   //  << G4BestUnit(fEdep, "Energy") << G4endl;
0176 
0177   for (auto molecule : *species) {
0178     for (auto time_mol : fTimeToRecord) {
0179       double n_mol = G4MoleculeCounter::Instance()->GetNMoleculesAtTime(molecule, time_mol);
0180 
0181       if (n_mol < 0) {
0182         G4cerr << "N molecules not valid < 0 " << G4endl;
0183         G4Exception("", "N<0", FatalException, "");
0184       }
0185 
0186       SpeciesInfo& molInfo = fSpeciesInfoPerTime[time_mol][molecule];
0187       molInfo.fNumber += n_mol;
0188       double gValue = (n_mol / (fEdep / eV)) * 100.;
0189       molInfo.fG += gValue;
0190       molInfo.fG2 += gValue * gValue;
0191 
0192       //      G4cout << "In Save molucule: fNumber " << molInfo.fNumber
0193       //            << " fG " << molInfo.fG
0194       //            << " fEdep " << fEdep/eV
0195       //            << G4endl;
0196     }
0197   }
0198 
0199   ++fNEvent;
0200 
0201   //  G4cout << "End of event " << fNEvent
0202   //         << ", energy deposited=" << G4BestUnit(fEdep, "Energy") << G4endl;
0203 
0204   fEdep = 0.;
0205   G4MoleculeCounter::Instance()->ResetCounter();
0206 }
0207 
0208 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0209 
0210 void ScoreSpecies::AbsorbResultsFromWorkerScorer(G4VPrimitiveScorer* workerScorer)
0211 {
0212   ScoreSpecies* right =
0213     dynamic_cast<ScoreSpecies*>(dynamic_cast<G4VPrimitiveScorer*>(workerScorer));
0214 
0215   if (right == 0) {
0216     return;
0217   }
0218   if (right == this) {
0219     return;
0220   }
0221 
0222   // G4cout<<"ScoreSpecies::AbsorbResultsFromWorkerScorer"<<G4endl;
0223   SpeciesMap::iterator it_map1 = right->fSpeciesInfoPerTime.begin();
0224   SpeciesMap::iterator end_map1 = right->fSpeciesInfoPerTime.end();
0225 
0226   for (; it_map1 != end_map1; ++it_map1) {
0227     InnerSpeciesMap& map2 = it_map1->second;
0228     InnerSpeciesMap::iterator it_map2 = map2.begin();
0229     InnerSpeciesMap::iterator end_map2 = map2.end();
0230 
0231     for (; it_map2 != end_map2; ++it_map2) {
0232       SpeciesInfo& molInfo = fSpeciesInfoPerTime[it_map1->first][it_map2->first];
0233       molInfo.fNumber += it_map2->second.fNumber;
0234       molInfo.fG += it_map2->second.fG;
0235       molInfo.fG2 += it_map2->second.fG2;
0236 
0237       //      G4cout << "In AbsorbeResultsFromWorkerScorer: fNumber "
0238       //             << molInfo.fNumber
0239       //             << " fG "
0240       //             << molInfo.fG
0241       //             << G4endl;
0242     }
0243   }
0244   right->fSpeciesInfoPerTime.clear();
0245 
0246   fNEvent += right->fNEvent;
0247   right->fNEvent = 0;
0248   right->fEdep = 0.;
0249 }
0250 
0251 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0252 
0253 void ScoreSpecies::DrawAll()
0254 {
0255   ;
0256 }
0257 
0258 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0259 
0260 void ScoreSpecies::PrintAll()
0261 {
0262   G4cout << " MultiFunctionalDet  " << detector->GetName() << G4endl;
0263   G4cout << " PrimitiveScorer " << GetName() << G4endl;
0264   G4cout << " Number of events " << fNEvent << G4endl;
0265   G4cout << " Number of energy deposition recorded " << fEvtMap->entries() << G4endl;
0266 
0267   for (auto itr : *fEvtMap->GetMap()) {
0268     G4cout << "  copy no.: " << itr.first << "  energy deposit: " << *(itr.second) / GetUnitValue()
0269            << " [" << GetUnit() << "]" << G4endl;
0270   }
0271 }
0272 
0273 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0274 
0275 void ScoreSpecies::OutputAndClear()
0276 {
0277   if (G4Threading::IsWorkerThread()) return;
0278 
0279   //---------------------------------------------------------------------------
0280   // Save results
0281 
0282   G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
0283   analysisManager->SetDefaultFileType(fOutputType);
0284 
0285   if (analysisManager) {
0286     this->WriteWithAnalysisManager(analysisManager);
0287   }
0288 
0289   fNEvent = 0;
0290   fSpeciesInfoPerTime.clear();
0291 }
0292 
0293 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
0294 
0295 void ScoreSpecies::WriteWithAnalysisManager(G4VAnalysisManager* analysisManager)
0296 {
0297   G4String fileN = "Species" + G4UIcommand::ConvertToString(fRunID);
0298   analysisManager->OpenFile(fileN);
0299   int fNtupleID = analysisManager->CreateNtuple("species", "species");
0300   analysisManager->CreateNtupleIColumn(fNtupleID, "speciesID");
0301   analysisManager->CreateNtupleIColumn(fNtupleID, "number");
0302   analysisManager->CreateNtupleIColumn(fNtupleID, "nEvent");
0303   analysisManager->CreateNtupleSColumn(fNtupleID, "speciesName");
0304   analysisManager->CreateNtupleDColumn(fNtupleID, "time");
0305   analysisManager->CreateNtupleDColumn(fNtupleID, "sumG");
0306   analysisManager->CreateNtupleDColumn(fNtupleID, "sumG2");
0307   analysisManager->FinishNtuple(fNtupleID);
0308 
0309   for (auto it_map1 : fSpeciesInfoPerTime) {
0310     InnerSpeciesMap& map2 = it_map1.second;
0311 
0312     if (it_map1.first == fSpeciesInfoPerTime.begin()->first) {
0313       for (auto it_molname : map2) {
0314         auto tmp_species = it_molname.first;
0315         out << std::setw(12) << tmp_species->GetName() << std::setw(12)
0316             << tmp_species->GetMoleculeID();
0317       }
0318       out << '\n';
0319     }
0320 
0321     for (auto it_map2 : map2) {
0322       double time = it_map1.first;
0323       auto species = it_map2.first;
0324       const G4String& name = species->GetName();
0325       int molID = it_map2.first->GetMoleculeID();
0326       int number = it_map2.second.fNumber;
0327       double G = it_map2.second.fG;
0328       double G2 = it_map2.second.fG2;
0329       G4int N = fNEvent;
0330 
0331       if (time == *fTimeToRecord.rbegin()) {
0332         if (N > 1) {
0333           out << std::setw(12) << G / N << std::setw(12)
0334               << std::sqrt(((G2 / N) - std::pow(G / N, 2)) / (N - 1));
0335         }
0336         else {
0337           out << std::setw(12) << G / N << std::setw(12)
0338               << std::sqrt(((G2 / N) - std::pow(G / N, 2)) / N);
0339         }
0340       }
0341 
0342       analysisManager->FillNtupleIColumn(fNtupleID, 0, molID);  // MolID
0343       analysisManager->FillNtupleIColumn(fNtupleID, 1, number);  // Number
0344       analysisManager->FillNtupleIColumn(fNtupleID, 2, fNEvent);  // Total nb events
0345       analysisManager->FillNtupleSColumn(fNtupleID, 3, name);  // molName
0346       analysisManager->FillNtupleDColumn(fNtupleID, 4, time);  // time
0347       analysisManager->FillNtupleDColumn(fNtupleID, 5, G);  // G
0348       analysisManager->FillNtupleDColumn(fNtupleID, 6, G2);  // G2
0349       analysisManager->AddNtupleRow(fNtupleID);
0350     }
0351   }
0352 
0353   analysisManager->Write();
0354   analysisManager->CloseFile();
0355   fRunID++;
0356 }
0357 
0358 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......