Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4NuclideTable class implementation << 26 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> 27 // >> 28 // MODULE: G4NuclideTable.cc >> 29 // >> 30 // Date: 10/10/13 >> 31 // Author: T.Koi >> 32 // >> 33 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> 34 // >> 35 // HISTORY >> 36 // Based on G4IsomerTable >> 37 //////////////////////////////////////////////////////////////////////////////// 27 // 38 // 28 // Author: T.Koi, SLAC - 10 October 2013 << 29 // ------------------------------------------- << 30 << 31 #include "G4NuclideTable.hh" 39 #include "G4NuclideTable.hh" 32 40 33 #include "G4NuclideTableMessenger.hh" << 34 #include "G4PhysicalConstants.hh" << 35 #include "G4String.hh" << 36 #include "G4SystemOfUnits.hh" << 37 #include "G4ios.hh" 41 #include "G4ios.hh" 38 #include "globals.hh" 42 #include "globals.hh" 39 << 43 #include "G4PhysicalConstants.hh" 40 #include <fstream> << 44 #include "G4SystemOfUnits.hh" 41 #include <iomanip> 45 #include <iomanip> >> 46 #include <fstream> 42 #include <sstream> 47 #include <sstream> 43 48 44 G4NuclideTable* G4NuclideTable::GetInstance() << 49 const G4double G4NuclideTable::levelTolerance = 1.0*eV; 45 { << 50 // const G4double G4NuclideTable::levelTolerance = 1.0e-3*eV; 46 static G4NuclideTable instance; << 51 // torelance for excitation energy 47 return &instance; << 52 48 } << 53 49 << 54 /////////////////////////////////////////////////////////////////////////////// 50 G4NuclideTable* G4NuclideTable::GetNuclideTabl << 55 G4NuclideTable* G4NuclideTable::GetInstance() { 51 { << 56 static G4NuclideTable instance; 52 return GetInstance(); << 57 return &instance; 53 } 58 } 54 59 >> 60 /////////////////////////////////////////////////////////////////////////////// 55 G4NuclideTable::G4NuclideTable() 61 G4NuclideTable::G4NuclideTable() 56 : G4VIsotopeTable("Isomer"), mean_life_thres << 62 :G4VIsotopeTable("Isomer"), >> 63 threshold_of_half_life(1000.0*ns), >> 64 fUserDefinedList(NULL), >> 65 fIsotopeList(0) 57 { 66 { 58 fMessenger = new G4NuclideTableMessenger(thi << 67 //SetVerboseLevel(G4ParticleTable::GetParticleTable()->GetVerboseLevel()); 59 fIsotopeList = new G4IsotopeList(); << 68 FillHardCodeList(); 60 GenerateNuclide(); << 61 } 69 } 62 70 >> 71 /////////////////////////////////////////////////////////////////////////////// 63 G4NuclideTable::~G4NuclideTable() 72 G4NuclideTable::~G4NuclideTable() 64 { 73 { 65 for (auto& it : map_pre_load_list) { << 74 if (fIsotopeList!=0) { 66 it.second.clear(); << 75 for (size_t i = 0 ; i<fIsotopeList->size(); i++) { >> 76 delete (*fIsotopeList)[i]; >> 77 } >> 78 fIsotopeList->clear(); >> 79 delete fIsotopeList; >> 80 fIsotopeList = 0; 67 } 81 } 68 map_pre_load_list.clear(); << 69 82 70 for (auto& it : map_full_list) { << 83 for ( std::map< G4int , std::multimap< G4double , G4IsotopeProperty* > >::iterator 71 it.second.clear(); << 84 it = map_pre_load_list.begin(); it != map_pre_load_list.end(); it++ ) { >> 85 it->second.clear(); 72 } 86 } 73 map_full_list.clear(); << 87 map_pre_load_list.clear(); 74 88 75 if (fIsotopeList != nullptr) { << 89 for ( std::map< G4int , std::multimap< G4double , G4IsotopeProperty* > >::iterator 76 for (const auto& i : *fIsotopeList) { << 90 it = map_hard_code_list.begin(); it != map_hard_code_list.end(); it++ ) { 77 delete i; << 91 for ( std::multimap< G4double , G4IsotopeProperty* >::iterator 78 } << 92 itt = it->second.begin(); itt != it->second.end(); itt++ ) { 79 fIsotopeList->clear(); << 93 delete itt->second; 80 delete fIsotopeList; << 94 } 81 fIsotopeList = nullptr; << 95 it->second.clear(); >> 96 } >> 97 map_hard_code_list.clear(); >> 98 >> 99 for ( std::map< G4int , std::multimap< G4double , G4IsotopeProperty* > >::iterator >> 100 it = map_full_list.begin(); it != map_full_list.end(); it++ ) { >> 101 for ( std::multimap< G4double , G4IsotopeProperty* >::iterator >> 102 itt = it->second.begin(); itt != it->second.end(); itt++ ) { >> 103 delete itt->second; >> 104 } >> 105 it->second.clear(); 82 } 106 } 83 delete fMessenger; << 107 map_full_list.clear(); 84 } 108 } 85 109 86 G4IsotopeProperty* G4NuclideTable::GetIsotope( << 110 /////////////////////////////////////////////////////////////////////////////// 87 << 111 // >> 112 G4IsotopeProperty* G4NuclideTable::GetIsotope(G4int Z, G4int A, G4double E) 88 { 113 { 89 G4IsotopeProperty* fProperty = nullptr; << 90 114 91 // At first searching UserDefined << 115 G4IsotopeProperty* fProperty = 0; 92 if (fUserDefinedList != nullptr) { << 116 G4int ionCode = 1000*Z + A; 93 for (const auto it : *fUserDefinedList) { << 117 94 if (Z == it->GetAtomicNumber() && A == i << 118 //Serching pre-load 95 G4double levelE = it->GetEnergy(); << 119 //Note: isomer level is properly set only for pre_load_list. 96 if (levelE - flevelTolerance / 2 <= E << 120 if ( map_pre_load_list.find( ionCode ) != map_pre_load_list.end() ) { 97 if (flb == it->GetFloatLevelBase()) << 121 98 return it; << 122 std::multimap< G4double , G4IsotopeProperty* >::iterator lower_bound_itr = 99 } // found << 123 map_pre_load_list.find( ionCode ) -> second.lower_bound ( E - levelTolerance/2 ); 100 } << 124 >> 125 //std::multimap< G4double , G4IsotopeProperty* >::iterator upper_bound_itr = >> 126 //map_pre_load_list.find( ionCode ) -> second.upper_bound ( E ); >> 127 >> 128 G4double levelE = DBL_MAX; >> 129 if ( lower_bound_itr != map_pre_load_list.find( ionCode ) -> second.end() ) { >> 130 levelE = lower_bound_itr->first; >> 131 if ( levelE - levelTolerance/2 <= E && E < levelE + levelTolerance/2 ) { >> 132 return lower_bound_itr->second; // found >> 133 } >> 134 } >> 135 } >> 136 >> 137 //Searching hard-code >> 138 if ( map_hard_code_list.find( ionCode ) != map_hard_code_list.end() ) { >> 139 std::multimap< G4double , G4IsotopeProperty* >::iterator lower_bound_itr = >> 140 map_hard_code_list.find( ionCode ) -> second.lower_bound ( E - levelTolerance/2 ); >> 141 >> 142 //std::multimap< G4double , G4IsotopeProperty* >::iterator upper_bound_itr = >> 143 //map_pre_load_list.find( ionCode ) -> second.upper_bound ( E ); >> 144 >> 145 G4double levelE = DBL_MAX; >> 146 if ( lower_bound_itr != map_hard_code_list.find( ionCode ) -> second.end() ) { >> 147 levelE = lower_bound_itr->first; >> 148 if ( levelE - levelTolerance/2 <= E && E < levelE + levelTolerance/2 ) { >> 149 return lower_bound_itr->second; // found >> 150 } 101 } 151 } 102 } << 152 } 103 } << 153 >> 154 //Searching big-list >> 155 char* path = getenv("G4ENSDFSTATEDATA"); >> 156 >> 157 if ( !path ) { >> 158 return fProperty; // not found; >> 159 } >> 160 >> 161 if ( map_full_list.find( ionCode ) == map_full_list.end() ) { >> 162 >> 163 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 164 map_full_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); 104 165 105 // Searching pre-load << 166 std::fstream ifs; 106 // Note: isomer level is properly set only f << 167 G4String filename(path); 107 // << 168 filename += "/ENSDFSTATE.dat"; 108 G4int ionCode = 1000 * Z + A; << 169 ifs.open( filename.c_str() ); 109 auto itf = map_pre_load_list.find(ionCode); << 170 110 << 171 G4bool reading_target = false; 111 if (itf != map_pre_load_list.cend()) { << 172 112 auto lower_bound_itr = itf->second.lower_b << 173 G4int ionZ; 113 G4double levelE = DBL_MAX; << 174 G4int ionA; 114 << 175 G4double ionE; 115 while (lower_bound_itr != itf->second.cend << 176 G4double ionLife; 116 levelE = lower_bound_itr->first; << 177 G4int ionJ; 117 if (levelE - flevelTolerance / 2 <= E && << 178 G4double ionMu; 118 if (flb == (lower_bound_itr->second)-> << 179 119 return lower_bound_itr->second; // << 180 ifs >> ionZ >> ionA >> ionE >> ionLife >> ionJ >> ionMu; 120 } << 181 >> 182 while ( ifs.good() ) { >> 183 >> 184 if ( ionZ == Z && ionA == A ) { >> 185 >> 186 reading_target = true; >> 187 >> 188 ionE *= keV; >> 189 ionLife *= ns; >> 190 ionMu *= (joule/tesla); >> 191 >> 192 G4IsotopeProperty* property = new G4IsotopeProperty(); >> 193 >> 194 G4int iLevel=9; >> 195 property->SetAtomicNumber(ionZ); >> 196 property->SetAtomicMass(ionA); >> 197 property->SetIsomerLevel(iLevel); >> 198 property->SetEnergy(ionE); >> 199 property->SetiSpin(ionJ); >> 200 property->SetLifeTime(ionLife); >> 201 property->SetMagneticMoment(ionMu); >> 202 >> 203 map_full_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , property ) ); >> 204 >> 205 } else if ( reading_target == true ) { >> 206 ifs.close(); >> 207 break; >> 208 } >> 209 >> 210 ifs >> ionZ >> ionA >> ionE >> ionLife >> ionJ >> ionMu; 121 } 211 } 122 else { << 212 123 break; << 213 ifs.close(); >> 214 } >> 215 >> 216 >> 217 if ( map_full_list.find( ionCode ) != map_full_list.end() ) { >> 218 >> 219 std::multimap< G4double , G4IsotopeProperty* >::iterator lower_bound_itr = >> 220 map_full_list.find( ionCode ) -> second.lower_bound ( E - levelTolerance/2 ); >> 221 >> 222 //std::multimap< G4double , G4IsotopeProperty* >::iterator upper_bound_itr = >> 223 //map_full_list.find( ionCode ) -> second.upper_bound ( E - levelTolerance/2 ); >> 224 >> 225 G4double levelE = DBL_MAX; >> 226 if ( lower_bound_itr != map_full_list.find( ionCode ) -> second.end() ) { >> 227 levelE = lower_bound_itr->first; >> 228 if ( levelE - levelTolerance/2 < E && E < levelE + levelTolerance/2 ) { >> 229 return lower_bound_itr->second; // found >> 230 } 124 } 231 } 125 ++lower_bound_itr; << 232 } 126 } << 127 } << 128 233 129 return fProperty; // not found << 234 return fProperty; // not found; 130 } 235 } 131 236 132 G4double G4NuclideTable::GetTruncationError(G4 << 237 /////////////////////////////////////////////////////////////////////// >> 238 G4IsotopeProperty* >> 239 G4NuclideTable::GetIsotopeByIsoLvl(G4int Z, G4int A, G4int lvl) 133 { 240 { 134 G4double tolerance = G4NuclideTable::GetInst << 241 if(lvl==0) return GetIsotope(Z,A,0.0); 135 return eex - (G4long)(eex / tolerance) * tol << 242 return (G4IsotopeProperty*)0; 136 } 243 } 137 244 138 G4double G4NuclideTable::Round(G4double eex) << 245 /////////////////////////////////////////////////////////////////////////////// >> 246 void G4NuclideTable::FillHardCodeList() 139 { 247 { 140 G4double tolerance = G4NuclideTable::GetInst << 248 for (size_t i=0; i<nEntries_ground_state; i++) { 141 return round(eex / tolerance) * tolerance; << 142 } << 143 249 144 G4long G4NuclideTable::Truncate(G4double eex) << 250 G4int ionZ = (G4int)groundStateTable[i][idxZ]; 145 { << 251 G4int ionA = (G4int)groundStateTable[i][idxA]; 146 G4double tolerance = G4NuclideTable::GetInst << 252 G4int lvl = 0; // ground state 147 return (G4long)(eex / tolerance); << 253 G4double ionE = groundStateTable[i][idxEnergy]*keV; 148 } << 254 G4double ionLife = groundStateTable[i][idxLife]*ns; >> 255 G4int ionJ = (G4int)(groundStateTable[i][idxSpin]); >> 256 G4double ionMu = groundStateTable[i][idxMu]*(joule/tesla); 149 257 150 G4double G4NuclideTable::Tolerance() << 258 G4int ionCode = 1000*ionZ + ionA; 151 { << 152 return G4NuclideTable::GetInstance()->GetLev << 153 } << 154 259 155 G4IsotopeProperty* G4NuclideTable::GetIsotopeB << 260 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); 156 { << 261 157 if (lvl == 0) return GetIsotope(Z, A, 0.0); << 262 // Set Isotope Property 158 return nullptr; << 263 fProperty->SetAtomicNumber(ionZ); >> 264 fProperty->SetAtomicMass(ionA); >> 265 fProperty->SetIsomerLevel(lvl); >> 266 fProperty->SetEnergy(ionE); >> 267 fProperty->SetiSpin(ionJ); >> 268 fProperty->SetLifeTime(ionLife); >> 269 fProperty->SetDecayTable(0); >> 270 fProperty->SetMagneticMoment(ionMu); >> 271 >> 272 if ( map_hard_code_list.find ( ionCode ) == map_hard_code_list.end() ) { >> 273 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 274 map_hard_code_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); >> 275 } >> 276 map_hard_code_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , fProperty ) ); >> 277 >> 278 } >> 279 >> 280 for (size_t i=0; i<nEntries_excite_state; i++) { >> 281 >> 282 G4int ionZ = (G4int)exciteStateTable[i][idxZ]; >> 283 G4int ionA = (G4int)exciteStateTable[i][idxA]; >> 284 G4double ionE = exciteStateTable[i][idxEnergy]*keV; >> 285 G4double ionLife = exciteStateTable[i][idxLife]*ns; >> 286 G4int ionJ = (G4int)(exciteStateTable[i][idxSpin]); >> 287 G4double ionMu = exciteStateTable[i][idxMu]*(joule/tesla); >> 288 >> 289 G4int ionCode = 1000*ionZ + ionA; >> 290 >> 291 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); >> 292 >> 293 // Set Isotope Property >> 294 fProperty->SetAtomicNumber(ionZ); >> 295 fProperty->SetAtomicMass(ionA); >> 296 fProperty->SetIsomerLevel(9); >> 297 fProperty->SetEnergy(ionE); >> 298 fProperty->SetiSpin(ionJ); >> 299 fProperty->SetLifeTime(ionLife); >> 300 fProperty->SetDecayTable(0); >> 301 fProperty->SetMagneticMoment(ionMu); >> 302 >> 303 if ( map_hard_code_list.find ( ionCode ) == map_hard_code_list.end() ) { >> 304 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 305 map_hard_code_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); >> 306 } >> 307 map_hard_code_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , fProperty ) ); >> 308 >> 309 } 159 } 310 } 160 311 >> 312 /////////////////////////////////////////////////////////////////////////////// 161 void G4NuclideTable::GenerateNuclide() 313 void G4NuclideTable::GenerateNuclide() 162 { 314 { 163 if (mean_life_threshold < minimum_mean_life_ << 164 // Need to update full list << 165 const char* path = G4FindDataDir("G4ENSDFS << 166 << 167 if (path == nullptr) { << 168 G4Exception("G4NuclideTable", "PART70000 << 169 "G4ENSDFSTATEDATA environmen << 170 return; << 171 } << 172 315 173 std::ifstream ifs; << 316 if( fIsotopeList !=0 ) return; 174 G4String filename(path); << 317 fIsotopeList = new G4IsotopeList(); 175 filename += "/ENSDFSTATE.dat"; << 176 << 177 ifs.open(filename.c_str()); << 178 if (!ifs.good()) { << 179 G4Exception("G4NuclideTable", "PART70001 << 180 return; << 181 } << 182 318 183 G4int ionCode = 0; << 319 for (size_t i=0; i<nEntries_ground_state; i++) { 184 G4int iLevel = 0; << 185 G4int ionZ; << 186 G4int ionA; << 187 G4double ionE; << 188 G4String ionFL; << 189 G4double ionLife; << 190 G4int ionJ; << 191 G4double ionMu; << 192 << 193 // Lifetimes read from ENSDFSTATE are mean << 194 ifs >> ionZ >> ionA >> ionE >> ionFL >> io << 195 << 196 while (ifs.good()) // Loop checking, 09.0 << 197 { << 198 if (ionCode != 1000 * ionZ + ionA) { << 199 iLevel = 0; << 200 ionCode = 1000 * ionZ + ionA; << 201 } << 202 << 203 ionE *= keV; << 204 G4Ions::G4FloatLevelBase flb = StripFloa << 205 ionLife *= ns; << 206 ionMu *= (joule / tesla); << 207 << 208 if ((ionE == 0 && flb == G4Ions::G4Float << 209 || (mean_life_threshold <= ionLife & << 210 { << 211 if (ionE > 0) ++iLevel; << 212 if (iLevel > 9) iLevel = 9; << 213 << 214 auto fProperty = new G4IsotopeProperty << 215 << 216 // Set Isotope Property << 217 fProperty->SetAtomicNumber(ionZ); << 218 fProperty->SetAtomicMass(ionA); << 219 fProperty->SetIsomerLevel(iLevel); << 220 fProperty->SetEnergy(ionE); << 221 fProperty->SetiSpin(ionJ); << 222 fProperty->SetLifeTime(ionLife); << 223 fProperty->SetDecayTable(nullptr); << 224 fProperty->SetMagneticMoment(ionMu); << 225 fProperty->SetFloatLevelBase(flb); << 226 << 227 fIsotopeList->push_back(fProperty); << 228 << 229 auto itf = map_full_list.find(ionCode) << 230 if (itf == map_full_list.cend()) { << 231 std::multimap<G4double, G4IsotopePro << 232 itf = (map_full_list.insert(std::pai << 233 ionCode, aMultiMap))) << 234 .first; << 235 } << 236 itf->second.insert(std::pair<G4double, << 237 } << 238 320 239 ifs >> ionZ >> ionA >> ionE >> ionFL >> << 321 G4int ionZ = (G4int)groundStateTable[i][idxZ]; 240 } // End while << 322 G4int ionA = (G4int)groundStateTable[i][idxA]; >> 323 G4int lvl = 0; // ground state >> 324 G4double ionE = groundStateTable[i][idxEnergy]*keV; >> 325 G4double ionLife = groundStateTable[i][idxLife]*ns; >> 326 G4int ionJ = (G4int)(groundStateTable[i][idxSpin]); >> 327 G4double ionMu = groundStateTable[i][idxMu]*(joule/tesla); >> 328 >> 329 if ( ionLife < 0.0 || ionLife*std::log(2.0) > threshold_of_half_life ) { >> 330 >> 331 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); >> 332 >> 333 // Set Isotope Property >> 334 fProperty->SetAtomicNumber(ionZ); >> 335 fProperty->SetAtomicMass(ionA); >> 336 fProperty->SetIsomerLevel(lvl); >> 337 fProperty->SetEnergy(ionE); >> 338 fProperty->SetiSpin(ionJ); >> 339 fProperty->SetLifeTime(ionLife); >> 340 fProperty->SetDecayTable(0); >> 341 fProperty->SetMagneticMoment(ionMu); >> 342 >> 343 //G4cout << ionZ << " " << ionA << " " << lvl << " " << ionE/keV << " [keV]" << G4endl; >> 344 fIsotopeList->push_back(fProperty); >> 345 >> 346 G4int ionCode = 1000*ionZ + ionA; >> 347 if ( map_pre_load_list.find ( ionCode ) == map_pre_load_list.end() ) { >> 348 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 349 map_pre_load_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); >> 350 } >> 351 map_pre_load_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , fProperty ) ); 241 352 242 minimum_mean_life_threshold = mean_life_th << 353 } 243 } << 354 } 244 355 245 // Clear current map << 356 if ( threshold_of_half_life >= 1.0*ns ) { 246 for (auto& it : map_pre_load_list) { << 247 it.second.clear(); << 248 } << 249 map_pre_load_list.clear(); << 250 357 251 // Build map based on current threshold valu << 358 G4int ionCode=0; 252 for (const auto& it : map_full_list) { << 359 G4int iLevel=0; 253 G4int ionCode = it.first; << 360 G4double previousE=0.0; 254 auto itf = map_pre_load_list.find(ionCode) << 361 255 if (itf == map_pre_load_list.cend()) { << 362 for (size_t i=0; i<nEntries_excite_state; i++) { 256 std::multimap<G4double, G4IsotopePropert << 363 257 itf = (map_pre_load_list.insert( << 364 G4int ionZ = (G4int)exciteStateTable[i][idxZ]; 258 std::pair<G4int, std::multimap< << 365 G4int ionA = (G4int)exciteStateTable[i][idxA]; 259 .first; << 366 if ( ionCode != 1000*ionZ + ionA ) { 260 } << 367 previousE=0.0; >> 368 iLevel = 0; >> 369 ionCode = 1000*ionZ + ionA; >> 370 } >> 371 >> 372 G4double ionE = exciteStateTable[i][idxEnergy]*keV; >> 373 G4double ionLife = exciteStateTable[i][idxLife]*ns; >> 374 G4int ionJ = (G4int)(exciteStateTable[i][idxSpin]); >> 375 G4double ionMu = exciteStateTable[i][idxMu]*(joule/tesla); >> 376 >> 377 if (( ionLife < 0.0 || ionLife*ionLife*std::log(2.0) > threshold_of_half_life ) >> 378 && (ionE > levelTolerance+previousE)) { >> 379 previousE = ionE; >> 380 iLevel++; >> 381 if ( iLevel > 9 ) iLevel=9; >> 382 //G4cout << ionZ << " " << ionA << " " << iLevel << " " << ionE/keV << " [keV]" << G4endl; >> 383 >> 384 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); >> 385 >> 386 // Set Isotope Property >> 387 fProperty->SetAtomicNumber(ionZ); >> 388 fProperty->SetAtomicMass(ionA); >> 389 fProperty->SetIsomerLevel(iLevel); >> 390 fProperty->SetEnergy(ionE); >> 391 fProperty->SetiSpin(ionJ); >> 392 fProperty->SetLifeTime(ionLife); >> 393 fProperty->SetDecayTable(0); >> 394 fProperty->SetMagneticMoment(ionMu); >> 395 >> 396 fIsotopeList->push_back(fProperty); >> 397 >> 398 if ( map_pre_load_list.find ( ionCode ) == map_pre_load_list.end() ) { >> 399 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 400 map_pre_load_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); >> 401 } >> 402 map_pre_load_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , fProperty ) ); 261 403 262 G4int iLevel = 0; << 404 } 263 for (const auto& itt : it.second) { << 264 G4double exEnergy = itt.first; << 265 G4double meanLife = itt.second->GetLifeT << 266 if (exEnergy == 0.0 || meanLife > mean_l << 267 if (itt.first != 0.0) ++iLevel; << 268 if (iLevel > 9) iLevel = 9; << 269 itt.second->SetIsomerLevel(iLevel); << 270 itf->second.insert(std::pair<G4double, << 271 } 405 } 272 } << 406 } else { 273 } << 274 } << 275 << 276 void G4NuclideTable::AddState(G4int ionZ, G4in << 277 G4double ionMu) << 278 { << 279 if (G4Threading::IsMasterThread()) { << 280 G4int flbIndex = 0; << 281 ionE = StripFloatLevelBase(ionE, flbIndex) << 282 AddState(ionZ, ionA, ionE, flbIndex, ionLi << 283 } << 284 } << 285 407 286 void G4NuclideTable::AddState(G4int ionZ, G4in << 408 char* path = getenv("G4ENSDFSTATEDATA"); 287 G4double ionLife << 288 { << 289 if (G4Threading::IsMasterThread()) { << 290 if (fUserDefinedList == nullptr) fUserDefi << 291 409 292 auto fProperty = new G4IsotopeProperty(); << 410 if ( !path ) { >> 411 G4Exception("G4NuclideTable", "PART70000", >> 412 FatalException, "G4ENSDFSTATEDATA environment variable must be set"); >> 413 return; >> 414 } >> 415 >> 416 std::fstream ifs; >> 417 G4String filename(path); >> 418 filename += "/ENSDFSTATE.dat"; >> 419 >> 420 ifs.open( filename.c_str() ); >> 421 >> 422 if ( !ifs.good() ) { >> 423 G4Exception("G4NuclideTable", "PART70001", >> 424 FatalException, "ENSDFSTATE.dat is not found."); >> 425 return; >> 426 } >> 427 293 428 294 // Set Isotope Property << 429 G4int ionCode=0; 295 fProperty->SetAtomicNumber(ionZ); << 430 G4int iLevel=0; 296 fProperty->SetAtomicMass(ionA); << 297 fProperty->SetIsomerLevel(9); << 298 fProperty->SetEnergy(ionE); << 299 fProperty->SetiSpin(ionJ); << 300 fProperty->SetLifeTime(ionLife); << 301 fProperty->SetDecayTable(nullptr); << 302 fProperty->SetMagneticMoment(ionMu); << 303 fProperty->SetFloatLevelBase(flbIndex); << 304 431 305 fUserDefinedList->push_back(fProperty); << 432 G4int ionZ; 306 fIsotopeList->push_back(fProperty); << 433 G4int ionA; 307 } << 434 G4double ionE; 308 } << 435 G4double ionLife; >> 436 G4int ionJ; >> 437 G4double ionMu; >> 438 >> 439 ifs >> ionZ >> ionA >> ionE >> ionLife >> ionJ >> ionMu; >> 440 >> 441 while ( ifs.good() ) { >> 442 >> 443 if ( ionCode != 1000*ionZ + ionA ) { >> 444 iLevel = 0; >> 445 ionCode = 1000*ionZ + ionA; >> 446 } >> 447 >> 448 ionE *= keV; >> 449 ionLife *= ns; >> 450 ionMu *= (joule/tesla); >> 451 >> 452 //if ( ionLife == -1 || ionLife > threshold_of_half_life ) { >> 453 if ( ionLife*std::log(2.0) > threshold_of_half_life && ionE != 0 ) { >> 454 >> 455 iLevel++; >> 456 if ( iLevel > 9 ) iLevel=9; >> 457 //G4cout << ionZ << " " << ionA << " " << iLevel << " " << ionE/keV << " [keV]" << G4endl; >> 458 >> 459 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); >> 460 >> 461 // Set Isotope Property >> 462 fProperty->SetAtomicNumber(ionZ); >> 463 fProperty->SetAtomicMass(ionA); >> 464 fProperty->SetIsomerLevel(iLevel); >> 465 fProperty->SetEnergy(ionE); >> 466 fProperty->SetiSpin(ionJ); >> 467 fProperty->SetLifeTime(ionLife); >> 468 fProperty->SetDecayTable(0); >> 469 fProperty->SetMagneticMoment(ionMu); >> 470 >> 471 fIsotopeList->push_back(fProperty); >> 472 >> 473 if ( map_pre_load_list.find ( ionCode ) == map_pre_load_list.end() ) { >> 474 std::multimap<G4double, G4IsotopeProperty*> aMultiMap; >> 475 map_pre_load_list.insert( std::pair< G4int , std::multimap< G4double , G4IsotopeProperty* > > ( ionCode , aMultiMap ) ); >> 476 } >> 477 map_pre_load_list.find ( ionCode ) -> second.insert( std::pair< G4double, G4IsotopeProperty* >( ionE , fProperty ) ); 309 478 310 void G4NuclideTable::AddState(G4int ionZ, G4in << 479 } 311 G4double ionLife << 312 { << 313 if (G4Threading::IsMasterThread()) { << 314 if (fUserDefinedList == nullptr) fUserDefi << 315 480 316 auto fProperty = new G4IsotopeProperty(); << 481 ifs >> ionZ >> ionA >> ionE >> ionLife >> ionJ >> ionMu; >> 482 } 317 483 318 // Set Isotope Property << 484 } 319 fProperty->SetAtomicNumber(ionZ); << 320 fProperty->SetAtomicMass(ionA); << 321 fProperty->SetIsomerLevel(9); << 322 fProperty->SetEnergy(ionE); << 323 fProperty->SetiSpin(ionJ); << 324 fProperty->SetLifeTime(ionLife); << 325 fProperty->SetDecayTable(nullptr); << 326 fProperty->SetMagneticMoment(ionMu); << 327 fProperty->SetFloatLevelBase(flb); << 328 485 329 fUserDefinedList->push_back(fProperty); << 486 if ( fUserDefinedList != NULL ) { 330 fIsotopeList->push_back(fProperty); << 487 for ( G4IsotopeList::iterator it = fUserDefinedList->begin() ; it != fUserDefinedList->end() ; it++ ) { 331 } << 488 fIsotopeList->push_back( *it ); 332 } << 489 } >> 490 } 333 491 334 void G4NuclideTable::SetThresholdOfHalfLife(G4 << 335 { << 336 if (G4Threading::IsMasterThread()) { << 337 mean_life_threshold = t / 0.69314718; << 338 GenerateNuclide(); << 339 } << 340 } 492 } 341 493 342 // Set the mean life threshold for nuclides << 494 void G4NuclideTable::AddState( G4int ionZ, G4int ionA, G4double ionE, G4double ionLife, G4int ionJ=0, G4double ionMu=0.0) 343 // All nuclides with mean lives greater than t << 344 // for this run << 345 void G4NuclideTable::SetMeanLifeThreshold(G4do << 346 { 495 { 347 if (G4Threading::IsMasterThread()) { << 496 if ( fUserDefinedList == NULL ) fUserDefinedList = new G4IsotopeList(); 348 mean_life_threshold = t; << 349 GenerateNuclide(); << 350 } << 351 } << 352 497 353 G4double G4NuclideTable::StripFloatLevelBase(G << 498 G4IsotopeProperty* fProperty = new G4IsotopeProperty(); 354 { << 355 G4double rem = std::fmod(E / (1.0E-3 * eV), << 356 flbIndex = G4int(rem); << 357 return E - rem; << 358 } << 359 499 360 G4Ions::G4FloatLevelBase G4NuclideTable::Strip << 500 // Set Isotope Property 361 { << 501 fProperty->SetAtomicNumber(ionZ); 362 if (sFLB.empty() || 2 < sFLB.size()) { << 502 fProperty->SetAtomicMass(ionA); 363 G4String text; << 503 fProperty->SetIsomerLevel(9); 364 text += sFLB; << 504 fProperty->SetEnergy(ionE); 365 text += " is not valid indicator of G4Ions << 505 fProperty->SetiSpin(ionJ); 366 text += "You may use a wrong version of EN << 506 fProperty->SetLifeTime(ionLife); 367 text += "Please use G4ENSDFSTATE-2.0 or la << 507 fProperty->SetDecayTable(0); >> 508 fProperty->SetMagneticMoment(ionMu); >> 509 >> 510 fUserDefinedList->push_back(fProperty); 368 511 369 G4Exception("G4NuclideTable", "PART70002", << 370 } << 371 G4Ions::G4FloatLevelBase flb = noFloat; << 372 if (!(sFLB == "-")) { << 373 flb = G4Ions::FloatLevelBase(sFLB.back()); << 374 } << 375 return flb; << 376 } 512 } >> 513 377 514