File indexing completed on 2026-09-15 08:28:44
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
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 #include "XSHistoManager.hh"
0050
0051 #include "G4Element.hh"
0052 #include "G4HadronicProcessStore.hh"
0053 #include "G4Material.hh"
0054 #include "G4NistManager.hh"
0055 #include "G4ParticleDefinition.hh"
0056 #include "G4ParticleTable.hh"
0057 #include "G4ios.hh"
0058
0059
0060 #include "tools_histo_flair.hh"
0061
0062 #include "G4RootAnalysisManager.hh"
0063
0064
0065
0066 XSHistoManager::XSHistoManager()
0067 : fMessenger(new XSHistoManagerMessenger(this)),
0068 fOutputFileName("all_XS"),
0069 fRootOutputFileName("all_XS.root"),
0070 fFlairOutputFileName("all_XS.hist"),
0071 fParticle(nullptr),
0072 fElement(nullptr),
0073 fMaterial(nullptr),
0074 fNumBins(10000),
0075 fMinKineticEnergy(1. * keV),
0076 fMaxKineticEnergy(10. * TeV),
0077 fFunctionName("none"),
0078 fBinSchemeName("log"),
0079 fRootEnergyUnit("MeV"),
0080 fAnalysisManager(G4RootAnalysisManager::Instance()),
0081 fElasticXSIndex(0),
0082 fInelasticXSIndex(1),
0083 fCaptureXSIndex(2),
0084 fFissionXSIndex(3),
0085 fChargeExchangeXSIndex(4),
0086 fTotalXSIndex(5),
0087 fElasticPerVolumeXSIndex(6),
0088 fInelasticPerVolumeXSIndex(7)
0089 {
0090
0091 }
0092
0093
0094
0095
0096 void XSHistoManager::SetOutputFileName(const G4String& outputFileName)
0097 {
0098 fOutputFileName = outputFileName;
0099 fRootOutputFileName = outputFileName + ".root";
0100 fFlairOutputFileName = outputFileName + ".hist";
0101 }
0102
0103
0104
0105
0106 void XSHistoManager::SetParticle(const G4String& particleName)
0107 {
0108 fParticle = G4ParticleTable::GetParticleTable()->FindParticle(particleName);
0109 }
0110
0111
0112
0113
0114 void XSHistoManager::SetElement(const G4String& elementName)
0115 {
0116 fElement = G4NistManager::Instance()->FindOrBuildElement(elementName);
0117
0118 SetMaterial(elementName);
0119 }
0120
0121
0122
0123
0124 void XSHistoManager::SetMaterial(const G4String& materialName)
0125 {
0126
0127 if (fMaterial) {
0128 G4ExceptionDescription msg;
0129 msg << "Please use UI command /allXS/elementName"
0130 << " OR UI command /allXS/nonElementaryMaterialName,"
0131 << " BUT NOT BOTH!" << G4endl;
0132 G4Exception("XSHistoManager::SetMaterial", "A target material is already defined.",
0133 FatalException, msg);
0134 }
0135
0136 fMaterial = G4NistManager::Instance()->FindOrBuildMaterial("G4_" + materialName);
0137 }
0138
0139
0140
0141
0142
0143 void XSHistoManager::Book()
0144 {
0145
0146 CheckInput();
0147
0148
0149 if (!fAnalysisManager->OpenFile(fRootOutputFileName)) {
0150 G4ExceptionDescription msg;
0151 msg << "Booking profiles: cannot open file " << fRootOutputFileName << G4endl;
0152 G4Exception("XSHistoManager::Book", "Cannot open file", FatalException, msg);
0153 }
0154 G4cout << "### XSHistoManager::Book: Successfully opened file " << fRootOutputFileName
0155 << " for dumping profiles." << G4endl;
0156
0157
0158 const G4int elasticXSProfileIndex =
0159 fAnalysisManager->CreateH1("ElasticXS", "Elastic XS", fNumBins, fMinKineticEnergy,
0160 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0161 fXSProfileIndex.insert(std::make_pair(fElasticXSIndex, elasticXSProfileIndex));
0162
0163 const G4int inelasticXSProfileIndex =
0164 fAnalysisManager->CreateH1("InelasticXS", "Inelastic XS", fNumBins, fMinKineticEnergy,
0165 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0166 fXSProfileIndex.insert(std::make_pair(fInelasticXSIndex, inelasticXSProfileIndex));
0167
0168 const G4int captureXSProfileIndex =
0169 fAnalysisManager->CreateH1("CaptureXS", "Capture XS", fNumBins, fMinKineticEnergy,
0170 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0171 fXSProfileIndex.insert(std::make_pair(fCaptureXSIndex, captureXSProfileIndex));
0172
0173 const G4int fissionXSProfileIndex =
0174 fAnalysisManager->CreateH1("FissionXS", "Fission XS", fNumBins, fMinKineticEnergy,
0175 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0176 fXSProfileIndex.insert(std::make_pair(fFissionXSIndex, fissionXSProfileIndex));
0177
0178 const G4int chargeExchangeXSProfileIndex = fAnalysisManager->CreateH1(
0179 "ChargeExchangeXS", "Charge exchange XS", fNumBins, fMinKineticEnergy, fMaxKineticEnergy,
0180 fRootEnergyUnit, fFunctionName, fBinSchemeName);
0181 fXSProfileIndex.insert(std::make_pair(fChargeExchangeXSIndex, chargeExchangeXSProfileIndex));
0182
0183 const G4int totalXSProfileIndex =
0184 fAnalysisManager->CreateH1("TotalXS", "Total XS", fNumBins, fMinKineticEnergy,
0185 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0186 fXSProfileIndex.insert(std::make_pair(fTotalXSIndex, totalXSProfileIndex));
0187
0188 const G4int elasticPerVolumeXSProfileIndex = fAnalysisManager->CreateH1(
0189 "ElasticPerVolumeXS", "Elastic XS per volume", fNumBins, fMinKineticEnergy, fMaxKineticEnergy,
0190 fRootEnergyUnit, fFunctionName, fBinSchemeName);
0191 fXSProfileIndex.insert(std::make_pair(fElasticPerVolumeXSIndex, elasticPerVolumeXSProfileIndex));
0192
0193 const G4int inelasticPerVolumeXSProfileIndex = fAnalysisManager->CreateH1(
0194 "InelasticPerVolumeXS", "Inelastic XS per volume", fNumBins, fMinKineticEnergy,
0195 fMaxKineticEnergy, fRootEnergyUnit, fFunctionName, fBinSchemeName);
0196 fXSProfileIndex.insert(
0197 std::make_pair(fInelasticPerVolumeXSIndex, inelasticPerVolumeXSProfileIndex));
0198 }
0199
0200
0201
0202
0203 void XSHistoManager::EndOfRun()
0204 {
0205 G4cout << "### XSHistoManager::EndOfRun: Compute & fill XS for " << fParticle->GetParticleName()
0206 << " in " << (fElement ? fElement->GetName() : fMaterial->GetName()) << G4endl;
0207
0208 G4HadronicProcessStore* const store = G4HadronicProcessStore::Instance();
0209
0210
0211 const G4double logMinKineticEnergy = std::log10(fMinKineticEnergy);
0212 const G4double logMaxKineticEnergy = std::log10(fMaxKineticEnergy);
0213 const G4double deltaLogKineticEnergy = (logMaxKineticEnergy - logMinKineticEnergy) / fNumBins;
0214
0215 G4double logKineticEnergy = logMinKineticEnergy - deltaLogKineticEnergy / 2.;
0216
0217
0218 for (G4int binIndex = 0; binIndex < fNumBins; ++binIndex) {
0219 logKineticEnergy += deltaLogKineticEnergy;
0220 const G4double kineticEnergy = std::pow(10., logKineticEnergy) * MeV;
0221
0222 G4double totalXS = 0.;
0223 if (fElement) {
0224
0225 const G4double elasticXS =
0226 store->GetElasticCrossSectionPerAtom(fParticle, kineticEnergy, fElement, fMaterial);
0227 fAnalysisManager->FillH1(fXSProfileIndex[fElasticXSIndex], kineticEnergy, elasticXS / barn);
0228 totalXS += elasticXS;
0229
0230
0231 const G4double inelasticXS =
0232 store->GetInelasticCrossSectionPerAtom(fParticle, kineticEnergy, fElement, fMaterial);
0233 fAnalysisManager->FillH1(fXSProfileIndex[fInelasticXSIndex], kineticEnergy,
0234 inelasticXS / barn);
0235 totalXS += inelasticXS;
0236
0237 if (fParticle == G4Neutron::Definition()) {
0238
0239 const G4double captureXS =
0240 store->GetCaptureCrossSectionPerAtom(fParticle, kineticEnergy, fElement, fMaterial);
0241 fAnalysisManager->FillH1(fXSProfileIndex[fCaptureXSIndex], kineticEnergy, captureXS / barn);
0242 totalXS += captureXS;
0243
0244
0245 const G4double fissionXS =
0246 store->GetFissionCrossSectionPerAtom(fParticle, kineticEnergy, fElement, fMaterial);
0247 totalXS += fissionXS;
0248 fAnalysisManager->FillH1(fXSProfileIndex[fFissionXSIndex], kineticEnergy, fissionXS / barn);
0249 }
0250
0251
0252 const G4double chargeExchangeXS =
0253 store->GetChargeExchangeCrossSectionPerAtom(fParticle, kineticEnergy, fElement, fMaterial);
0254 fAnalysisManager->FillH1(fXSProfileIndex[fChargeExchangeXSIndex], kineticEnergy,
0255 chargeExchangeXS / barn);
0256 totalXS += chargeExchangeXS;
0257
0258
0259 fAnalysisManager->FillH1(fXSProfileIndex[fTotalXSIndex], kineticEnergy, totalXS / barn);
0260 }
0261
0262 if (fMaterial) {
0263 const G4double materialSurfacicDensity =
0264 (fMaterial ? fMaterial->GetDensity() / (g / cm2) : 1.);
0265
0266
0267 const G4double elasticPerVolumeXS =
0268 store->GetElasticCrossSectionPerVolume(fParticle, kineticEnergy, fMaterial);
0269 fAnalysisManager->FillH1(fXSProfileIndex[fElasticPerVolumeXSIndex], kineticEnergy,
0270 elasticPerVolumeXS / materialSurfacicDensity);
0271
0272
0273 const G4double inelasticPerVolumeXS =
0274 store->GetInelasticCrossSectionPerVolume(fParticle, kineticEnergy, fMaterial);
0275 fAnalysisManager->FillH1(fXSProfileIndex[fInelasticPerVolumeXSIndex], kineticEnergy,
0276 inelasticPerVolumeXS / materialSurfacicDensity);
0277 }
0278 }
0279
0280
0281 DumpAllG4H1IntoRootFile();
0282
0283
0284 DumpAllG4H1IntoFlairFile();
0285
0286
0287 fAnalysisManager->CloseFile();
0288 fAnalysisManager->Clear();
0289 }
0290
0291
0292
0293
0294
0295 void XSHistoManager::CheckInput()
0296 {
0297 if (!fParticle) {
0298 G4ExceptionDescription msg;
0299 msg << "Please add a particle to study XS: UI command /allXS/particleName" << G4endl;
0300 G4Exception("XSHistoManager::CheckInput()", "Print XS: no input particle defined.",
0301 FatalException, msg);
0302 }
0303
0304 if (!fMaterial) {
0305 G4ExceptionDescription msg;
0306 msg << "Please add a material to study XS:"
0307 << " UI command /allXS/elementName for an elementary material,"
0308 << " or UI command /allXS/nonElementaryMaterialName for a compound/mixture material."
0309 << G4endl;
0310 G4Exception("XSHistoManager::CheckInput()", "Print XS: no target material defined.",
0311 FatalException, msg);
0312 }
0313 }
0314
0315
0316
0317
0318 void XSHistoManager::DumpAllG4H1IntoRootFile() const
0319 {
0320 if (!fAnalysisManager->Write()) {
0321 G4ExceptionDescription message;
0322 message << "Could not write ROOT file.";
0323 G4Exception("XSHistoManager::EndOfRun()", "I/O Error", FatalException, message);
0324 }
0325 G4cout << "### All profiles saved to " << fRootOutputFileName << G4endl;
0326 }
0327
0328
0329
0330
0331 void XSHistoManager::DumpAllG4H1IntoFlairFile() const
0332 {
0333 std::ofstream output;
0334 output.open(fFlairOutputFileName, std::ios_base::out);
0335 auto const rootAnalysisManager = dynamic_cast<G4RootAnalysisManager*>(fAnalysisManager);
0336
0337 G4int indexInOutputFile = 1;
0338 for (G4int xsIndex = fElasticXSIndex; xsIndex <= fInelasticPerVolumeXSIndex; ++xsIndex) {
0339 const G4int histoIndex = fXSProfileIndex.at(xsIndex);
0340 const G4String& histoName = fAnalysisManager->GetH1Name(histoIndex);
0341 const auto& histo = rootAnalysisManager->GetH1(histoIndex);
0342
0343 tools::histo::flair::dumpG4H1ProfileInFlairFormat(output, indexInOutputFile, histoName, histo,
0344 tools::histo::flair::Abscissa::KineticEnergy,
0345 fBinSchemeName);
0346 ++indexInOutputFile;
0347 }
0348 output.close();
0349 G4cout << "### All profiles saved to " << fFlairOutputFileName << G4endl;
0350 }
0351
0352