Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // ------------------------------------------------------------------- 28 // 29 // Geant4 source file 30 // 31 // File name: G4ParticleHPProbabilityTablesStore.cc 32 // 33 // Authors: Marek Zmeskal (CTU, Czech Technical University in Prague, Czech Republic) 34 // Loic Thulliez (CEA France) 35 // 36 // Creation date: 4 June 2024 37 // 38 // Description: Class to store all probability tables for 39 // different isotopes and in future also for 40 // different temperatures. 41 // 42 // Modifications: 43 // 44 // ------------------------------------------------------------------- 45 // 46 // 47 48 #include "G4ParticleHPProbabilityTablesStore.hh" 49 #include "G4SystemOfUnits.hh" 50 #include "G4ParticleHPVector.hh" 51 #include "G4ParticleHPManager.hh" 52 #include "G4HadronicParameters.hh" 53 #include "G4Material.hh" 54 #include "G4Element.hh" 55 #include "G4Isotope.hh" 56 #include "G4DynamicParticle.hh" 57 #include "G4Exception.hh" 58 #include "G4ParticleHPIsoProbabilityTable.hh" 59 #include "G4ParticleHPIsoProbabilityTable_NJOY.hh" 60 #include "G4ParticleHPIsoProbabilityTable_CALENDF.hh" 61 #include <string> 62 #include <sstream> 63 64 G4ParticleHPProbabilityTablesStore* G4ParticleHPProbabilityTablesStore::instance = nullptr; 65 66 ///-------------------------------------------------------------------------------------- 67 G4ParticleHPProbabilityTablesStore::G4ParticleHPProbabilityTablesStore() : 68 Temperatures(0), ProbabilityTables(0), URRlimits(0), usedNjoy(0), usedCalendf(0) { 69 if ( G4FindDataDir( "G4URRPTDATA" ) != nullptr ) { 70 dirName = G4FindDataDir( "G4URRPTDATA" ); 71 } else { 72 G4Exception( "G4ParticleHPProbabilityTablesStore::G4ParticleHPProbabilityTablesStore()", "hadhp01", 73 FatalException, "Please setenv G4URRPTDATA, it is not defined." ); 74 } 75 if ( G4HadronicParameters::Instance()->GetTypeTablePT() == "njoy" ) { 76 dirName += "/njoy/"; 77 usedNjoy = true; 78 } else if ( G4HadronicParameters::Instance()->GetTypeTablePT() == "calendf" ) { 79 dirName += "/calendf/"; 80 usedCalendf = true; 81 } else { 82 G4Exception( "G4ParticleHPProbabilityTablesStore::G4ParticleHPProbabilityTablesStore()", "hadhp01", 83 FatalException, "The format of probability tables is not set properly, " 84 "please set it with G4HadronicParameters::Instance()->SetTypeTablePT() before initialization in your main." ); 85 } 86 numIso = (G4int)G4Isotope::GetNumberOfIsotopes(); 87 // find all possible temperatures for all isotopes. 88 G4Material* theMaterial; 89 G4int Temp; 90 Temperatures = new std::vector< std::vector< G4int > >; 91 for ( G4int i = 0; i < numIso; ++i ) { 92 std::vector< G4int > isotemperatures; 93 std::map< std::thread::id, G4double > simpleMapE; 94 std::map< std::thread::id, G4double > simpleMapRN; 95 Temperatures->push_back( std::move(isotemperatures) ); 96 energy_cache.push_back( std::move(simpleMapE) ); 97 random_number_cache.push_back( std::move(simpleMapRN) ); 98 } 99 for ( std::size_t im = 0; im < G4Material::GetNumberOfMaterials(); ++im ) { 100 std::vector< G4bool > isoinmat( numIso, false ); 101 theMaterial = G4Material::GetMaterialTable()->at(im); 102 Temp = (G4int)theMaterial->GetTemperature(); 103 for ( G4int e = 0; e < (G4int)theMaterial->GetNumberOfElements(); ++e ) { 104 for ( G4int i = 0; i < (G4int)theMaterial->GetElement(e)->GetNumberOfIsotopes(); ++i ) { 105 std::size_t indexI = theMaterial->GetElement(e)->GetIsotope(i)->GetIndex(); 106 std::vector< G4int > isotemperatures = (*Temperatures)[indexI]; 107 if ( std::find( isotemperatures.begin(), isotemperatures.end(), Temp ) == isotemperatures.end() ) { 108 (*Temperatures)[indexI].push_back( Temp ); 109 isoinmat[indexI] = true; 110 } else { 111 if ( isoinmat[indexI] ) { 112 G4ExceptionDescription message; 113 message << "The isotope Z=" << theMaterial->GetElement(e)->GetIsotope(i)->GetZ() 114 << " and A=" << theMaterial->GetElement(e)->GetIsotope(i)->GetN() 115 << " is more times in material " << theMaterial->GetName() << ".\n" 116 << "This may cause bias in selection of target isotopes, if there are elements with different URR limits in the material.\n" 117 << "Please make materials only with elements with different Z."; 118 G4Exception( "G4ParticleHPProbabilityTablesStore::InitURRlimits()", "hadhp01", JustWarning, message ); 119 } 120 } 121 } // end of cycle over isotopes 122 } // end of cycle over elements 123 } // end of cycle over materials 124 } 125 126 ///-------------------------------------------------------------------------------------- 127 G4ParticleHPProbabilityTablesStore::~G4ParticleHPProbabilityTablesStore() { 128 for ( G4int i = 0; i < numIso; i++ ) { 129 for ( std::map< G4int, G4ParticleHPIsoProbabilityTable* >::iterator it = (*ProbabilityTables)[i].begin(); 130 it != (*ProbabilityTables)[i].end(); ++it ) { 131 delete it->second; 132 } 133 } 134 delete ProbabilityTables; 135 delete URRlimits; 136 delete Temperatures; 137 } 138 139 ///-------------------------------------------------------------------------------------- 140 G4ParticleHPProbabilityTablesStore* G4ParticleHPProbabilityTablesStore::GetInstance() { 141 if ( instance == nullptr ) instance = new G4ParticleHPProbabilityTablesStore; 142 return instance; 143 } 144 145 ///-------------------------------------------------------------------------------------- 146 G4double G4ParticleHPProbabilityTablesStore::GetIsoCrossSectionPT( const G4DynamicParticle* dp, G4int MTnumber, 147 const G4Isotope* iso, const G4Element* ele, const G4Material* mat ) { 148 G4double kineticEnergy = dp->GetKineticEnergy(); 149 std::size_t indexI = iso->GetIndex(); 150 G4int T = (G4int)( mat->GetTemperature() ); 151 std::thread::id id = std::this_thread::get_id(); 152 if ( energy_cache[indexI][id] == kineticEnergy ) { 153 return (*ProbabilityTables)[indexI][T]->GetCorrelatedIsoCrossSectionPT( dp, MTnumber, ele, kineticEnergy, random_number_cache[indexI][id], id ); 154 } else { 155 energy_cache[indexI][id] = kineticEnergy; 156 return (*ProbabilityTables)[iso->GetIndex()][T]->GetIsoCrossSectionPT( dp, MTnumber, ele, kineticEnergy, random_number_cache[indexI], id ); 157 } 158 } 159 160 ///-------------------------------------------------------------------------------------- 161 void G4ParticleHPProbabilityTablesStore::Init() { 162 ProbabilityTables = new std::vector< std::map< G4int, G4ParticleHPIsoProbabilityTable* > >; 163 for ( G4int i = 0; i < numIso; i++ ) { 164 G4int Z = (*(G4Isotope::GetIsotopeTable()))[i]->GetZ(); 165 G4int A = (*(G4Isotope::GetIsotopeTable()))[i]->GetN(); 166 G4int meso = (*(G4Isotope::GetIsotopeTable()))[i]->Getm(); 167 std::map< G4int, G4ParticleHPIsoProbabilityTable* > tempPTmap; 168 for ( G4int T : (*Temperatures)[i] ) { // create probability table for each temperature and isotope 169 if ( usedNjoy ) { 170 tempPTmap.insert( { T, new G4ParticleHPIsoProbabilityTable_NJOY } ); 171 } else if ( usedCalendf ) { 172 tempPTmap.insert( { T, new G4ParticleHPIsoProbabilityTable_CALENDF } ); 173 } 174 tempPTmap[T]->Init( Z, A, meso, T, dirName ); 175 } 176 ProbabilityTables->push_back( std::move(tempPTmap) ); 177 } 178 } 179 180 ///-------------------------------------------------------------------------------------- 181 void G4ParticleHPProbabilityTablesStore::InitURRlimits() { 182 URRlimits = new std::vector< std::pair< G4double, G4double > >; 183 // Find energy limits of the URR for each element. 184 std::vector< G4bool > wasnotprintedyet( numIso, true ); 185 for ( std::size_t i = 0; i < G4Element::GetNumberOfElements(); ++i ) { 186 G4double minE = DBL_MAX; 187 G4double maxE = 0.0; 188 for ( G4int ii = 0; ii < (G4int)(*(G4Element::GetElementTable()))[i]->GetNumberOfIsotopes(); ++ii ) { 189 G4int Z = (*(G4Element::GetElementTable()))[i]->GetIsotope(ii)->GetZ(); 190 G4int A = (*(G4Element::GetElementTable()))[i]->GetIsotope(ii)->GetN(); 191 G4int meso = (*(G4Element::GetElementTable()))[i]->GetIsotope(ii)->Getm(); 192 std::size_t indexI = (*(G4Element::GetElementTable()))[i]->GetIsotope(ii)->GetIndex(); 193 filename = std::to_string(Z) + "_" + std::to_string(A); 194 if ( meso != 0 ) filename += "_m" + std::to_string(meso); 195 G4double emin = DBL_MAX; 196 G4double emax = 0.0; 197 G4double emin2 = DBL_MAX; 198 G4double emax2 = 0.0; 199 G4bool hasalreadyPT = false; 200 G4bool doesnothavePTyet = false; 201 for ( G4int T : (*Temperatures)[indexI] ) { 202 G4String fullPathFileName = dirName + filename + "." + std::to_string(T) + ".pt"; 203 std::istringstream theData( std::ios::in ); 204 G4ParticleHPManager::GetInstance()->GetDataStream( fullPathFileName, theData ); 205 if ( theData.good() && hasalreadyPT ) { 206 theData >> emin2 >> emax2; 207 if ( emin2 != emin || emax2 != emax ) { 208 G4ExceptionDescription message; 209 message << "There is mismatch between limits of unresolved resonance region for isotope " << "\n" 210 << "with Z=" << Z << " and A=" << A << " for different temperatures, which should not happen, CHECK YOUR DATA!" << "\n" 211 << "The broadest limits will be used."; 212 G4Exception( "G4ParticleHPProbabilityTablesStore::InitURRlimits()", "hadhp01", JustWarning, message ); 213 G4cout << "Temperature T= " << T << " emin=" << emin << " emax=" << emax << " minE=" << minE << " maxE=" << maxE << G4endl; 214 if ( emin < minE ) minE = emin; 215 if ( emax > maxE ) maxE = emax; 216 } 217 } else if ( theData.good() ) { 218 theData >> emin >> emax; 219 if ( emin < minE ) minE = emin; 220 if ( emax > maxE ) maxE = emax; 221 hasalreadyPT = true; 222 if ( doesnothavePTyet && wasnotprintedyet[indexI] ) { 223 G4ExceptionDescription message; 224 message << "There are probability tables only for some of the used temperatures for isotope with Z=" << Z << " and A=" << A << ".\n" 225 << "Smooth cross section will be used for other temperature(s) of this isotope, which may cause severe differences in simulation."; 226 G4Exception( "G4ParticleHPProbabilityTablesStore::InitURRlimits()", "hadhp01", JustWarning, message ); 227 wasnotprintedyet[indexI] = false; 228 } 229 } else if ( hasalreadyPT && wasnotprintedyet[indexI] ) { 230 G4ExceptionDescription message; 231 message << "There are probability tables only for some of the used temperatures for isotope with Z=" << Z << " and A=" << A << ".\n" 232 << "Smooth cross section will be used for other temperature(s) of this isotope, which may cause severe differences in simulation."; 233 G4Exception( "G4ParticleHPProbabilityTablesStore::InitURRlimits()", "hadhp01", JustWarning, message ); 234 wasnotprintedyet[indexI] = false; 235 } else { 236 doesnothavePTyet = true; 237 } 238 } 239 } 240 std::pair< G4double, G4double > simplepair( minE * eV, maxE * eV ); 241 URRlimits->push_back( simplepair ); 242 } 243 // Find absolute energy limits of the URR and set them at the end of URRlimits. 244 G4double absminE = (*URRlimits)[0].first; 245 G4double absmaxE = (*URRlimits)[0].second; 246 for ( auto iterator : (*URRlimits) ) { 247 if ( iterator.first < absminE ) absminE = iterator.first; 248 if ( iterator.second > absmaxE ) absmaxE = iterator.second; 249 } 250 std::pair< G4double, G4double > minmaxpair( absminE, absmaxE ); 251 URRlimits->push_back( minmaxpair ); 252 } 253