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