File indexing completed on 2025-12-16 09:31:14
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
0030
0031
0032
0033
0034
0035
0036 #include "ScoreSpecies.hh"
0037
0038 #include "G4Event.hh"
0039 #include "G4UnitsTable.hh"
0040
0041 #include <G4EventManager.hh>
0042 #include <G4MolecularConfiguration.hh>
0043 #include <G4MoleculeCounter.hh>
0044 #include <G4SystemOfUnits.hh>
0045 #include <globals.hh>
0046 #include <iomanip>
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 ScoreSpecies::ScoreSpecies(G4String name, G4int depth)
0060 : G4VPrimitiveScorer(name, depth)
0061 {
0062 auto tMin = 1.0 * CLHEP::picosecond;
0063 auto tMax = 999999 * CLHEP::picosecond;
0064 auto tLogMin = std::log10(tMin);
0065 auto tLogMax = std::log10(tMax);
0066 auto tBins = 50;
0067 for (G4int i = 0; i <= tBins; i++)
0068 AddTimeToRecord(std::pow(10., tLogMin + i * (tLogMax - tLogMin) / tBins));
0069 }
0070
0071
0072
0073 G4bool ScoreSpecies::ProcessHits(G4Step* aStep, G4TouchableHistory*)
0074 {
0075 G4double edep = aStep->GetTotalEnergyDeposit();
0076
0077 if (edep == 0.) return FALSE;
0078
0079 edep *= aStep->GetPreStepPoint()->GetWeight();
0080 G4int index = GetIndex(aStep);
0081 fEvtMap->add(index, edep);
0082 fEdep += edep;
0083
0084 return TRUE;
0085 }
0086
0087
0088
0089 void ScoreSpecies::Initialize(G4HCofThisEvent* HCE)
0090 {
0091 fEvtMap = new G4THitsMap<G4double>(GetMultiFunctionalDetector()->GetName(), GetName());
0092
0093 if (fHCID < 0) {
0094 fHCID = GetCollectionID(0);
0095 }
0096
0097 HCE->AddHitsCollection(fHCID, (G4VHitsCollection*)fEvtMap);
0098 }
0099
0100
0101
0102 void ScoreSpecies::EndOfEvent(G4HCofThisEvent*)
0103 {
0104 if (G4EventManager::GetEventManager()->GetConstCurrentEvent()->IsAborted()) {
0105 fEdep = 0.;
0106 return;
0107 }
0108
0109
0110 auto counter = G4MoleculeCounterManager::Instance()->GetMoleculeCounter<G4MoleculeCounter>(0);
0111 if (counter == nullptr) {
0112 G4Exception("ScoreSpecies::EndOfEvent", "BAD_REFERENCE", FatalException,
0113 "The molecule counter could not be received!");
0114 }
0115
0116 auto indices = counter->GetMapIndices();
0117
0118 if (indices.empty()) {
0119 G4cout << "No molecule recorded, energy deposited= " << G4BestUnit(fEdep, "Energy") << G4endl;
0120 ++fNEvent;
0121 fEdep = 0.;
0122 return;
0123 }
0124
0125 for (const auto& idx : indices) {
0126 for (auto time_mol : fTimeToRecord) {
0127 double n_mol = counter->GetNbMoleculesAtTime(idx, time_mol);
0128
0129 if (n_mol < 0) {
0130 G4cerr << "N molecules not valid < 0 " << G4endl;
0131 G4Exception("", "N<0", FatalException, "");
0132 }
0133
0134 SpeciesInfo& molInfo = fSpeciesInfoPerTime[time_mol][idx.Molecule];
0135 molInfo.fNumber += n_mol;
0136 G4double gValue = (n_mol / (fEdep / eV)) * 100.;
0137 molInfo.fG += gValue;
0138 molInfo.fG2 += gValue * gValue;
0139 }
0140 }
0141 ++fNEvent;
0142
0143 fEdep = 0.;
0144 }
0145
0146
0147
0148 void ScoreSpecies::AbsorbResultsFromWorkerScorer(G4VPrimitiveScorer* workerScorer)
0149 {
0150 auto right =
0151 dynamic_cast<ScoreSpecies*>(dynamic_cast<G4VPrimitiveScorer*>(workerScorer));
0152
0153 if (right == nullptr) {
0154 return;
0155 }
0156 if (right == this) {
0157 return;
0158 }
0159
0160 auto it_map1 = right->fSpeciesInfoPerTime.begin();
0161 auto end_map1 = right->fSpeciesInfoPerTime.end();
0162
0163 for (; it_map1 != end_map1; ++it_map1) {
0164 InnerSpeciesMap& map2 = it_map1->second;
0165 auto it_map2 = map2.begin();
0166 auto end_map2 = map2.end();
0167
0168 for (; it_map2 != end_map2; ++it_map2) {
0169 SpeciesInfo& molInfo = fSpeciesInfoPerTime[it_map1->first][it_map2->first];
0170 molInfo.fNumber += it_map2->second.fNumber;
0171 molInfo.fG += it_map2->second.fG;
0172 molInfo.fG2 += it_map2->second.fG2;
0173 }
0174 }
0175 right->fSpeciesInfoPerTime.clear();
0176
0177 fNEvent += right->fNEvent;
0178 right->fNEvent = 0;
0179 right->fEdep = 0.;
0180 }
0181
0182
0183
0184 void ScoreSpecies::PrintAll()
0185 {
0186 G4cout << " MultiFunctionalDet " << detector->GetName() << G4endl;
0187 G4cout << " PrimitiveScorer " << GetName() << G4endl;
0188 G4cout << " Number of events " << fNEvent << G4endl;
0189 G4cout << " Number of energy deposition recorded " << fEvtMap->entries() << G4endl;
0190
0191 for (auto itr : *fEvtMap->GetMap()) {
0192 G4cout << " copy no.: " << itr.first << " energy deposit: " << *(itr.second) / GetUnitValue()
0193 << " [" << GetUnit() << "]" << G4endl;
0194 }
0195 }
0196
0197
0198
0199 void ScoreSpecies::ASCII()
0200 {
0201 std::ofstream out("Species.txt");
0202 if (!out) return;
0203
0204 out << "# Time [ps] G-value (/100 eV) RMS Molecule" << G4endl;
0205
0206 std::map<G4String, std::map<G4double, std::pair<G4double, G4double>>> mol;
0207
0208 for (auto& it_map1 : fSpeciesInfoPerTime) {
0209 InnerSpeciesMap& map2 = it_map1.second;
0210 G4double time = it_map1.first / ps;
0211 for (auto& it_map2 : map2) {
0212 G4double G = it_map2.second.fG;
0213 G4double G2 = it_map2.second.fG2;
0214 G4double N = fNEvent;
0215 G /= N;
0216 G2 = std::sqrt(N / (N - 1) * (G2 / N - G * G));
0217 mol[it_map2.first->GetName()][time] = std::make_pair(G, G2);
0218 }
0219 }
0220
0221 for (const auto& it1 : mol)
0222 for (auto it2 : it1.second)
0223 out << std::setw(12) << it2.first << std::setw(12) << it2.second.first << std::setw(12)
0224 << it2.second.second << std::setw(12) << std::setw(12) << it1.first << G4endl;
0225
0226 out.close();
0227 }
0228
0229
0230
0231 void ScoreSpecies::OutputAndClear()
0232 {
0233 if (G4Threading::IsWorkerThread()) return;
0234
0235
0236
0237 ASCII();
0238
0239 fNEvent = 0;
0240 fSpeciesInfoPerTime.clear();
0241 }