Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4NeutronHPThermalScattering.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 (SLAC/SCCS)
28//
29// Class Description:
30//
31// Final State Generators for a high precision (based on evaluated data
32// libraries) description of themal neutron scattering below 4 eV;
33// Based on Thermal neutron scattering files
34// from the evaluated nuclear data files ENDF/B-VI, Release2
35// To be used in your physics list in case you need this physics.
36// In this case you want to register an object of this class with
37// the corresponding process.
38
39
40// 070625 Fix memory leaking at destructor by T. Koi
41// 081201 Fix memory leaking at destructor by T. Koi
42// 100729 Add model name in constructor Problem #1116
43
45#include "G4SystemOfUnits.hh"
46#include "G4Neutron.hh"
47#include "G4ElementTable.hh"
48
50 :G4HadronicInteraction("NeutronHPThermalScattering")
51{
52
53 theHPElastic = new G4NeutronHPElastic();
54
55 SetMinEnergy( 0.*eV );
56 SetMaxEnergy( 4*eV );
57 theXSection = new G4NeutronHPThermalScatteringData();
58 theXSection->BuildPhysicsTable( *(G4Neutron::Neutron()) );
59
60 buildPhysicsTable();
61
62}
63
64
65
67{
68
69 for ( std::map < G4int , std::map < G4double , std::vector < E_isoAng* >* >* >::iterator it = incoherentFSs.begin() ; it != incoherentFSs.end() ; it++ )
70 {
71 std::map < G4double , std::vector < E_isoAng* >* >::iterator itt;
72 for ( itt = it->second->begin() ; itt != it->second->end() ; itt++ )
73 {
74 std::vector< E_isoAng* >::iterator ittt;
75 for ( ittt = itt->second->begin(); ittt != itt->second->end() ; ittt++ )
76 {
77 delete *ittt;
78 }
79 delete itt->second;
80 }
81 delete it->second;
82 }
83
84 for ( std::map < G4int , std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >* >::iterator it = coherentFSs.begin() ; it != coherentFSs.end() ; it++ )
85 {
86 std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >::iterator itt;
87 for ( itt = it->second->begin() ; itt != it->second->end() ; itt++ )
88 {
89 std::vector < std::pair< G4double , G4double >* >::iterator ittt;
90 for ( ittt = itt->second->begin(); ittt != itt->second->end() ; ittt++ )
91 {
92 delete *ittt;
93 }
94 delete itt->second;
95 }
96 delete it->second;
97 }
98
99 for ( std::map < G4int , std::map < G4double , std::vector < E_P_E_isoAng* >* >* >::iterator it = inelasticFSs.begin() ; it != inelasticFSs.end() ; it++ )
100 {
101 std::map < G4double , std::vector < E_P_E_isoAng* >* >::iterator itt;
102 for ( itt = it->second->begin() ; itt != it->second->end() ; itt++ )
103 {
104 std::vector < E_P_E_isoAng* >::iterator ittt;
105 for ( ittt = itt->second->begin(); ittt != itt->second->end() ; ittt++ )
106 {
107 std::vector < E_isoAng* >::iterator it4;
108 for ( it4 = (*ittt)->vE_isoAngle.begin() ; it4 != (*ittt)->vE_isoAngle.end() ; it4++ )
109 {
110 delete *it4;
111 }
112 delete *ittt;
113 }
114 delete itt->second;
115 }
116 delete it->second;
117 }
118
119 delete theHPElastic;
120 delete theXSection;
121}
122
123
124
125std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >* G4NeutronHPThermalScattering::readACoherentFSDATA( G4String name )
126{
127
128 std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >* aCoherentFSDATA = new std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >;
129
130 std::ifstream theChannel( name.c_str() );
131
132 std::vector< G4double > vBraggE;
133
134 G4int dummy;
135 while ( theChannel >> dummy ) // MF
136 {
137 theChannel >> dummy; // MT
138 G4double temp;
139 theChannel >> temp;
140 std::vector < std::pair< G4double , G4double >* >* anBragE_P = new std::vector < std::pair< G4double , G4double >* >;
141
142 G4int n;
143 theChannel >> n;
144 for ( G4int i = 0 ; i < n ; i++ )
145 {
146 G4double Ei;
147 G4double Pi;
148 if ( aCoherentFSDATA->size() == 0 )
149 {
150 theChannel >> Ei;
151 vBraggE.push_back( Ei );
152 }
153 else
154 {
155 Ei = vBraggE[ i ];
156 }
157 theChannel >> Pi;
158 anBragE_P->push_back ( new std::pair < G4double , G4double > ( Ei , Pi ) );
159 //G4cout << "Coherent Elastic " << Ei << " " << Pi << G4endl;
160 }
161 aCoherentFSDATA->insert ( std::pair < G4double , std::vector < std::pair< G4double , G4double >* >* > ( temp , anBragE_P ) );
162 }
163
164 return aCoherentFSDATA;
165}
166
167
168
169std::map < G4double , std::vector < E_P_E_isoAng* >* >* G4NeutronHPThermalScattering::readAnInelasticFSDATA ( G4String name )
170{
171 std::map < G4double , std::vector < E_P_E_isoAng* >* >* anT_E_P_E_isoAng = new std::map < G4double , std::vector < E_P_E_isoAng* >* >;
172
173 std::ifstream theChannel( name.c_str() );
174
175 G4int dummy;
176 while ( theChannel >> dummy ) // MF
177 {
178 theChannel >> dummy; // MT
179 G4double temp;
180 theChannel >> temp;
181 std::vector < E_P_E_isoAng* >* vE_P_E_isoAng = new std::vector < E_P_E_isoAng* >;
182 G4int n;
183 theChannel >> n;
184 for ( G4int i = 0 ; i < n ; i++ )
185 {
186 vE_P_E_isoAng->push_back ( readAnE_P_E_isoAng ( &theChannel ) );
187 }
188 anT_E_P_E_isoAng->insert ( std::pair < G4double , std::vector < E_P_E_isoAng* >* > ( temp , vE_P_E_isoAng ) );
189 }
190 theChannel.close();
191
192 return anT_E_P_E_isoAng;
193}
194
195
196
197E_P_E_isoAng* G4NeutronHPThermalScattering::readAnE_P_E_isoAng( std::ifstream* file )
198{
199 E_P_E_isoAng* aData = new E_P_E_isoAng;
200
201 G4double dummy;
202 G4double energy;
203 G4int nep , nl;
204 *file >> dummy;
205 *file >> energy;
206 aData->energy = energy*eV;
207 *file >> dummy;
208 *file >> dummy;
209 *file >> nep;
210 *file >> nl;
211 aData->n = nep/nl;
212 for ( G4int i = 0 ; i < aData->n ; i++ )
213 {
214 G4double prob;
215 E_isoAng* anE_isoAng = new E_isoAng;
216 aData->vE_isoAngle.push_back( anE_isoAng );
217 *file >> energy;
218 anE_isoAng->energy = energy*eV;
219 anE_isoAng->n = nl - 2;
220 anE_isoAng->isoAngle.resize( anE_isoAng->n );
221 *file >> prob;
222 aData->prob.push_back( prob );
223 //G4cout << "G4NeutronHPThermalScattering inelastic " << energy/eV << " " << i << " " << prob << " " << aData->prob[ i ] << G4endl;
224 for ( G4int j = 0 ; j < anE_isoAng->n ; j++ )
225 {
226 G4double x;
227 *file >> x;
228 anE_isoAng->isoAngle[j] = x ;
229 //G4cout << "G4NeutronHPThermalScattering inelastic " << x << anE_isoAng->isoAngle[j] << G4endl;
230 }
231 }
232
233 // Calcuate sum_of_provXdEs
234 G4double total = 0;
235 for ( G4int i = 0 ; i < aData->n - 1 ; i++ )
236 {
237 G4double E_L = aData->vE_isoAngle[i]->energy/eV;
238 G4double E_H = aData->vE_isoAngle[i+1]->energy/eV;
239 G4double dE = E_H - E_L;
240 total += ( ( aData->prob[i] ) * dE );
241 }
242 aData->sum_of_probXdEs = total;
243
244 return aData;
245}
246
247
248
249std::map < G4double , std::vector < E_isoAng* >* >* G4NeutronHPThermalScattering::readAnIncoherentFSDATA ( G4String name )
250{
251 std::map < G4double , std::vector < E_isoAng* >* >* T_E = new std::map < G4double , std::vector < E_isoAng* >* >;
252
253 std::ifstream theChannel( name.c_str() );
254
255 G4int dummy;
256 while ( theChannel >> dummy ) // MF
257 {
258 theChannel >> dummy; // MT
259 G4double temp;
260 theChannel >> temp;
261 std::vector < E_isoAng* >* vE_isoAng = new std::vector < E_isoAng* >;
262 G4int n;
263 theChannel >> n;
264 for ( G4int i = 0 ; i < n ; i++ )
265 vE_isoAng->push_back ( readAnE_isoAng( &theChannel ) );
266 T_E->insert ( std::pair < G4double , std::vector < E_isoAng* >* > ( temp , vE_isoAng ) );
267 }
268 theChannel.close();
269
270 return T_E;
271}
272
273
274
275E_isoAng* G4NeutronHPThermalScattering::readAnE_isoAng( std::ifstream* file )
276{
277 E_isoAng* aData = new E_isoAng;
278
279 G4double dummy;
280 G4double energy;
281 G4int n;
282 *file >> dummy;
283 *file >> energy;
284 *file >> dummy;
285 *file >> dummy;
286 *file >> n;
287 *file >> dummy;
288 aData->energy = energy*eV;
289 aData->n = n-2;
290 aData->isoAngle.resize( n );
291
292 *file >> dummy;
293 *file >> dummy;
294 for ( G4int i = 0 ; i < aData->n ; i++ )
295 *file >> aData->isoAngle[i];
296
297 return aData;
298}
299
300
301
303{
304
305// Select Element > Reaction >
306
307 const G4Material * theMaterial = aTrack.GetMaterial();
308 G4double aTemp = theMaterial->GetTemperature();
309 G4int n = theMaterial->GetNumberOfElements();
310 //static const G4ElementTable* theElementTable = G4Element::GetElementTable();
311
312 G4bool findThermalElement = false;
313 G4int ielement;
314 const G4Element* theElement = NULL;
315 for ( G4int i = 0; i < n ; i++ )
316 {
317 theElement = theMaterial->GetElement(i);
318 //Select target element
319 if ( aNucleus.GetZ_asInt() == (G4int)(theElement->GetZ() + 0.5 ) )
320 {
321 //Check Applicability of Thermal Scattering
322 if ( getTS_ID( NULL , theElement ) != -1 )
323 {
324 ielement = getTS_ID( NULL , theElement );
325 findThermalElement = true;
326 break;
327 }
328 else if ( getTS_ID( theMaterial , theElement ) != -1 )
329 {
330 ielement = getTS_ID( theMaterial , theElement );
331 findThermalElement = true;
332 break;
333 }
334 }
335 }
336
337 if ( findThermalElement == true )
338 {
339
340// Select Reaction (Inelastic, coherent, incoherent)
341
342 G4ParticleDefinition* pd = const_cast< G4ParticleDefinition* >( aTrack.GetDefinition() );
343 G4DynamicParticle* dp = new G4DynamicParticle ( pd , aTrack.Get4Momentum() );
344 G4double total = theXSection->GetCrossSection( dp , theElement , theMaterial );
345 G4double inelastic = theXSection->GetInelasticCrossSection( dp , theElement , theMaterial );
346
347
348 G4double random = G4UniformRand();
349 if ( random <= inelastic/total )
350 {
351 // Inelastic
352
353 // T_L and T_H
354 std::map < G4double , std::vector< E_P_E_isoAng* >* >::iterator it;
355 std::vector<G4double> v_temp;
356 v_temp.clear();
357 for ( it = inelasticFSs.find( ielement )->second->begin() ; it != inelasticFSs.find( ielement )->second->end() ; it++ )
358 {
359 v_temp.push_back( it->first );
360 }
361
362// T_L T_H
363 std::pair < G4double , G4double > tempLH = find_LH ( aTemp , &v_temp );
364//
365// For T_L aNEP_EPM_TL and T_H aNEP_EPM_TH
366//
367 std::vector< E_P_E_isoAng* >* vNEP_EPM_TL = 0;
368 std::vector< E_P_E_isoAng* >* vNEP_EPM_TH = 0;
369
370 if ( tempLH.first != 0.0 && tempLH.second != 0.0 )
371 {
372 vNEP_EPM_TL = inelasticFSs.find( ielement )->second->find ( tempLH.first/kelvin )->second;
373 vNEP_EPM_TH = inelasticFSs.find( ielement )->second->find ( tempLH.second/kelvin )->second;
374 }
375 else if ( tempLH.first == 0.0 )
376 {
377 std::map < G4double , std::vector< E_P_E_isoAng* >* >::iterator itm;
378 itm = inelasticFSs.find( ielement )->second->begin();
379 vNEP_EPM_TL = itm->second;
380 itm++;
381 vNEP_EPM_TH = itm->second;
382 }
383 else if ( tempLH.second == 0.0 )
384 {
385 std::map < G4double , std::vector< E_P_E_isoAng* >* >::iterator itm;
386 itm = inelasticFSs.find( ielement )->second->end();
387 itm--;
388 vNEP_EPM_TH = itm->second;
389 itm--;
390 vNEP_EPM_TL = itm->second;
391 }
392
393//
394
395 G4double rand_for_sE = G4UniformRand();
396
397 std::pair< G4double , E_isoAng > TL = create_sE_and_EPM_from_pE_and_vE_P_E_isoAng ( rand_for_sE , aTrack.GetKineticEnergy() , vNEP_EPM_TL );
398 std::pair< G4double , E_isoAng > TH = create_sE_and_EPM_from_pE_and_vE_P_E_isoAng ( rand_for_sE , aTrack.GetKineticEnergy() , vNEP_EPM_TH );
399
400 G4double sE;
401 sE = get_linear_interpolated ( aTemp , std::pair < G4double , G4double > ( tempLH.first , TL.first ) , std::pair < G4double , G4double > ( tempLH.second , TH.first ) );
402 E_isoAng anE_isoAng;
403 if ( TL.second.n == TH.second.n )
404 {
405 anE_isoAng.energy = sE;
406 anE_isoAng.n = TL.second.n;
407 for ( G4int i=0 ; i < anE_isoAng.n ; i++ )
408 {
409 G4double angle;
410 angle = get_linear_interpolated ( aTemp , std::pair< G4double , G4double > ( tempLH.first , TL.second.isoAngle[ i ] ) , std::pair< G4double , G4double > ( tempLH.second , TH.second.isoAngle[ i ] ) );
411 anE_isoAng.isoAngle.push_back( angle );
412 }
413 }
414 else
415 {
416 std::cout << "Do not Suuport yet." << std::endl;
417 }
418
419 //set
421 G4double mu = getMu( &anE_isoAng );
422 theParticleChange.SetMomentumChange( 0.0 , std::sqrt ( 1 - mu*mu ) , mu );
423
424 }
425 //else if ( random <= ( inelastic + theXSection->GetCoherentCrossSection( dp , (*theElementTable)[ ielement ] , aTemp ) ) / total )
426 else if ( random <= ( inelastic + theXSection->GetCoherentCrossSection( dp , theElement , theMaterial ) ) / total )
427 {
428 // Coherent Elastic
429
430 G4double E = aTrack.GetKineticEnergy();
431
432 // T_L and T_H
433 std::map < G4double , std::vector< std::pair< G4double , G4double >* >* >::iterator it;
434 std::vector<G4double> v_temp;
435 v_temp.clear();
436 for ( it = coherentFSs.find( ielement )->second->begin() ; it != coherentFSs.find( ielement )->second->end() ; it++ )
437 {
438 v_temp.push_back( it->first );
439 }
440
441// T_L T_H
442 std::pair < G4double , G4double > tempLH = find_LH ( aTemp , &v_temp );
443//
444//
445// For T_L anEPM_TL and T_H anEPM_TH
446//
447 std::vector< std::pair< G4double , G4double >* >* pvE_p_TL = 0;
448 std::vector< std::pair< G4double , G4double >* >* pvE_p_TH = 0;
449
450 if ( tempLH.first != 0.0 && tempLH.second != 0.0 )
451 {
452 pvE_p_TL = coherentFSs.find( ielement )->second->find ( tempLH.first/kelvin )->second;
453 pvE_p_TH = coherentFSs.find( ielement )->second->find ( tempLH.first/kelvin )->second;
454 }
455 else if ( tempLH.first == 0.0 )
456 {
457 pvE_p_TL = coherentFSs.find( ielement )->second->find ( v_temp[ 0 ] )->second;
458 pvE_p_TH = coherentFSs.find( ielement )->second->find ( v_temp[ 1 ] )->second;
459 }
460 else if ( tempLH.second == 0.0 )
461 {
462 pvE_p_TL = coherentFSs.find( ielement )->second->find ( v_temp.back() )->second;
463 std::vector< G4double >::iterator itv;
464 itv = v_temp.end();
465 itv--;
466 itv--;
467 pvE_p_TL = coherentFSs.find( ielement )->second->find ( *itv )->second;
468 }
469
470
471 std::vector< G4double > vE_T;
472 std::vector< G4double > vp_T;
473
474 G4int n1 = pvE_p_TL->size();
475 //G4int n2 = pvE_p_TH->size();
476
477 for ( G4int i=1 ; i < n1 ; i++ )
478 {
479 if ( (*pvE_p_TL)[i]->first != (*pvE_p_TH)[i]->first ) abort();
480 vE_T.push_back ( (*pvE_p_TL)[i]->first );
481 vp_T.push_back ( get_linear_interpolated ( aTemp , std::pair< G4double , G4double > ( tempLH.first , (*pvE_p_TL)[i]->second ) , std::pair< G4double , G4double > ( tempLH.second , (*pvE_p_TL)[i]->second ) ) );
482 }
483
484 G4int j = 0;
485 for ( G4int i = 1 ; i < n ; i++ )
486 {
487 if ( E/eV < vE_T[ i ] )
488 {
489 j = i-1;
490 break;
491 }
492 }
493
494 G4double rand_for_mu = G4UniformRand();
495
496 G4int k = 0;
497 for ( G4int i = 1 ; i < j ; i++ )
498 {
499 G4double Pi = vp_T[ i ] / vp_T[ j ];
500 if ( rand_for_mu < Pi )
501 {
502 k = i-1;
503 break;
504 }
505 }
506
507 //G4double Ei = vE_T[ j ];
508 G4double Ei = vE_T[ k ];
509
510 G4double mu = 1 - 2 * Ei / (E/eV) ;
511 //111102
512 if ( mu < -1.0 ) mu = -1.0;
513
515 theParticleChange.SetMomentumChange( 0.0 , std::sqrt ( 1 - mu*mu ) , mu );
516
517
518 }
519 else
520 {
521 // InCoherent Elastic
522
523 // T_L and T_H
524 std::map < G4double , std::vector < E_isoAng* >* >::iterator it;
525 std::vector<G4double> v_temp;
526 v_temp.clear();
527 for ( it = incoherentFSs.find( ielement )->second->begin() ; it != incoherentFSs.find( ielement )->second->end() ; it++ )
528 {
529 v_temp.push_back( it->first );
530 }
531
532// T_L T_H
533 std::pair < G4double , G4double > tempLH = find_LH ( aTemp , &v_temp );
534
535//
536// For T_L anEPM_TL and T_H anEPM_TH
537//
538
539 E_isoAng anEPM_TL_E;
540 E_isoAng anEPM_TH_E;
541
542 if ( tempLH.first != 0.0 && tempLH.second != 0.0 )
543 {
544 anEPM_TL_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( tempLH.first/kelvin )->second );
545 anEPM_TH_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( tempLH.second/kelvin )->second );
546 }
547 else if ( tempLH.first == 0.0 )
548 {
549 anEPM_TL_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( v_temp[ 0 ] )->second );
550 anEPM_TH_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( v_temp[ 1 ] )->second );
551 }
552 else if ( tempLH.second == 0.0 )
553 {
554 anEPM_TH_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( v_temp.back() )->second );
555 std::vector< G4double >::iterator itv;
556 itv = v_temp.end();
557 itv--;
558 itv--;
559 anEPM_TL_E = create_E_isoAng_from_energy ( aTrack.GetKineticEnergy() , incoherentFSs.find( ielement )->second->find ( *itv )->second );
560 }
561
562 // E_isoAng for aTemp and aTrack.GetKineticEnergy()
563 E_isoAng anEPM_T_E;
564
565 if ( anEPM_TL_E.n == anEPM_TH_E.n )
566 {
567 anEPM_T_E.n = anEPM_TL_E.n;
568 for ( G4int i=0 ; i < anEPM_TL_E.n ; i++ )
569 {
570 G4double angle;
571 angle = get_linear_interpolated ( aTemp , std::pair< G4double , G4double > ( tempLH.first , anEPM_TL_E.isoAngle[ i ] ) , std::pair< G4double , G4double > ( tempLH.second , anEPM_TH_E.isoAngle[ i ] ) );
572 anEPM_T_E.isoAngle.push_back( angle );
573 }
574 }
575 else
576 {
577 std::cout << "Do not Suuport yet." << std::endl;
578 }
579
580 // Decide mu
581 G4double mu = getMu ( &anEPM_T_E );
582
583 // Set Final State
584 theParticleChange.SetEnergyChange( aTrack.GetKineticEnergy() ); // No energy change in Elastic
585 theParticleChange.SetMomentumChange( 0.0 , std::sqrt ( 1 - mu*mu ) , mu );
586
587 }
588 delete dp;
589
590 return &theParticleChange;
591
592 }
593 else
594 {
595 // Not thermal element
596 // Neutron HP will handle
597 return theHPElastic -> ApplyYourself( aTrack, aNucleus );
598 }
599
600}
601
602
603
604G4double G4NeutronHPThermalScattering::getMu( E_isoAng* anEPM )
605{
606
607 G4double random = G4UniformRand();
608 G4double result = 0.0;
609
610 G4int in = int ( random * ( (*anEPM).n ) );
611
612 if ( in != 0 )
613 {
614 G4double mu_l = (*anEPM).isoAngle[ in-1 ];
615 G4double mu_h = (*anEPM).isoAngle[ in ];
616 result = ( mu_h - mu_l ) * ( random * ( (*anEPM).n ) - in ) + mu_l;
617 }
618 else
619 {
620 G4double x = random * (*anEPM).n;
621 G4double D = ( (*anEPM).isoAngle[ 0 ] - ( -1 ) ) + ( 1 - (*anEPM).isoAngle[ (*anEPM).n - 1 ] );
622 G4double ratio = ( (*anEPM).isoAngle[ 0 ] - ( -1 ) ) / D;
623 if ( x <= ratio )
624 {
625 G4double mu_l = -1;
626 G4double mu_h = (*anEPM).isoAngle[ 0 ];
627 result = ( mu_h - mu_l ) * x + mu_l;
628 }
629 else
630 {
631 G4double mu_l = (*anEPM).isoAngle[ (*anEPM).n - 1 ];
632 G4double mu_h = 1;
633 result = ( mu_h - mu_l ) * x + mu_l;
634 }
635 }
636 return result;
637}
638
639
640
641std::pair < G4double , G4double > G4NeutronHPThermalScattering::find_LH ( G4double x , std::vector< G4double >* aVector )
642{
643 G4double L = 0.0;
644 G4double H = 0.0;
645 std::vector< G4double >::iterator it;
646 for ( it = aVector->begin() ; it != aVector->end() ; it++ )
647 {
648 if ( x <= *it )
649 {
650 H = *it;
651 if ( it != aVector->begin() )
652 {
653 it--;
654 L = *it;
655 }
656 else
657 {
658 L = 0.0;
659 }
660 break;
661 }
662 }
663 if ( H == 0.0 )
664 L = aVector->back();
665
666 return std::pair < G4double , G4double > ( L , H );
667}
668
669
670
671G4double G4NeutronHPThermalScattering::get_linear_interpolated ( G4double x , std::pair< G4double , G4double > Low , std::pair< G4double , G4double > High )
672{
673 G4double y=0.0;
674 if ( High.first - Low.first != 0 )
675 y = ( High.second - Low.second ) / ( High.first - Low.first ) * ( x - Low.first ) + Low.second;
676 else
677 std::cout << "G4NeutronHPThermalScattering liner interpolation err!!" << std::endl;
678
679 return y;
680}
681
682
683
684E_isoAng G4NeutronHPThermalScattering::create_E_isoAng_from_energy ( G4double energy , std::vector< E_isoAng* >* vEPM )
685{
686 E_isoAng anEPM_T_E;
687
688 std::vector< E_isoAng* >::iterator iv;
689
690 std::vector< G4double > v_e;
691 v_e.clear();
692 for ( iv = vEPM->begin() ; iv != vEPM->end() ; iv++ )
693 v_e.push_back ( (*iv)->energy );
694
695 std::pair < G4double , G4double > energyLH = find_LH ( energy , &v_e );
696 //std::cout << " " << energy/eV << " " << energyLH.first/eV << " " << energyLH.second/eV << std::endl;
697
698 E_isoAng* panEPM_T_EL=0;
699 E_isoAng* panEPM_T_EH=0;
700
701 if ( energyLH.first != 0.0 && energyLH.second != 0.0 )
702 {
703 for ( iv = vEPM->begin() ; iv != vEPM->end() ; iv++ )
704 {
705 if ( energyLH.first == (*iv)->energy )
706 break;
707 }
708 panEPM_T_EL = *iv;
709 iv++;
710 panEPM_T_EH = *iv;
711 }
712 else if ( energyLH.first == 0.0 )
713 {
714 panEPM_T_EL = (*vEPM)[0];
715 panEPM_T_EH = (*vEPM)[1];
716 }
717 else if ( energyLH.second == 0.0 )
718 {
719 panEPM_T_EH = (*vEPM).back();
720 iv = vEPM->end();
721 iv--;
722 iv--;
723 panEPM_T_EL = *iv;
724 }
725
726 if ( panEPM_T_EL->n == panEPM_T_EH->n )
727 {
728 anEPM_T_E.energy = energy;
729 anEPM_T_E.n = panEPM_T_EL->n;
730
731 for ( G4int i=0 ; i < panEPM_T_EL->n ; i++ )
732 {
733 G4double angle;
734 angle = get_linear_interpolated ( energy , std::pair< G4double , G4double > ( energyLH.first , panEPM_T_EL->isoAngle[ i ] ) , std::pair< G4double , G4double > ( energyLH.second , panEPM_T_EH->isoAngle[ i ] ) );
735 anEPM_T_E.isoAngle.push_back( angle );
736 }
737 }
738 else
739 {
740 G4cout << "G4NeutronHPThermalScattering Do not Suuport yet." << G4endl;
741 }
742
743
744 return anEPM_T_E;
745}
746
747
748
749G4double G4NeutronHPThermalScattering::get_secondary_energy_from_E_P_E_isoAng ( G4double random , E_P_E_isoAng* anE_P_E_isoAng )
750{
751
752 G4double secondary_energy = 0.0;
753
754 G4int n = anE_P_E_isoAng->n;
755 G4double sum_p = 0.0; // sum_p_H
756 G4double sum_p_L = 0.0;
757
758 G4double total=0.0;
759
760/*
761 delete for speed up
762 for ( G4int i = 0 ; i < n-1 ; i++ )
763 {
764 G4double E_L = anE_P_E_isoAng->vE_isoAngle[i]->energy/eV;
765 G4double E_H = anE_P_E_isoAng->vE_isoAngle[i+1]->energy/eV;
766 G4double dE = E_H - E_L;
767 total += ( ( anE_P_E_isoAng->prob[i] ) * dE );
768 }
769
770 if ( std::abs( total - anE_P_E_isoAng->sum_of_probXdEs ) > 1.0e-14 ) std::cout << total - anE_P_E_isoAng->sum_of_probXdEs << std::endl;
771*/
772 total = anE_P_E_isoAng->sum_of_probXdEs;
773
774 for ( G4int i = 0 ; i < n-1 ; i++ )
775 {
776 G4double E_L = anE_P_E_isoAng->vE_isoAngle[i]->energy/eV;
777 G4double E_H = anE_P_E_isoAng->vE_isoAngle[i+1]->energy/eV;
778 G4double dE = E_H - E_L;
779 sum_p += ( ( anE_P_E_isoAng->prob[i] ) * dE );
780
781 if ( random <= sum_p/total )
782 {
783 secondary_energy = get_linear_interpolated ( random , std::pair < G4double , G4double > ( sum_p_L/total , E_L ) , std::pair < G4double , G4double > ( sum_p/total , E_H ) );
784 secondary_energy = secondary_energy*eV; //need eV
785 break;
786 }
787 sum_p_L = sum_p;
788 }
789
790 return secondary_energy;
791}
792
793
794
795std::pair< G4double , E_isoAng > G4NeutronHPThermalScattering::create_sE_and_EPM_from_pE_and_vE_P_E_isoAng ( G4double rand_for_sE , G4double pE , std::vector < E_P_E_isoAng* >* vNEP_EPM )
796{
797
798 std::map< G4double , G4int > map_energy;
799 map_energy.clear();
800 std::vector< G4double > v_energy;
801 v_energy.clear();
802 std::vector< E_P_E_isoAng* >::iterator itv;
803 G4int i = 0;
804 for ( itv = vNEP_EPM->begin(); itv != vNEP_EPM->end(); itv++ )
805 {
806 v_energy.push_back( (*itv)->energy );
807 map_energy.insert( std::pair < G4double , G4int > ( (*itv)->energy , i ) );
808 i++;
809 }
810
811 std::pair < G4double , G4double > energyLH = find_LH ( pE , &v_energy );
812
813 E_P_E_isoAng* pE_P_E_isoAng_EL = 0;
814 E_P_E_isoAng* pE_P_E_isoAng_EH = 0;
815
816 if ( energyLH.first != 0.0 && energyLH.second != 0.0 )
817 {
818 pE_P_E_isoAng_EL = (*vNEP_EPM)[ map_energy.find ( energyLH.first )->second ];
819 pE_P_E_isoAng_EH = (*vNEP_EPM)[ map_energy.find ( energyLH.second )->second ];
820 }
821 else if ( energyLH.first == 0.0 )
822 {
823 pE_P_E_isoAng_EL = (*vNEP_EPM)[ 0 ];
824 pE_P_E_isoAng_EH = (*vNEP_EPM)[ 1 ];
825 }
826 if ( energyLH.second == 0.0 )
827 {
828 pE_P_E_isoAng_EH = (*vNEP_EPM).back();
829 itv = vNEP_EPM->end();
830 itv--;
831 itv--;
832 pE_P_E_isoAng_EL = *itv;
833 }
834
835
836 G4double sE;
837 G4double sE_L;
838 G4double sE_H;
839
840
841 sE_L = get_secondary_energy_from_E_P_E_isoAng ( rand_for_sE , pE_P_E_isoAng_EL );
842 sE_H = get_secondary_energy_from_E_P_E_isoAng ( rand_for_sE , pE_P_E_isoAng_EH );
843
844 sE = get_linear_interpolated ( pE , std::pair < G4double , G4double > ( energyLH.first , sE_L ) , std::pair < G4double , G4double > ( energyLH.second , sE_H ) );
845
846
847 E_isoAng E_isoAng_L = create_E_isoAng_from_energy ( sE , &(pE_P_E_isoAng_EL->vE_isoAngle) );
848 E_isoAng E_isoAng_H = create_E_isoAng_from_energy ( sE , &(pE_P_E_isoAng_EH->vE_isoAngle) );
849
850 E_isoAng anE_isoAng;
851 if ( E_isoAng_L.n == E_isoAng_H.n )
852 {
853 anE_isoAng.n = E_isoAng_L.n;
854 for ( G4int j=0 ; j < anE_isoAng.n ; j++ )
855 {
856 G4double angle;
857 angle = get_linear_interpolated ( sE , std::pair< G4double , G4double > ( sE_L , E_isoAng_L.isoAngle[ j ] ) , std::pair< G4double , G4double > ( sE_H , E_isoAng_H.isoAngle[ j ] ) );
858 anE_isoAng.isoAngle.push_back( angle );
859 }
860 }
861 else
862 {
863 std::cout << "Do not Suuport yet." << std::endl;
864 }
865
866
867
868 return std::pair< G4double , E_isoAng >( sE , anE_isoAng);
869}
870
871void G4NeutronHPThermalScattering::buildPhysicsTable()
872{
873
874 dic.clear();
875 std::map < G4String , G4int > co_dic;
876
877 //Searching Nist Materials
878 static const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
879 size_t numberOfMaterials = G4Material::GetNumberOfMaterials();
880 for ( size_t i = 0 ; i < numberOfMaterials ; i++ )
881 {
882 G4Material* material = (*theMaterialTable)[i];
883 size_t numberOfElements = material->GetNumberOfElements();
884 for ( size_t j = 0 ; j < numberOfElements ; j++ )
885 {
886 const G4Element* element = material->GetElement(j);
887 if ( names.IsThisThermalElement ( material->GetName() , element->GetName() ) )
888 {
889 G4int ts_ID_of_this_geometry;
890 G4String ts_ndl_name = names.GetTS_NDL_Name( material->GetName() , element->GetName() );
891 if ( co_dic.find ( ts_ndl_name ) != co_dic.end() )
892 {
893 ts_ID_of_this_geometry = co_dic.find ( ts_ndl_name ) -> second;
894 }
895 else
896 {
897 ts_ID_of_this_geometry = co_dic.size();
898 co_dic.insert ( std::pair< G4String , G4int >( ts_ndl_name , ts_ID_of_this_geometry ) );
899 }
900
901 //G4cout << "Neutron HP Thermal Scattering: Registering a material-element pair of "
902 // << material->GetName() << " " << element->GetName()
903 // << " as internal thermal scattering id of " << ts_ID_of_this_geometry << "." << G4endl;
904
905 dic.insert( std::pair < std::pair < G4Material* , const G4Element* > , G4int > ( std::pair < G4Material* , const G4Element* > ( material , element ) , ts_ID_of_this_geometry ) );
906 }
907 }
908 }
909
910 //Searching TS Elements
911 static const G4ElementTable* theElementTable = G4Element::GetElementTable();
912 size_t numberOfElements = G4Element::GetNumberOfElements();
913 //size_t numberOfThermalElements = 0;
914 for ( size_t i = 0 ; i < numberOfElements ; i++ )
915 {
916 const G4Element* element = (*theElementTable)[i];
917 if ( names.IsThisThermalElement ( element->GetName() ) )
918 {
919 if ( names.IsThisThermalElement ( element->GetName() ) )
920 {
921 G4int ts_ID_of_this_geometry;
922 G4String ts_ndl_name = names.GetTS_NDL_Name( element->GetName() );
923 if ( co_dic.find ( ts_ndl_name ) != co_dic.end() )
924 {
925 ts_ID_of_this_geometry = co_dic.find ( ts_ndl_name ) -> second;
926 }
927 else
928 {
929 ts_ID_of_this_geometry = co_dic.size();
930 co_dic.insert ( std::pair< G4String , G4int >( ts_ndl_name , ts_ID_of_this_geometry ) );
931 }
932
933 //G4cout << "Neutron HP Thermal Scattering: Registering an element of "
934 // << material->GetName() << " " << element->GetName()
935 // << " as internal thermal scattering id of " << ts_ID_of_this_geometry << "." << G4endl;
936
937 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 ) );
938 }
939 }
940 }
941
942 G4cout << G4endl;
943 G4cout << "Neutron HP Thermal Scattering: Following material-element pairs or elements are registered." << G4endl;
944 for ( std::map < std::pair < const G4Material* , const G4Element* > , G4int >::iterator it = dic.begin() ; it != dic.end() ; it++ )
945 {
946 if ( it->first.first != NULL )
947 {
948 G4cout << "Material " << it->first.first->GetName() << " - Element " << it->first.second->GetName() << ", internal thermal scattering id " << it->second << G4endl;
949 }
950 else
951 {
952 G4cout << "Element " << it->first.second->GetName() << ", internal thermal scattering id " << it->second << G4endl;
953 }
954 }
955 G4cout << G4endl;
956
957 // Read Cross Section Data files
958
959 G4String dirName;
960 if ( !getenv( "G4NEUTRONHPDATA" ) )
961 throw G4HadronicException(__FILE__, __LINE__, "Please setenv G4NEUTRONHPDATA to point to the neutron cross-section files.");
962 dirName = getenv( "G4NEUTRONHPDATA" );
963
964 //dirName = baseName + "/ThermalScattering";
965
966 G4String name;
967
968 for ( std::map < G4String , G4int >::iterator it = co_dic.begin() ; it != co_dic.end() ; it++ )
969 {
970 G4String tsndlName = it->first;
971 G4int ts_ID = it->second;
972
973 // Coherent
974 G4String fsName = "/ThermalScattering/Coherent/FS/";
975 G4String fileName = dirName + fsName + tsndlName;
976 coherentFSs.insert ( std::pair < G4int , std::map < G4double , std::vector < std::pair< G4double , G4double >* >* >* > ( ts_ID , readACoherentFSDATA( fileName ) ) );
977
978 // incoherent elastic
979 fsName = "/ThermalScattering/Incoherent/FS/";
980 fileName = dirName + fsName + tsndlName;
981 incoherentFSs.insert ( std::pair < G4int , std::map < G4double , std::vector < E_isoAng* >* >* > ( ts_ID , readAnIncoherentFSDATA( fileName ) ) );
982
983 // inelastic
984 fsName = "/ThermalScattering/Inelastic/FS/";
985 fileName = dirName + fsName + tsndlName;
986 inelasticFSs.insert ( std::pair < G4int , std::map < G4double , std::vector < E_P_E_isoAng* >* >* > ( ts_ID , readAnInelasticFSDATA( fileName ) ) );
987 }
988}
989
990
991G4int G4NeutronHPThermalScattering::getTS_ID ( const G4Material* material , const G4Element* element )
992{
993 G4int result = -1;
994 if ( dic.find( std::pair < const G4Material* , const G4Element* > ( material , element ) ) != dic.end() )
995 result = dic.find( std::pair < const G4Material* , const G4Element* > ( material , element ) )->second;
996 return result;
997}
998
999const std::pair<G4double, G4double> G4NeutronHPThermalScattering::GetFatalEnergyCheckLevels() const
1000{
1001 //return std::pair<G4double, G4double>(10*perCent,10*GeV);
1002 return std::pair<G4double, G4double>(10*perCent,DBL_MAX);
1003}
std::vector< G4Element * > G4ElementTable
std::vector< G4Material * > G4MaterialTable
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
G4double GetZ() const
Definition: G4Element.hh:131
static size_t GetNumberOfElements()
Definition: G4Element.cc:406
const G4String & GetName() const
Definition: G4Element.hh:127
static const G4ElementTable * GetElementTable()
Definition: G4Element.cc:399
void SetEnergyChange(G4double anEnergy)
void SetMomentumChange(const G4ThreeVector &aV)
const G4Material * GetMaterial() const
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
void SetMinEnergy(G4double anEnergy)
void SetMaxEnergy(const G4double anEnergy)
static const G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:562
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:569
G4double GetTemperature() const
Definition: G4Material.hh:181
const G4Element * GetElement(G4int iel) const
Definition: G4Material.hh:201
size_t GetNumberOfElements() const
Definition: G4Material.hh:185
const G4String & GetName() const
Definition: G4Material.hh:177
G4double GetInelasticCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
void BuildPhysicsTable(const G4ParticleDefinition &)
G4double GetCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
G4double GetCoherentCrossSection(const G4DynamicParticle *, const G4Element *, const G4Material *)
G4String GetTS_NDL_Name(G4String nameG4Element)
virtual const std::pair< G4double, G4double > GetFatalEnergyCheckLevels() const
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &aTargetNucleus)
static G4Neutron * Neutron()
Definition: G4Neutron.cc:104
G4int GetZ_asInt() const
Definition: G4Nucleus.hh:115
G4int first(char) const
std::vector< G4double > prob
std::vector< E_isoAng * > vE_isoAngle
std::vector< G4double > isoAngle
#define DBL_MAX
Definition: templates.hh:83