Geant4 11.4.0
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// G4ParticleHPThermalScatteringData
27//
28// 15-Nov-06 First implementation is done by T. Koi (SLAC/SCCS)
29// 070625 implement clearCurrentXSData to fix memory leaking by T. Koi
30// P. Arce, June-2014 Conversion neutron_hp to particle_hp
31// ---------------------------------------------------------------------
32
34
35#include "G4ElementTable.hh"
36#include "G4Neutron.hh"
38#include "G4SystemOfUnits.hh"
39#include "G4Threading.hh"
40
41#include <algorithm>
42#include <list>
43
44G4ParticleHPThermalScatteringNames* G4ParticleHPThermalScatteringData::names = nullptr;
45std::vector<G4int>* G4ParticleHPThermalScatteringData::indexOfThermalElement = nullptr;
46std::map<std::pair<const G4Material*, const G4Element*>, G4int>* G4ParticleHPThermalScatteringData::dic = nullptr;
47
49 : G4VCrossSectionDataSet("NeutronHPThermalScatteringData")
50{
51 // Upper limit of neutron energy
52 emax = 4 * CLHEP::eV;
53 SetMinKinEnergy(0 * MeV);
54 SetMaxKinEnergy(emax);
55
56 ke_cache = 0.0;
57 xs_cache = 0.0;
58 element_cache = nullptr;
59 material_cache = nullptr;
60
61 if (nullptr == names) {
62 isInitializer = true;
63 indexOfThermalElement = new std::vector<G4int>;
65 dic = new std::map<std::pair<const G4Material*, const G4Element*>, G4int>;
66
68 coherent = new std::map<G4int, std::map<G4double, G4ParticleHPVector*>*>;
69 incoherent = new std::map<G4int, std::map<G4double, G4ParticleHPVector*>*>;
70 inelastic = new std::map<G4int, std::map<G4double, G4ParticleHPVector*>*>;
71
75 }
76}
77
79{
80 if (!isInitializer) return;
81
82 clearCurrentXSData(coherent);
83 clearCurrentXSData(incoherent);
84 clearCurrentXSData(inelastic);
85
86 delete names;
87 delete dic;
88 delete indexOfThermalElement;
89 names = nullptr;
90 dic = nullptr;
91 indexOfThermalElement = nullptr;
92}
93
95 G4int /*A*/, const G4Element* element,
96 const G4Material* material)
97{
98 if (dp->GetKineticEnergy() > emax)
99 return false;
100
101 if (dic->find(std::pair<const G4Material*, const G4Element*>((G4Material*)nullptr, element))
102 != dic->end()
103 || dic->find(std::pair<const G4Material*, const G4Element*>(material, element)) != dic->end())
104 return true;
105
106 return false;
107}
108
110 G4int /*Z*/, G4int /*A*/,
111 const G4Isotope* /*iso*/,
112 const G4Element* element,
113 const G4Material* material)
114{
115 ke_cache = dp->GetKineticEnergy();
116 element_cache = element;
117 material_cache = material;
118 G4double xs = GetCrossSection(dp, element, material);
119 xs_cache = xs;
120 return xs;
121}
122
123void G4ParticleHPThermalScatteringData::clearCurrentXSData(std::map<G4int, std::map<G4double, G4ParticleHPVector*>*>* ptr)
124{
125 if (nullptr == ptr) return;
126 for (auto it = ptr->begin(); it != ptr->end(); ++it) {
127 auto p = it->second;
128 if (nullptr != p) {
129 for (auto itt = p->begin(); itt != p->end(); ++itt) {
130 delete itt->second;
131 }
132 delete p;
133 }
134 }
135 delete ptr;
136}
137
139 const G4Element* anEle)
140{
141 // Check energy
142 if (aP->GetKineticEnergy() > emax)
143 return false;
144
145 // anEle is one of Thermal elements
146 auto ie = (G4int)anEle->GetIndex();
147 for (auto const& it : *indexOfThermalElement) {
148 if (ie == it) return true;
149 }
150 return false;
151}
152
154{
155 if (&aP != G4Neutron::Neutron()) {
157 ed << "Neutron thermal scattering cannot be applied to " << aP.GetParticleName();
158
159 G4Exception("G4ParticleHPThermalScatteringData::BuildPhysicsTable","hp0001",
160 FatalException, ed, " run stopped");
161 return;
162 }
163
164 // Common initialisation for all threads
166 verbose = hpmanager->GetVerboseLevel();
167
168 coherent = hpmanager->GetThermalScatteringCoherentCrossSections();
169 incoherent = hpmanager->GetThermalScatteringIncoherentCrossSections();
170 inelastic = hpmanager->GetThermalScatteringInelasticCrossSections();
171
172 // The initialisation is performed only in the master thread
173 if (!isInitializer)
174 return;
175
176 std::map<G4String, G4int> co_dic;
177
178 // Searching Materials
179 auto const theMaterialTable = G4Material::GetMaterialTable();
180 std::size_t numberOfMaterials = G4Material::GetNumberOfMaterials();
181 for (std::size_t i = 0; i < numberOfMaterials; ++i) {
182 G4Material* material = (*theMaterialTable)[i];
183 auto numberOfElements = (G4int)material->GetNumberOfElements();
184 for (G4int j = 0; j < numberOfElements; ++j) {
185 const G4Element* element = material->GetElement(j);
186 if (names->IsThisThermalElement(material->GetName(), element->GetName())) {
187 G4int ts_ID_of_this_geometry;
188 G4String ts_ndl_name = names->GetTS_NDL_Name(material->GetName(), element->GetName());
189 if (co_dic.find(ts_ndl_name) != co_dic.cend()) {
190 ts_ID_of_this_geometry = co_dic.find(ts_ndl_name)->second;
191 }
192 else {
193 ts_ID_of_this_geometry = (G4int)co_dic.size();
194 co_dic.insert(std::pair<G4String, G4int>(ts_ndl_name, ts_ID_of_this_geometry));
195 }
196
197 dic->insert(std::pair<std::pair<G4Material*, const G4Element*>, G4int>(
198 std::pair<G4Material*, const G4Element*>(material, element), ts_ID_of_this_geometry));
199 }
200 }
201 }
202
203 // Searching TS Elements
204 auto const theElementTable = G4Element::GetElementTable();
205 std::size_t numberOfElements = G4Element::GetNumberOfElements();
206
207 for (std::size_t i = 0; i < numberOfElements; ++i) {
208 const G4Element* element = (*theElementTable)[i];
209 if (names->IsThisThermalElement(element->GetName())) {
210 G4int ts_ID_of_this_geometry;
211 const G4String ts_ndl_name = names->GetTS_NDL_Name(element->GetName());
212 if (co_dic.find(ts_ndl_name) != co_dic.cend()) {
213 ts_ID_of_this_geometry = co_dic.find(ts_ndl_name)->second;
214 }
215 else {
216 ts_ID_of_this_geometry = (G4int)co_dic.size();
217 co_dic.insert(std::pair<G4String, G4int>(ts_ndl_name, ts_ID_of_this_geometry));
218 }
219
220 dic->insert(std::pair<std::pair<const G4Material*, const G4Element*>, G4int>(
221 std::pair<const G4Material*, const G4Element*>((G4Material*)nullptr, element),
222 ts_ID_of_this_geometry));
223 }
224 }
225
226 if (0 < verbose) {
227 G4cout << "##T## Neutron HP Thermal Scattering Data: Following material-element pairs and/or elements "
228 "are registered for " << dic->size() << " materials." << G4endl;
229
230 if (dic->empty()) return;
231
232 for (const auto& it : *dic) {
233 if (it.first.first != nullptr) {
234 G4cout << " Material " << it.first.first->GetName() << " - Element "
235 << it.first.second->GetName() << ", internal thermal scattering id " << it.second
236 << G4endl;
237 }
238 else {
239 G4cout << " Element " << it.first.second->GetName() << ", internal thermal scattering id "
240 << it.second << G4endl;
241 }
242 }
243 G4cout << G4endl;
244 }
245
246 // Read Cross Section Data files
247 const G4String dirName = hpmanager->GetNeutronHPPath() + "/ThermalScattering";
248
249 G4String ndl_filename;
250 G4String full_name;
251
252 for (const auto& it : co_dic) {
253 ndl_filename = it.first;
254 G4int ts_ID = it.second;
255
256 // Coherent
257 full_name = dirName + "/Coherent/CrossSection/" + ndl_filename;
258 auto coh_amapTemp_EnergyCross = readData(full_name);
259 coherent->insert(std::pair<G4int, std::map<G4double, G4ParticleHPVector*>*>(
260 ts_ID, coh_amapTemp_EnergyCross));
261
262 // Incoherent
263 full_name = dirName + "/Incoherent/CrossSection/" + ndl_filename;
264 auto incoh_amapTemp_EnergyCross = readData(full_name);
265 incoherent->insert(std::pair<G4int, std::map<G4double, G4ParticleHPVector*>*>(
266 ts_ID, incoh_amapTemp_EnergyCross));
267
268 // Inelastic
269 full_name = dirName + "/Inelastic/CrossSection/" + ndl_filename;
270 auto inela_amapTemp_EnergyCross = readData(full_name);
271 inelastic->insert(std::pair<G4int, std::map<G4double, G4ParticleHPVector*>*>(
272 ts_ID, inela_amapTemp_EnergyCross));
273 }
274}
275
276std::map<G4double, G4ParticleHPVector*>*
277G4ParticleHPThermalScatteringData::readData(const G4String& full_name)
278{
279 auto aData = new std::map<G4double, G4ParticleHPVector*>;
280
281 std::istringstream theChannel;
282 G4ParticleHPManager::GetInstance()->GetDataStream(full_name, theChannel);
283
284 G4int dummy;
285 while (theChannel >> dummy) // MF // Loop checking, 11.05.2015, T. Koi
286 {
287 theChannel >> dummy; // MT
288 G4double temp;
289 theChannel >> temp;
290 auto anEnergyCross = new G4ParticleHPVector;
291 G4int nData;
292 theChannel >> nData;
293 anEnergyCross->Init(theChannel, nData, eV, barn);
294 aData->insert(std::pair<G4double, G4ParticleHPVector*>(temp, anEnergyCross));
295 }
296
297 return aData;
298}
299
302
304 const G4Element* anE,
305 const G4Material* aM)
306{
307 G4double result = 0;
308 G4int ts_id = getTS_ID(aM, anE);
309
310 if (ts_id == -1) return result;
311
312 G4double aT = aM->GetTemperature();
313
314 auto u = coherent->find(ts_id);
315 G4double Xcoh = (u != coherent->end()) ? GetX(aP, aT, u->second) : 0.0;
316 auto v = incoherent->find(ts_id);
317 G4double Xincoh = (v != incoherent->end()) ? GetX(aP, aT, v->second) : 0.0;
318 auto w = inelastic->find(ts_id);
319 G4double Xinela = (w != inelastic->end()) ? GetX(aP, aT, w->second) : 0.0;
320
321 result = Xcoh + Xincoh + Xinela;
322
323 return result;
324}
325
327 const G4Element* anE,
328 const G4Material* aM)
329{
330 G4double result = 0;
331 G4int ts_id = getTS_ID(aM, anE);
332 if (ts_id == -1) return result;
333 G4double aT = aM->GetTemperature();
334 auto ptr = inelastic->find(ts_id);
335 if (ptr != inelastic->end()) {
336 result = GetX(aP, aT, ptr->second);
337 }
338 return result;
339}
340
342 const G4Element* anE,
343 const G4Material* aM)
344{
345 G4double result = 0;
346 G4int ts_id = getTS_ID(aM, anE);
347 if (ts_id == -1) return result;
348 G4double aT = aM->GetTemperature();
349 auto u = coherent->find(ts_id);
350 if (u != coherent->end()) { result = GetX(aP, aT, u->second); }
351 return result;
352}
353
355 const G4Element* anE,
356 const G4Material* aM)
357{
358 G4double result = 0;
359 G4int ts_id = getTS_ID(aM, anE);
360 if (ts_id == -1) return result;
361 G4double aT = aM->GetTemperature();
362 auto u = incoherent->find(ts_id);
363 if (u != incoherent->end()) { result = GetX(aP, aT, u->second); }
364 return result;
365}
366
367G4int G4ParticleHPThermalScatteringData::getTS_ID(const G4Material* material,
368 const G4Element* element)
369{
370 auto it = dic->find(std::pair<const G4Material*, const G4Element*>((G4Material*)nullptr, element));
371 if (it != dic->end()) { return it->second; }
372 auto jt = dic->find(std::pair<const G4Material*, const G4Element*>(material, element));
373 if (jt != dic->end()) { return jt->second; }
374 return -1;
375}
376
377G4double G4ParticleHPThermalScatteringData::
378GetX(const G4DynamicParticle* aP, G4double aT,
379 std::map<G4double, G4ParticleHPVector*>* amapTemp_EnergyCross)
380{
381 if (amapTemp_EnergyCross->empty())
382 return 0.0;
383
384 G4double eKinetic = aP->GetKineticEnergy();
385 auto it_begin = amapTemp_EnergyCross->begin();
386 G4double Tmin = it_begin->first;
387 std::size_t n = amapTemp_EnergyCross->size();
388
389 // special cases
390 if (n == 1 || aT <= Tmin) {
391 return it_begin->second->GetXsec(eKinetic);
392 }
393
394 // high temperature
395 auto it_end = amapTemp_EnergyCross->end();
396 --it_end;
397 G4double Tmax = it_end->first;
398 if (aT >= Tmax) {
399 return it_end->second->GetXsec(eKinetic);
400 }
401
402 // linear interpolation between two temperature values
403 ++it_begin;
404 auto it = it_begin;
405 G4double TH = Tmin;
406 for (;;) {
407 TH = it->first;
408 if (aT <= TH || it == it_end) break;
409 ++it;
410 }
411
412 G4double XH = it->second->GetXsec(eKinetic);
413 --it;
414 G4double TL = it->first;
415 if (TH == TL) return XH;
416
417 G4double XL = it->second->GetXsec(eKinetic);
418 return (aT - TL) * (XH - XL) / (TH - TL) + XL;
419}
420
422 const G4String& filename)
423{
424 names->AddThermalElement(nameG4Element, filename);
425}
426
428{
429 outFile << "High Precision cross data based on thermal scattering data in evaluated nuclear data "
430 "libraries for neutrons below 5eV on specific materials\n";
431}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
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
G4double GetKineticEnergy() const
static std::size_t GetNumberOfElements()
Definition G4Element.cc:408
std::size_t GetIndex() const
Definition G4Element.hh:159
const G4String & GetName() const
Definition G4Element.hh:115
static const G4ElementTable * GetElementTable()
Definition G4Element.cc:401
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
const G4String & GetParticleName() const
void RegisterThermalScatteringIncoherentCrossSections(std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > *val)
std::map< G4int, std::map< G4double, G4ParticleHPVector * > * > * GetThermalScatteringCoherentCrossSections() const
const G4String & GetNeutronHPPath() 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
void AddUserThermalScatteringFile(const G4String &, const G4String &)
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 *)
G4VCrossSectionDataSet(const G4String &nam="")
void SetMaxKinEnergy(G4double value)
void SetMinKinEnergy(G4double value)