Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ParticleHPThermalScatteringData.cc
Go to the documentation of this file.
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// Thermal Neutron Scattering
27// Koi, Tatsumi (SCCS/SLAC)
28//
29// Class Description
30// Cross Sections for a high precision (based on evaluated data
31// libraries) description of themal neutron scattering below 4 eV;
32// Based on Thermal neutron scattering files
33// from the evaluated nuclear data files ENDF/B-VI, Release2
34// To be used in your physics list in case you need this physics.
35// In this case you want to register an object of this class with
36// the corresponding process.
37// Class Description - End
38
39// 15-Nov-06 First implementation is done by T. Koi (SLAC/SCCS)
40// 070625 implement clearCurrentXSData to fix memory leaking by T. Koi
41// P. Arce, June-2014 Conversion neutron_hp to particle_hp
42//
43
44#include <list>
45#include <algorithm>
46
49
50#include "G4SystemOfUnits.hh"
51#include "G4Neutron.hh"
52#include "G4ElementTable.hh"
53
54#include "G4Threading.hh"
55
57:G4VCrossSectionDataSet("NeutronHPThermalScatteringData")
58,coherent(nullptr)
59,incoherent(nullptr)
60,inelastic(nullptr)
61{
62 // Upper limit of neutron energy
63 emax = 4*eV;
64 SetMinKinEnergy( 0*MeV );
65 SetMaxKinEnergy( emax );
66
67 ke_cache = 0.0;
68 xs_cache = 0.0;
69 element_cache = nullptr;
70 material_cache = nullptr;
71
72 indexOfThermalElement.clear();
73
75}
76
78{
79 clearCurrentXSData();
80
81 delete names;
82}
83
85 G4int /*Z*/ , G4int /*A*/ ,
86 const G4Element* element ,
87 const G4Material* material )
88{
89 G4double eKin = dp->GetKineticEnergy();
90 if ( eKin > 4.0*eV //GetMaxKinEnergy()
91 || eKin < 0 //GetMinKinEnergy()
92 || dp->GetDefinition() != G4Neutron::Neutron() ) return false;
93
94 if ( dic.find( std::pair < const G4Material* , const G4Element* > ( (G4Material*)NULL , element ) ) != dic.end()
95 || dic.find( std::pair < const G4Material* , const G4Element* > ( material , element ) ) != dic.end() ) return true;
96
97 return false;
98}
99
101 G4int /*Z*/ , G4int /*A*/ ,
102 const G4Isotope* /*iso*/ ,
103 const G4Element* element ,
104 const G4Material* material )
105{
106 ke_cache = dp->GetKineticEnergy();
107 element_cache = element;
108 material_cache = material;
109 G4double xs = GetCrossSection( dp , element , material );
110 xs_cache = xs;
111 return xs;
112}
113
114void G4ParticleHPThermalScatteringData::clearCurrentXSData()
115{
116 if ( coherent != nullptr )
117 {
118 for (auto it=coherent->cbegin() ; it!=coherent->cend(); ++it)
119 {
120 if ( it->second != nullptr )
121 {
122 for (auto itt=it->second->cbegin(); itt!=it->second->cend(); ++itt)
123 {
124 delete itt->second;
125 }
126 }
127 delete it->second;
128 }
129 coherent->clear();
130 }
131
132 if ( incoherent != nullptr )
133 {
134 for (auto it=incoherent->cbegin(); it!=incoherent->cend() ; ++it)
135 {
136 if ( it->second != nullptr )
137 {
138 for (auto itt=it->second->cbegin(); itt!=it->second->cend(); ++itt)
139 {
140 delete itt->second;
141 }
142 }
143 delete it->second;
144 }
145 incoherent->clear();
146 }
147
148 if ( inelastic != nullptr )
149 {
150 for (auto it=inelastic->cbegin(); it!=inelastic->cend(); ++it)
151 {
152 if ( it->second != nullptr )
153 {
154 for (auto itt=it->second->cbegin(); itt!=it->second->cend(); ++itt)
155 {
156 delete itt->second;
157 }
158 }
159 delete it->second;
160 }
161 inelastic->clear();
162 }
163
164}
165
166
168{
169 G4bool result = false;
170
171 G4double eKin = aP->GetKineticEnergy();
172 // Check energy
173 if ( eKin < emax )
174 {
175 // Check Particle Species
176 if ( aP->GetDefinition() == G4Neutron::Neutron() )
177 {
178 // anEle is one of Thermal elements
179 G4int ie = (G4int) anEle->GetIndex();
180 for (auto it = indexOfThermalElement.cbegin();
181 it != indexOfThermalElement.cend() ; ++it)
182 {
183 if ( ie == *it ) return true;
184 }
185 }
186 }
187
188 return result;
189}
190
191
193{
194
195 if ( &aP != G4Neutron::Neutron() )
196 throw G4HadronicException(__FILE__, __LINE__, "Attempt to use NeutronHP data for particles other than neutrons!!!");
197
198 //std::map < std::pair < G4Material* , const G4Element* > , G4int > dic;
199 //
200 dic.clear();
201 if ( G4Threading::IsMasterThread() ) clearCurrentXSData();
202
203 std::map < G4String , G4int > co_dic;
204
205 //Searching Nist Materials
206 static G4ThreadLocal G4MaterialTable* theMaterialTable = nullptr;
207 if (!theMaterialTable) theMaterialTable= G4Material::GetMaterialTable();
208 std::size_t numberOfMaterials = G4Material::GetNumberOfMaterials();
209 for ( std::size_t i = 0 ; i < numberOfMaterials ; ++i )
210 {
211 G4Material* material = (*theMaterialTable)[i];
212 G4int numberOfElements = (G4int)material->GetNumberOfElements();
213 for ( G4int j = 0 ; j < numberOfElements ; ++j )
214 {
215 const G4Element* element = material->GetElement(j);
216 if ( names->IsThisThermalElement ( material->GetName() , element->GetName() ) )
217 {
218 G4int ts_ID_of_this_geometry;
219 G4String ts_ndl_name = names->GetTS_NDL_Name( material->GetName() , element->GetName() );
220 if ( co_dic.find ( ts_ndl_name ) != co_dic.cend() )
221 {
222 ts_ID_of_this_geometry = co_dic.find ( ts_ndl_name ) -> second;
223 }
224 else
225 {
226 ts_ID_of_this_geometry = (G4int)co_dic.size();
227 co_dic.insert ( std::pair< G4String , G4int >( ts_ndl_name , ts_ID_of_this_geometry ) );
228 }
229
230 dic.insert( std::pair < std::pair < G4Material* , const G4Element* > , G4int > ( std::pair < G4Material* , const G4Element* > ( material , element ) , ts_ID_of_this_geometry ) );
231 }
232 }
233 }
234
235 //Searching TS Elements
236 static G4ThreadLocal G4ElementTable* theElementTable = nullptr;
237 if (!theElementTable) theElementTable= G4Element::GetElementTable();
238 std::size_t numberOfElements = G4Element::GetNumberOfElements();
239
240 for ( std::size_t i = 0 ; i < numberOfElements ; ++i )
241 {
242 const G4Element* element = (*theElementTable)[i];
243 if ( names->IsThisThermalElement ( element->GetName() ) )
244 {
245 if ( names->IsThisThermalElement ( element->GetName() ) )
246 {
247 G4int ts_ID_of_this_geometry;
248 G4String ts_ndl_name = names->GetTS_NDL_Name( element->GetName() );
249 if ( co_dic.find ( ts_ndl_name ) != co_dic.cend() )
250 {
251 ts_ID_of_this_geometry = co_dic.find ( ts_ndl_name ) -> second;
252 }
253 else
254 {
255 ts_ID_of_this_geometry = (G4int)co_dic.size();
256 co_dic.insert ( std::pair< G4String , G4int >( ts_ndl_name , ts_ID_of_this_geometry ) );
257 }
258
259 dic.insert( std::pair < std::pair < const G4Material* , const G4Element* > , G4int > ( std::pair < const G4Material* , const G4Element* > ( (G4Material*)NULL , element ) , ts_ID_of_this_geometry ) );
260 }
261 }
262 }
263
264 G4cout << G4endl;
265 G4cout << "Neutron HP Thermal Scattering Data: Following material-element pairs and/or elements are registered." << G4endl;
266 for ( auto it = dic.cbegin() ; it != dic.cend() ; ++it )
267 {
268 if ( it->first.first != nullptr )
269 {
270 G4cout << "Material " << it->first.first->GetName() << " - Element "
271 << it->first.second->GetName()
272 << ", internal thermal scattering id " << it->second << G4endl;
273 }
274 else
275 {
276 G4cout << "Element " << it->first.second->GetName()
277 << ", internal thermal scattering id " << it->second << G4endl;
278 }
279 }
280 G4cout << G4endl;
281
283
284 coherent = hpmanager->GetThermalScatteringCoherentCrossSections();
285 incoherent = hpmanager->GetThermalScatteringIncoherentCrossSections();
286 inelastic = hpmanager->GetThermalScatteringInelasticCrossSections();
287
289 {
290 if ( coherent == nullptr )
291 coherent = new std::map< G4int , std::map< G4double , G4ParticleHPVector* >* >;
292 if ( incoherent == nullptr )
293 incoherent = new std::map< G4int , std::map< G4double , G4ParticleHPVector* >* >;
294 if ( inelastic == nullptr )
295 inelastic = new std::map< G4int , std::map< G4double , G4ParticleHPVector* >* >;
296
297 // Read Cross Section Data files
298
299 G4String dirName;
300 if ( !G4FindDataDir( "G4NEUTRONHPDATA" ) )
301 throw G4HadronicException(__FILE__, __LINE__, "Please setenv G4NEUTRONHPDATA to point to the neutron cross-section files.");
302 G4String baseName = G4FindDataDir( "G4NEUTRONHPDATA" );
303
304 dirName = baseName + "/ThermalScattering";
305
306 G4String ndl_filename;
307 G4String full_name;
308
309 for ( auto it = co_dic.cbegin() ; it != co_dic.cend() ; ++it )
310 {
311 ndl_filename = it->first;
312 G4int ts_ID = it->second;
313
314 // Coherent
315 full_name = dirName + "/Coherent/CrossSection/" + ndl_filename;
316 auto coh_amapTemp_EnergyCross = readData( full_name );
317 coherent->insert ( std::pair < G4int , std::map< G4double , G4ParticleHPVector* >* > ( ts_ID , coh_amapTemp_EnergyCross ) );
318
319 // Incoherent
320 full_name = dirName + "/Incoherent/CrossSection/" + ndl_filename;
321 auto incoh_amapTemp_EnergyCross = readData( full_name );
322 incoherent->insert ( std::pair < G4int , std::map< G4double , G4ParticleHPVector* >* > ( ts_ID , incoh_amapTemp_EnergyCross ) );
323
324 // Inelastic
325 full_name = dirName + "/Inelastic/CrossSection/" + ndl_filename;
326 auto inela_amapTemp_EnergyCross = readData( full_name );
327 inelastic->insert ( std::pair < G4int , std::map< G4double , G4ParticleHPVector* >* > ( ts_ID , inela_amapTemp_EnergyCross ) );
328 }
332 }
333}
334
335
336std::map< G4double , G4ParticleHPVector* >*
337G4ParticleHPThermalScatteringData::readData ( G4String full_name )
338{
339 auto aData = new std::map< G4double , G4ParticleHPVector* >;
340
341 std::istringstream theChannel;
342 G4ParticleHPManager::GetInstance()->GetDataStream(full_name,theChannel);
343
344 G4int dummy;
345 while ( theChannel >> dummy ) // MF // Loop checking, 11.05.2015, T. Koi
346 {
347 theChannel >> dummy; // MT
348 G4double temp;
349 theChannel >> temp;
350 G4ParticleHPVector* anEnergyCross = new G4ParticleHPVector;
351 G4int nData;
352 theChannel >> nData;
353 anEnergyCross->Init ( theChannel , nData , eV , barn );
354 aData->insert ( std::pair < G4double , G4ParticleHPVector* > ( temp , anEnergyCross ) );
355 }
356
357 return aData;
358}
359
360
362{
363 if( &aP != G4Neutron::Neutron() )
364 throw G4HadronicException(__FILE__, __LINE__, "Attempt to use NeutronHP data for particles other than neutrons!!!");
365}
366
367
369{
370 G4double result = 0;
371
372 G4int ts_id =getTS_ID( aM , anE );
373
374 if ( ts_id == -1 ) return result;
375
376 G4double aT = aM->GetTemperature();
377
378 G4double Xcoh = GetX ( aP , aT , coherent->find(ts_id)->second );
379 G4double Xincoh = GetX ( aP , aT , incoherent->find(ts_id)->second );
380 G4double Xinela = GetX ( aP , aT , inelastic->find(ts_id)->second );
381
382 result = Xcoh + Xincoh + Xinela;
383
384 return result;
385}
386
387
389{
390 G4double result = 0;
391 G4int ts_id = getTS_ID( aM , anE );
392 G4double aT = aM->GetTemperature();
393 result = GetX ( aP , aT , inelastic->find( ts_id )->second );
394 return result;
395}
396
398{
399 G4double result = 0;
400 G4int ts_id = getTS_ID( aM , anE );
401 G4double aT = aM->GetTemperature();
402 result = GetX ( aP , aT , coherent->find( ts_id )->second );
403 return result;
404}
405
407{
408 G4double result = 0;
409 G4int ts_id = getTS_ID( aM , anE );
410 G4double aT = aM->GetTemperature();
411 result = GetX ( aP , aT , incoherent->find( ts_id )->second );
412 return result;
413}
414
415G4int G4ParticleHPThermalScatteringData::getTS_ID ( const G4Material* material , const G4Element* element )
416{
417 G4int result = -1;
418 if ( dic.find( std::pair < const G4Material* , const G4Element* > ( (G4Material*)NULL , element ) ) != dic.end() )
419 return dic.find( std::pair < const G4Material* , const G4Element* > ( (G4Material*)NULL , element ) )->second;
420 if ( dic.find( std::pair < const G4Material* , const G4Element* > ( material , element ) ) != dic.end() )
421 return dic.find( std::pair < const G4Material* , const G4Element* > ( material , element ) )->second;
422 return result;
423}
424
425G4double G4ParticleHPThermalScatteringData::GetX ( const G4DynamicParticle* aP, G4double aT , std::map < G4double , G4ParticleHPVector* >* amapTemp_EnergyCross )
426{
427 G4double result = 0;
428 if ( amapTemp_EnergyCross->size() == 0 ) return result;
429
430 G4double eKinetic = aP->GetKineticEnergy();
431
432 if ( amapTemp_EnergyCross->size() == 1 ) {
433 if ( std::fabs ( aT - amapTemp_EnergyCross->cbegin()->first ) / amapTemp_EnergyCross->begin()->first > 0.1 ) {
434 G4cout << "G4ParticleHPThermalScatteringData:: The temperature of material ("
435 << aT/kelvin << "K) is different more than 10% from temperature of thermal scattering file expected ("
436 << amapTemp_EnergyCross->begin()->first << "K). Result may not be reliable."
437 << G4endl;
438 }
439 result = amapTemp_EnergyCross->begin()->second->GetXsec ( eKinetic );
440 return result;
441 }
442
443 auto it = amapTemp_EnergyCross->cbegin();
444 for (it=amapTemp_EnergyCross->cbegin(); it!=amapTemp_EnergyCross->cend(); ++it)
445 {
446 if ( aT < it->first ) break;
447 }
448 if ( it == amapTemp_EnergyCross->cbegin() ) {
449 ++it; // lower than the first
450 } else if ( it == amapTemp_EnergyCross->cend() ) {
451 --it; // upper than the last
452 }
453
454 G4double TH = it->first;
455 G4double XH = it->second->GetXsec ( eKinetic );
456
457 if ( it != amapTemp_EnergyCross->cbegin() ) --it;
458 G4double TL = it->first;
459 G4double XL = it->second->GetXsec ( eKinetic );
460
461 if ( TH == TL )
462 throw G4HadronicException(__FILE__, __LINE__, "Thermal Scattering Data Error!");
463
464 G4double T = aT;
465 G4double X = ( XH - XL ) / ( TH - TL ) * ( T - TL ) + XL;
466 result = X;
467
468 return result;
469}
470
471
473{
474 names->AddThermalElement( nameG4Element , filename );
475}
476
478{
479 outFile << "High Precision cross data based on thermal scattering data in evaluated nuclear data libraries for neutrons below 5eV on specific materials\n" ;
480}
std::vector< G4Element * > G4ElementTable
const char * G4FindDataDir(const char *)
std::vector< G4Material * > G4MaterialTable
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4ElementTable * GetElementTable()
Definition: G4Element.cc:403
static size_t GetNumberOfElements()
Definition: G4Element.cc:410
size_t GetIndex() const
Definition: G4Element.hh:182
const G4String & GetName() const
Definition: G4Element.hh:127
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:684
G4double GetTemperature() const
Definition: G4Material.hh:177
const G4Element * GetElement(G4int iel) const
Definition: G4Material.hh:197
size_t GetNumberOfElements() const
Definition: G4Material.hh:181
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:677
const G4String & GetName() const
Definition: G4Material.hh:172
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
void RegisterThermalScatteringIncoherentCrossSections(std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > *val)
std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > * GetThermalScatteringCoherentCrossSections()
std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > * GetThermalScatteringInelasticCrossSections()
void RegisterThermalScatteringCoherentCrossSections(std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > *val)
std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > * GetThermalScatteringIncoherentCrossSections()
static G4ParticleHPManager * GetInstance()
void GetDataStream(G4String, std::istringstream &iss)
void RegisterThermalScatteringInelasticCrossSections(std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > *val)
G4double GetCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
G4double GetIncoherentCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
void BuildPhysicsTable(const G4ParticleDefinition &)
G4double GetIsoCrossSection(const G4DynamicParticle *, G4int, G4int, const G4Isotope *, const G4Element *, const G4Material *)
G4double GetCoherentCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
void DumpPhysicsTable(const G4ParticleDefinition &)
G4double GetInelasticCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
virtual void CrossSectionDescription(std::ostream &) const
G4bool IsApplicable(const G4DynamicParticle *, const G4Element *)
G4bool IsIsoApplicable(const G4DynamicParticle *, G4int, G4int, const G4Element *, const G4Material *)
void Init(std::istream &aDataFile, G4int total, G4double ux=1., G4double uy=1.)
void SetMaxKinEnergy(G4double value)
void SetMinKinEnergy(G4double value)
G4bool IsMasterThread()
Definition: G4Threading.cc:124
#define G4ThreadLocal
Definition: tls.hh:77