Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ParticleHPContAngularPar.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// neutron_hp -- source file
27// J.P. Wellisch, Nov-1996
28// A prototype of the low energy neutron transport model.
29//
30// 09-May-06 fix in Sample by T. Koi
31// 080318 Fix Compilation warnings - gcc-4.3.0 by T. Koi
32// (This fix has a real effect to the code.)
33// 080409 Fix div0 error with G4FPE by T. Koi
34// 080612 Fix contribution from Benoit Pirard and Laurent Desorgher (Univ. Bern) #1
35// 080714 Limiting the sum of energy of secondary particles by T. Koi
36// 080801 Fix div0 error wiht G4FPE and memory leak by T. Koi
37// 081024 G4NucleiPropertiesTable:: to G4NucleiProperties::
38//
39// P. Arce, June-2014 Conversion neutron_hp to particle_hp
40//
41// June-2019 - E. Mendoza --> redefinition of the residual mass to consider incident particles different than neutrons.
42
45#include "G4SystemOfUnits.hh"
47#include "G4Gamma.hh"
48#include "G4Electron.hh"
49#include "G4Positron.hh"
50#include "G4Neutron.hh"
51#include "G4Proton.hh"
52#include "G4Deuteron.hh"
53#include "G4Triton.hh"
54#include "G4He3.hh"
55#include "G4Alpha.hh"
56#include "G4ParticleHPVector.hh"
57#include "G4NucleiProperties.hh"
59#include "G4IonTable.hh"
61#include <set>
62#include <vector>
63
65{
66 theAngular = 0;
67 if (fCache.Get() == 0) cacheInit();
68 fCache.Get()->currentMeanEnergy = -2;
69 fCache.Get()->fresh = true;
70 adjustResult = true;
71 if (G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState() )
72 adjustResult = false;
73
74 theMinEner = DBL_MAX;
75 theMaxEner = -DBL_MAX;
76 theProjectile = projectile;
77
78 theEnergy = 0.0;
79 nEnergies = 0;
80 nDiscreteEnergies = 0;
81 nAngularParameters = 0;
82}
83
84
85void
86G4ParticleHPContAngularPar::Init(std::istream& aDataFile, G4ParticleDefinition* projectile)
87{
88 adjustResult = true;
89 if (G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState() )
90 adjustResult = false;
91
92 theProjectile = projectile;
93
94 aDataFile >> theEnergy >> nEnergies >> nDiscreteEnergies >> nAngularParameters;
95 theEnergy *= eV;
96 theAngular = new G4ParticleHPList [nEnergies];
97 G4double sEnergy;
98 for (G4int i = 0; i < nEnergies; i++) {
99 aDataFile >> sEnergy;
100 sEnergy *= eV;
101 theAngular[i].SetLabel(sEnergy);
102 theAngular[i].Init(aDataFile, nAngularParameters, 1.);
103 theMinEner = std::min(theMinEner,sEnergy);
104 theMaxEner = std::max(theMaxEner,sEnergy);
105 }
106}
107
108
111 G4double /*targetMass*/,
112 G4int angularRep, G4int /*interpolE*/ )
113{
114 // The following line is needed because it may change between runs by UI command
115 if (G4ParticleHPManager::GetInstance()->GetDoNotAdjustFinalState() )
116 adjustResult = false;
117
118 if (fCache.Get() == 0 ) cacheInit();
120 G4int Z = static_cast<G4int>(massCode/1000);
121 G4int A = static_cast<G4int>(massCode-1000*Z);
122 if (massCode == 0) {
123 result->SetDefinition(G4Gamma::Gamma());
124 } else if (A == 0) {
126 if (Z == 1) result->SetDefinition(G4Positron::Positron());
127 } else if (A == 1) {
129 if (Z == 1) result->SetDefinition(G4Proton::Proton());
130 } else if (A == 2) {
132 } else if (A == 3) {
134 if(Z == 2) result->SetDefinition(G4He3::He3());
135 } else if (A == 4) {
136 result->SetDefinition(G4Alpha::Alpha());
137 if (Z != 2) throw G4HadronicException(__FILE__, __LINE__,
138 "G4ParticleHPContAngularPar: Unknown ion case 1");
139 } else {
140 result->SetDefinition(G4IonTable::GetIonTable()->GetIon(Z,A,0) );
141 }
142
143 G4int i(0);
144 G4int it(0);
145 G4double fsEnergy(0);
146 G4double cosTh(0);
147
148 if (angularRep == 1) {
149 if (nDiscreteEnergies != 0) {
150 // 1st check remaining_energy
151 // if this is the first set it. (How?)
152 if (fCache.Get()->fresh == true) {
153 // Discrete Lines, larger energies come first
154 // Continues Emssions, low to high LAST
155 fCache.Get()->remaining_energy = std::max (theAngular[0].GetLabel(),
156 theAngular[nEnergies-1].GetLabel() );
157 fCache.Get()->fresh = false;
158 }
159
160 // Cheating for small remaining_energy
161 // Temporary solution
162 if (nDiscreteEnergies == nEnergies) {
163 fCache.Get()->remaining_energy = std::max(fCache.Get()->remaining_energy,
164 theAngular[nDiscreteEnergies-1].GetLabel() ); //Minimum Line
165 } else {
166 G4double cont_min = 0.0;
167 for (G4int j = nDiscreteEnergies; j < nEnergies; j++) {
168 cont_min = theAngular[j].GetLabel();
169 if (theAngular[j].GetValue(0) != 0.0 ) break;
170 }
171 fCache.Get()->remaining_energy =
172 std::max (fCache.Get()->remaining_energy,
173 std::min(theAngular[nDiscreteEnergies-1].GetLabel(), cont_min) ); //Minimum Line or grid
174 }
175
176 G4double random = G4UniformRand();
177 G4double* running = new G4double[nEnergies+1];
178 running[0] = 0.0;
179
180 G4double delta;
181 for (G4int j = 0; j < nDiscreteEnergies; j++) {
182 delta = 0.0;
183 if (theAngular[j].GetLabel() <= fCache.Get()->remaining_energy)
184 delta = theAngular[j].GetValue(0);
185 running[j+1] = running[j] + delta;
186 }
187
188 G4double tot_prob_DIS = std::max( running[nDiscreteEnergies], 0.0 );
189
190 G4double delta1;
191 for (G4int j = nDiscreteEnergies; j < nEnergies; j++) {
192 delta1 = 0.0;
193 G4double e_low = 0.0;
194 G4double e_high = 0.0;
195 if (theAngular[j].GetLabel() <= fCache.Get()->remaining_energy)
196 delta1 = theAngular[j].GetValue(0);
197
198 // To calculate Prob. e_low and e_high should be in eV
199 // There are two cases:
200 // 1: theAngular[nDiscreteEnergies].GetLabel() != 0.0
201 // delta1 should be used between j-1 and j
202 // At j = nDiscreteEnergies (the first) e_low should be set explicitly
203 if (theAngular[j].GetLabel() != 0) {
204 if (j == nDiscreteEnergies) {
205 e_low = 0.0/eV;
206 } else {
207 if ( j < 1 ) j = 1; // Protection against evaluation of arrays at index j-1
208 e_low = theAngular[j-1].GetLabel()/eV;
209 }
210 e_high = theAngular[j].GetLabel()/eV;
211 }
212
213 // 2: theAngular[nDiscreteEnergies].GetLabel() == 0.0
214 // delta1 should be used between j and j+1
215 if (theAngular[j].GetLabel() == 0.0) {
216 e_low = theAngular[j].GetLabel()/eV;
217 if (j != nEnergies-1) {
218 e_high = theAngular[j+1].GetLabel()/eV;
219 } else {
220 e_high = theAngular[j].GetLabel()/eV;
221 if (theAngular[j].GetValue(0) != 0.0) {
222 throw G4HadronicException(__FILE__, __LINE__,
223 "G4ParticleHPContAngularPar: Unexpected non zero value of theAngular[nEnergies-1].GetValue(0)");
224 }
225 }
226 }
227
228 running[j+1] = running[j] + ( ( e_high - e_low ) * delta1);
229 }
230 G4double tot_prob_CON = std::max( running[ nEnergies ] - running[ nDiscreteEnergies ], 0.0 );
231
232 // Give up in the pathological case of null probabilities
233 if ( tot_prob_DIS == 0.0 && tot_prob_CON == 0.0 ) return result;
234
235 // Normalize random
236 random *= (tot_prob_DIS + tot_prob_CON);
237 // 2nd Judge Discrete or not
238
239 // This should be relatively close to 1 For safty
240 if (random <= (tot_prob_DIS/(tot_prob_DIS + tot_prob_CON) ) || nDiscreteEnergies == nEnergies) {
241 // Discrete Emission
242 for (G4int j = 0; j < nDiscreteEnergies; j++) {
243 // Here we should use i+1
244 if (random < running[ j+1 ] ) {
245 it = j;
246 break;
247 }
248 }
249 fsEnergy = theAngular[ it ].GetLabel();
250
251 G4ParticleHPLegendreStore theStore(1);
252 theStore.Init(0,fsEnergy,nAngularParameters);
253 for (G4int j = 0; j < nAngularParameters; j++) {
254 theStore.SetCoeff(0,j,theAngular[it].GetValue(j));
255 }
256 // use it to sample.
257 cosTh = theStore.SampleMax(fsEnergy);
258 // Done
259
260 } else {
261 // Continuous emission
262 for (G4int j = nDiscreteEnergies; j < nEnergies; j++) {
263 // Here we should use i
264 if (random < running[ j ] ) {
265 it = j;
266 break;
267 }
268 }
269
270 if ( it < 1 ) it = 1; // Protection against evaluation of arrays at index it-1
271
272 G4double x1 = running[it-1];
273 G4double x2 = running[it];
274
275 G4double y1 = 0.0;
276 if (it != nDiscreteEnergies) y1 = theAngular[it-1].GetLabel();
277 G4double y2 = theAngular[it].GetLabel();
278
279 fsEnergy = theInt.Interpolate(theManager.GetInverseScheme(it),
280 random,x1,x2,y1,y2);
281
282 G4ParticleHPLegendreStore theStore(2);
283 theStore.Init(0, y1, nAngularParameters);
284 theStore.Init(1, y2, nAngularParameters);
285 theStore.SetManager(theManager);
286 G4int itt;
287 for (G4int j = 0; j < nAngularParameters; j++) {
288 itt = it;
289 if (it == nDiscreteEnergies) itt = it+1;
290 // "This case "it-1" has data for Discrete, so we will use an extrpolated values it and it+1
291 theStore.SetCoeff(0, j, theAngular[itt-1].GetValue(j) );
292 theStore.SetCoeff(1, j, theAngular[itt].GetValue(j) );
293 }
294 // use it to sample.
295 cosTh = theStore.SampleMax(fsEnergy);
296
297 //Done
298 }
299
300 // The remaining energy needs to be lowered by the photon energy in *any* case.
301 // Otherwise additional photons with too high energy will be produced - therefore the
302 // adjustResult condition has been removed
303 fCache.Get()->remaining_energy -= fsEnergy;
304 delete[] running;
305
306 // end (nDiscreteEnergies != 0) branch
307
308 } else {
309 // Only continue, TK will clean up
310 if (fCache.Get()->fresh == true) {
311 fCache.Get()->remaining_energy = theAngular[ nEnergies-1 ].GetLabel();
312 fCache.Get()->fresh = false;
313 }
314
315 G4double random = G4UniformRand();
316 G4double* running = new G4double[nEnergies];
317 running[0] = 0;
318 G4double weighted = 0;
319 for (i = 1; i < nEnergies; i++) {
320 running[i]=running[i-1];
321 if (fCache.Get()->remaining_energy >= theAngular[i].GetLabel() ) {
322 running[i] += theInt.GetBinIntegral(theManager.GetScheme(i-1),
323 theAngular[i-1].GetLabel(),
324 theAngular[i].GetLabel(),
325 theAngular[i-1].GetValue(0),
326 theAngular[i].GetValue(0) );
327 weighted += theInt.GetWeightedBinIntegral(theManager.GetScheme(i-1),
328 theAngular[i-1].GetLabel(),
329 theAngular[i].GetLabel(),
330 theAngular[i-1].GetValue(0),
331 theAngular[i].GetValue(0));
332 }
333 }
334
335 // Cache the mean energy in this distribution
336 if (nEnergies == 1 || running[nEnergies-1] == 0) {
337 fCache.Get()->currentMeanEnergy = 0.0;
338 } else {
339 fCache.Get()->currentMeanEnergy = weighted/running[nEnergies-1];
340 }
341
342 if (nEnergies == 1) it = 0;
343 if (running[nEnergies-1] != 0) {
344 for (i = 1; i < nEnergies; i++) {
345 it = i;
346 if (random < running [i]/running[nEnergies-1] ) break;
347 }
348 }
349
350 if (running[nEnergies-1] == 0) it = 0;
351 if (it < nDiscreteEnergies || it == 0) {
352 if (it == 0) {
353 fsEnergy = theAngular[it].GetLabel();
354 G4ParticleHPLegendreStore theStore(1);
355 theStore.Init(0,fsEnergy,nAngularParameters);
356 for (i = 0; i < nAngularParameters; i++) {
357 theStore.SetCoeff(0, i, theAngular[it].GetValue(i) );
358 }
359 // use it to sample.
360 cosTh = theStore.SampleMax(fsEnergy);
361
362 } else {
363 G4double e1, e2;
364 e1 = theAngular[it-1].GetLabel();
365 e2 = theAngular[it].GetLabel();
366 fsEnergy = theInt.Interpolate(theManager.GetInverseScheme(it),
367 random,
368 running[it-1]/running[nEnergies-1],
369 running[it]/running[nEnergies-1],
370 e1, e2);
371 // fill a Legendrestore
372 G4ParticleHPLegendreStore theStore(2);
373 theStore.Init(0,e1,nAngularParameters);
374 theStore.Init(1,e2,nAngularParameters);
375 for (i = 0; i < nAngularParameters; i++) {
376 theStore.SetCoeff(0, i, theAngular[it-1].GetValue(i) );
377 theStore.SetCoeff(1, i, theAngular[it].GetValue(i) );
378 }
379 // use it to sample.
380 theStore.SetManager(theManager);
381 cosTh = theStore.SampleMax(fsEnergy);
382 }
383
384 } else { // continuum contribution
385 G4double x1 = running[it-1]/running[nEnergies-1];
386 G4double x2 = running[it]/running[nEnergies-1];
387 G4double y1 = theAngular[it-1].GetLabel();
388 G4double y2 = theAngular[it].GetLabel();
389 fsEnergy = theInt.Interpolate(theManager.GetInverseScheme(it),
390 random,x1,x2,y1,y2);
391 G4ParticleHPLegendreStore theStore(2);
392 theStore.Init(0,y1,nAngularParameters);
393 theStore.Init(1,y2,nAngularParameters);
394 theStore.SetManager(theManager);
395 for (i = 0; i < nAngularParameters; i++) {
396 theStore.SetCoeff(0, i, theAngular[it-1].GetValue(i));
397 theStore.SetCoeff(1, i, theAngular[it].GetValue(i));
398 }
399 // use it to sample.
400 cosTh = theStore.SampleMax(fsEnergy);
401 }
402 delete [] running;
403
404 // The remaining energy needs to be lowered by the photon energy in
405 // *any* case. Otherwise additional photons with too much energy will be
406 // produced - therefore the adjustResult condition has been removed
407
408 fCache.Get()->remaining_energy -= fsEnergy;
409 // end if (nDiscreteEnergies != 0)
410 }
411 // end of (angularRep == 1) branch
412
413 } else if (angularRep == 2) {
414 // first get the energy (already the right for this incoming energy)
415 G4int j;
416 G4double* running = new G4double[nEnergies];
417 running[0] = 0;
418 G4double weighted = 0;
419 for (j = 1; j < nEnergies; j++) {
420 if (j != 0) running[j] = running[j-1];
421 running[j] += theInt.GetBinIntegral(theManager.GetScheme(j-1),
422 theAngular[j-1].GetLabel(), theAngular[j].GetLabel(),
423 theAngular[j-1].GetValue(0), theAngular[j].GetValue(0));
424 weighted += theInt.GetWeightedBinIntegral(theManager.GetScheme(j-1),
425 theAngular[j-1].GetLabel(), theAngular[j].GetLabel(),
426 theAngular[j-1].GetValue(0), theAngular[j].GetValue(0));
427 }
428
429 // Cache the mean energy in this distribution
430 if (nEnergies == 1)
431 fCache.Get()->currentMeanEnergy = 0.0;
432 else
433 fCache.Get()->currentMeanEnergy = weighted/running[nEnergies-1];
434
435 G4int itt(0);
436 G4double randkal = G4UniformRand();
437 for (j = 1; j < nEnergies; j++) {
438 itt = j;
439 if (randkal < running[j]/running[nEnergies-1] ) break;
440 }
441
442 // Interpolate the secondary energy
443 G4double x, x1, x2, y1, y2;
444 if (itt == 0) itt = 1;
445 x = randkal*running[nEnergies-1];
446 x1 = running[itt-1];
447 x2 = running[itt];
448 G4double compoundFraction;
449 // interpolate energy
450 y1 = theAngular[itt-1].GetLabel();
451 y2 = theAngular[itt].GetLabel();
452 fsEnergy = theInt.Interpolate(theManager.GetInverseScheme(itt-1),
453 x, x1, x2, y1, y2);
454
455 // For theta, interpolate the compoundFractions
456 G4double cLow = theAngular[itt-1].GetValue(1);
457 G4double cHigh = theAngular[itt].GetValue(1);
458 compoundFraction = theInt.Interpolate(theManager.GetScheme(itt),
459 fsEnergy, y1, y2, cLow, cHigh);
460
461 if (compoundFraction > 1.0) compoundFraction = 1.0; // Protection against unphysical interpolation
462
463 delete [] running;
464
465 // get cosTh
466 G4double incidentEnergy = anEnergy;
467 G4double incidentMass = theProjectile->GetPDGMass();
468 G4double productEnergy = fsEnergy;
469 G4double productMass = result->GetMass();
470 G4int targetZ = G4int(fCache.Get()->theTargetCode/1000);
471 G4int targetA = G4int(fCache.Get()->theTargetCode-1000*targetZ);
472
473 // To correspond to natural composition (-nat-) data files.
474 if (targetA == 0)
475 targetA = G4int ( fCache.Get()->theTarget->GetMass()/amu_c2 + 0.5 );
476 G4double targetMass = fCache.Get()->theTarget->GetMass();
477 G4int incidentA=G4int(incidentMass/amu_c2 + 0.5 );
478 G4int incidentZ=G4int(theProjectile->GetPDGCharge()+ 0.5 );
479 G4int residualA = targetA+incidentA-A;
480 G4int residualZ = targetZ+incidentZ-Z;
481 G4double residualMass =G4NucleiProperties::GetNuclearMass( residualA , residualZ );
482 G4ParticleHPKallbachMannSyst theKallbach(compoundFraction,
483 incidentEnergy, incidentMass,
484 productEnergy, productMass,
485 residualMass, residualA, residualZ,
486 targetMass, targetA, targetZ,
487 incidentA,incidentZ,A,Z);
488 cosTh = theKallbach.Sample(anEnergy);
489 // end (angularRep == 2) branch
490
491 } else if (angularRep > 10 && angularRep < 16) {
492 G4double random = G4UniformRand();
493 G4double* running = new G4double[nEnergies];
494 running[0]=0;
495 G4double weighted = 0;
496 for (i = 1; i < nEnergies; i++) {
497 if (i != 0) running[i] = running[i-1];
498 running[i] += theInt.GetBinIntegral(theManager.GetScheme(i-1),
499 theAngular[i-1].GetLabel(), theAngular[i].GetLabel(),
500 theAngular[i-1].GetValue(0), theAngular[i].GetValue(0));
501 weighted += theInt.GetWeightedBinIntegral(theManager.GetScheme(i-1),
502 theAngular[i-1].GetLabel(), theAngular[i].GetLabel(),
503 theAngular[i-1].GetValue(0), theAngular[i].GetValue(0));
504 }
505
506 // Cache the mean energy in this distribution
507 if (nEnergies == 1)
508 fCache.Get()->currentMeanEnergy = 0.0;
509 else
510 fCache.Get()->currentMeanEnergy = weighted/running[nEnergies-1];
511
512 if (nEnergies == 1) it = 0;
513 for (i = 1; i < nEnergies; i++) {
514 it = i;
515 if(random<running[i]/running[nEnergies-1]) break;
516 }
517
518 if (it < nDiscreteEnergies || it == 0) {
519 if (it == 0) {
520 fsEnergy = theAngular[0].GetLabel();
521 G4ParticleHPVector theStore;
522 G4int aCounter = 0;
523 for (G4int j=1; j<nAngularParameters; j+=2) {
524 theStore.SetX(aCounter, theAngular[0].GetValue(j));
525 theStore.SetY(aCounter, theAngular[0].GetValue(j+1));
526 aCounter++;
527 }
529 aMan.Init(angularRep-10, nAngularParameters-1);
530 theStore.SetInterpolationManager(aMan);
531 cosTh = theStore.Sample();
532 } else {
533 fsEnergy = theAngular[it].GetLabel();
534 G4ParticleHPVector theStore;
536 aMan.Init(angularRep-10, nAngularParameters-1);
537 theStore.SetInterpolationManager(aMan); // Store interpolates f(costh)
538 G4InterpolationScheme currentScheme = theManager.GetInverseScheme(it);
539 G4int aCounter = 0;
540 for (G4int j=1; j<nAngularParameters; j+=2) {
541 theStore.SetX(aCounter, theAngular[it].GetValue(j));
542 theStore.SetY(aCounter,
543 theInt.Interpolate(currentScheme, random,
544 running[it-1]/running[nEnergies-1],
545 running[it]/running[nEnergies-1],
546 theAngular[it-1].GetValue(j+1),
547 theAngular[it].GetValue(j+1) ) );
548 aCounter++;
549 }
550 cosTh = theStore.Sample();
551 }
552
553 } else {
554 G4double x1 = running[it-1]/running[nEnergies-1];
555 G4double x2 = running[it]/running[nEnergies-1];
556 G4double y1 = theAngular[it-1].GetLabel();
557 G4double y2 = theAngular[it].GetLabel();
558 fsEnergy = theInt.Interpolate(theManager.GetInverseScheme(it),
559 random,x1,x2,y1,y2);
560 G4ParticleHPVector theBuff1;
561 G4ParticleHPVector theBuff2;
563 aMan.Init(angularRep-10, nAngularParameters-1);
564
565 G4int j;
566 for (i = 0, j = 1; i < nAngularParameters; i++, j+=2) {
567 theBuff1.SetX(i, theAngular[it-1].GetValue(j));
568 theBuff1.SetY(i, theAngular[it-1].GetValue(j+1));
569 theBuff2.SetX(i, theAngular[it].GetValue(j));
570 theBuff2.SetY(i, theAngular[it].GetValue(j+1));
571 }
572
573 G4ParticleHPVector theStore;
574 theStore.SetInterpolationManager(aMan); // Store interpolates f(costh)
575 x1 = y1;
576 x2 = y2;
577 G4double x, y;
578 for (i = 0; i < theBuff1.GetVectorLength(); i++) {
579 x = theBuff1.GetX(i); // costh binning identical
580 y1 = theBuff1.GetY(i);
581 y2 = theBuff2.GetY(i);
582 y = theInt.Interpolate(theManager.GetScheme(it),
583 fsEnergy, theAngular[it-1].GetLabel(),
584 theAngular[it].GetLabel(), y1, y2);
585 theStore.SetX(i, x);
586 theStore.SetY(i, y);
587 }
588 cosTh = theStore.Sample();
589 }
590 delete [] running;
591
592 } else {
593 throw G4HadronicException(__FILE__, __LINE__,
594 "G4ParticleHPContAngularPar::Sample: Unknown angular representation");
595 }
596
597 result->SetKineticEnergy(fsEnergy);
598 G4double phi = twopi*G4UniformRand();
599 G4double theta = std::acos(cosTh);
600 G4double sinth = std::sin(theta);
601 G4double mtot = result->GetTotalMomentum();
602 G4ThreeVector tempVector(mtot*sinth*std::cos(phi), mtot*sinth*std::sin(phi), mtot*std::cos(theta) );
603 result->SetMomentum(tempVector);
604 return result;
605}
606
607
608#define MERGE_NEW
609
611{
612 // Discrete energies: store own energies in a map for faster searching
613 //
614 // The data files sometimes have identical discrete energies (likely typos)
615 // which would lead to overwriting the already existing index and hence
616 // creating a hole in the lookup table.
617 // No attempt is made here to correct for the energies - rather an epsilon
618 // is subtracted from the energy in order to uniquely identify the line
619
620 for (G4int ie = 0; ie < nDiscreteEnergies; ie++) {
621 // check if energy is already present and subtract epsilon if that's the case
622 G4double myE = theAngular[ie].GetLabel();
623 while (theDiscreteEnergiesOwn.find(myE) != theDiscreteEnergiesOwn.end() ) {
624 myE -= 1e-6;
625 }
626 theDiscreteEnergiesOwn[myE] = ie;
627 }
628
629 /*
630 * the approach here makes no sense. It would work only for two sets that
631 * have identical min and max energy. If the 2 sets differ in min, max or
632 * both, the energy inserted would be normalized to its original set but
633 * interpreted with the new - which is not correct.
634 *
635 * Disable the code for now and simply return ...
636 */
637
638 return;
639
640 /*
641 *
642
643 if( !angParPrev ) return;
644
645 //----- Discrete energies: use energies that appear in one or another
646 for(ie=0; ie<nDiscreteEnergies; ie++) {
647 theDiscreteEnergies.insert(theAngular[ie].GetLabel());
648 }
649 G4int nDiscreteEnergiesPrev = angParPrev->GetNDiscreteEnergies();
650 for(ie=0; ie<nDiscreteEnergiesPrev; ie++) {
651 theDiscreteEnergies.insert(angParPrev->theAngular[ie].GetLabel());
652 }
653
654 //--- Get the values for which interpolation will be done : all energies of this and previous ContAngularPar
655 for(ie=nDiscreteEnergies; ie<nEnergies; ie++) {
656 G4double ener = theAngular[ie].GetLabel();
657 G4double enerT = (ener-theMinEner)/(theMaxEner-theMinEner);
658 theEnergiesTransformed.insert(enerT);
659 }
660
661 G4int nEnergiesPrev = angParPrev->GetNEnergies();
662 G4double minEnerPrev = angParPrev->GetMinEner();
663 G4double maxEnerPrev = angParPrev->GetMaxEner();
664 for(ie=nDiscreteEnergiesPrev; ie<nEnergiesPrev; ie++) {
665 G4double ener = angParPrev->theAngular[ie].GetLabel();
666 G4double enerT = (ener-minEnerPrev)/(maxEnerPrev-minEnerPrev);
667 theEnergiesTransformed.insert(enerT);
668 }
669 // add the maximum energy
670 //theEnergiesTransformed.insert(1.);
671
672 *
673 */
674}
675
676
677void
679 G4InterpolationScheme aScheme,
682{
683 G4int ie, ie1, ie2, ie1Prev, ie2Prev;
684 // Only rebuild the interpolation table if there is a new interaction.
685 // For several subsequent samplings of final state particles in the same
686 // interaction the existing table should be used
687 if (fCache.Get()->fresh != true) return;
688
689 // Make copies of angpar1 and angpar2. Since these are given by reference
690 // it can not be excluded that one of them is "this". Hence this code uses
691 // potentially the old "this" for creating the new this - which leads to
692 // memory corruption if the old is not stored as separarte object for lookup
693 const G4ParticleHPContAngularPar copyAngpar1(angpar1),copyAngpar2(angpar2);
694
695 nAngularParameters = copyAngpar1.nAngularParameters;
696 theManager = copyAngpar1.theManager;
697 theEnergy = anEnergy;
698 theMinEner = DBL_MAX; // min and max will be re-calculated after interpolation
699 theMaxEner = -DBL_MAX;
700
701 // The two discrete sets must be merged. A vector holds the temporary data to
702 // be copied to the array in the end. Since the G4ParticleHPList class
703 // contains pointers, can't simply assign elements of this type. Each member
704 // needs to call the explicit Set() method instead.
705
706 // First, average probabilities for those lines that are in both sets
707 const std::map<G4double,G4int> discEnerOwn1 = copyAngpar1.GetDiscreteEnergiesOwn();
708 const std::map<G4double,G4int> discEnerOwn2 = copyAngpar2.GetDiscreteEnergiesOwn();
709 std::map<G4double,G4int>::const_iterator itedeo1;
710 std::map<G4double,G4int>::const_iterator itedeo2;
711 std::vector<G4ParticleHPList*> vAngular(discEnerOwn1.size() );
712 G4double discEner1;
713 for (itedeo1 = discEnerOwn1.cbegin(); itedeo1 != discEnerOwn1.cend(); ++itedeo1) {
714 discEner1 = itedeo1->first;
715 if (discEner1 < theMinEner) {
716 theMinEner = discEner1;
717 }
718 if (discEner1 > theMaxEner) {
719 theMaxEner = discEner1;
720 }
721 ie1 = itedeo1->second;
722 itedeo2 = discEnerOwn2.find(discEner1);
723 if( itedeo2 == discEnerOwn2.cend() ) {
724 ie2 = -1;
725 } else {
726 ie2 = itedeo2->second;
727 }
728 vAngular[ie1] = new G4ParticleHPList();
729 vAngular[ie1]->SetLabel(copyAngpar1.theAngular[ie1].GetLabel());
730 G4double val1, val2;
731 for (G4int ip = 0; ip < nAngularParameters; ++ip) {
732 val1 = copyAngpar1.theAngular[ie1].GetValue(ip);
733 if (ie2 != -1) {
734 val2 = copyAngpar2.theAngular[ie2].GetValue(ip);
735 } else {
736 val2 = 0.;
737 }
738 G4double value = theInt.Interpolate(aScheme, anEnergy,
739 copyAngpar1.theEnergy, copyAngpar2.theEnergy,
740 val1, val2);
741 vAngular[ie1]->SetValue(ip, value);
742 }
743 } // itedeo1 loop
744
745 // Add the ones in set2 but not in set1
746 std::vector<G4ParticleHPList*>::const_iterator itv;
747 G4double discEner2;
748 for (itedeo2 = discEnerOwn2.cbegin(); itedeo2 != discEnerOwn2.cend(); ++itedeo2) {
749 discEner2 = itedeo2->first;
750 ie2 = itedeo2->second;
751 G4bool notFound = true;
752 itedeo1 = discEnerOwn1.find(discEner2);
753 if (itedeo1 != discEnerOwn1.cend() ) {
754 notFound = false;
755 }
756 if (notFound) {
757 // not yet in list
758 if (discEner2 < theMinEner) {
759 theMinEner = discEner2;
760 }
761 if (discEner2 > theMaxEner) {
762 theMaxEner = discEner2;
763 }
764 // find position to insert
765 G4bool isInserted = false;
766 ie = 0;
767 for (itv = vAngular.cbegin(); itv != vAngular.cend(); ++itv,++ie) {
768 if (discEner2 > (*itv)->GetLabel() ) {
769 itv = vAngular.insert(itv, new G4ParticleHPList);
770 (*itv)->SetLabel(copyAngpar2.theAngular[ie2].GetLabel());
771 isInserted = true;
772 break;
773 }
774 }
775 if (!isInserted) {
776 ie=(G4int)vAngular.size();
777 vAngular.push_back(new G4ParticleHPList);
778 vAngular[ie]->SetLabel(copyAngpar2.theAngular[ie2].GetLabel());
779 isInserted = true;
780 }
781
782 G4double val1, val2;
783 for (G4int ip = 0; ip < nAngularParameters; ++ip) {
784 val1 = 0;
785 val2 = copyAngpar2.theAngular[ie2].GetValue(ip);
786 G4double value = theInt.Interpolate(aScheme, anEnergy,
787 copyAngpar1.theEnergy,
788 copyAngpar2.theEnergy,
789 val1, val2);
790 vAngular[ie]->SetValue(ip, value);
791 }
792 } // end if(notFound)
793 } // end loop on itedeo2
794
795 // Store new discrete list
796 nDiscreteEnergies = (G4int)vAngular.size();
797 if (theAngular != 0) delete [] theAngular;
798 theAngular = 0;
799 if (nDiscreteEnergies > 0) {
800 theAngular = new G4ParticleHPList [nDiscreteEnergies];
801 }
802 theDiscreteEnergiesOwn.clear();
803 theDiscreteEnergies.clear();
804 for (ie = 0; ie < nDiscreteEnergies; ++ie) {
805 theAngular[ie].SetLabel(vAngular[ie]->GetLabel() );
806 for (G4int ip = 0; ip < nAngularParameters; ++ip) {
807 theAngular[ie].SetValue(ip, vAngular[ie]->GetValue(ip));
808 }
809 theDiscreteEnergiesOwn[theAngular[ie].GetLabel()] = ie;
810 theDiscreteEnergies.insert(theAngular[ie].GetLabel());
811 }
812
813 // The continuous energies need to be made from scratch like the discrete
814 // ones. Therefore the re-assignemnt of theAngular needs to be done
815 // after the continuous energy set is also finalized. Only then the
816 // total number of nEnergies is known and the array can be allocated.
817
818 // Get minimum and maximum energy interpolating
819 // Don't use theMinEner or theMaxEner here, since the transformed energies
820 // need the interpolated range from the original Angpar
821 G4double interMinEner = copyAngpar1.GetMinEner() + (theEnergy-copyAngpar1.GetEnergy() )
822 * (copyAngpar2.GetMinEner() - copyAngpar1.GetMinEner() )
823 / (copyAngpar2.GetEnergy()-copyAngpar1.GetEnergy() );
824 G4double interMaxEner = copyAngpar1.GetMaxEner() + (theEnergy-copyAngpar1.GetEnergy() )
825 * (copyAngpar2.GetMaxEner()-copyAngpar1.GetMaxEner() )
826 / (copyAngpar2.GetEnergy()-copyAngpar1.GetEnergy() );
827
828 // Loop to energies of new set
829 theEnergiesTransformed.clear();
830
831 G4int nEnergies1 = copyAngpar1.GetNEnergies();
832 G4int nDiscreteEnergies1 = copyAngpar1.GetNDiscreteEnergies();
833 G4double minEner1 = copyAngpar1.GetMinEner();
834 G4double maxEner1 = copyAngpar1.GetMaxEner();
835 G4int nEnergies2 = copyAngpar2.GetNEnergies();
836 G4int nDiscreteEnergies2 = copyAngpar2.GetNDiscreteEnergies();
837 G4double minEner2 = copyAngpar2.GetMinEner();
838 G4double maxEner2 = copyAngpar2.GetMaxEner();
839
840 // First build the list of transformed energies normalized
841 // to the new min max by assuming that the min-max range of
842 // each set would be scalable to the new, interpolated min
843 // max range
844
845 G4double e1(0.);
846 G4double eTNorm1(0.);
847 for (ie1 = nDiscreteEnergies1; ie1 < nEnergies1; ++ie1) {
848 e1 = copyAngpar1.theAngular[ie1].GetLabel();
849 eTNorm1 = (e1 - minEner1);
850 if (maxEner1 != minEner1) eTNorm1 /= (maxEner1-minEner1);
851 if (eTNorm1 >= 0 && eTNorm1 <= 1) theEnergiesTransformed.insert(eTNorm1);
852 }
853
854 G4double e2(0.);
855 G4double eTNorm2(0.);
856 for (ie2 = nDiscreteEnergies2; ie2 < nEnergies2; ++ie2) {
857 e2 = copyAngpar2.theAngular[ie2].GetLabel();
858 eTNorm2 = (e2 - minEner2);
859 if (maxEner2 != minEner2) eTNorm2 /= (maxEner2-minEner2);
860 if (eTNorm2 >= 0 && eTNorm2 <= 1) theEnergiesTransformed.insert(eTNorm2);
861 }
862
863 // Now the list of energies is complete
864 nEnergies = nDiscreteEnergies+(G4int)theEnergiesTransformed.size();
865
866 // Create final array of angular parameters
867 G4ParticleHPList* theNewAngular = new G4ParticleHPList [nEnergies];
868
869 // Copy discrete energies and interpolated parameters to new array
870
871 if (theAngular != 0) {
872 for (ie = 0; ie < nDiscreteEnergies; ++ie) {
873 theNewAngular[ie].SetLabel(theAngular[ie].GetLabel());
874 for (G4int ip = 0; ip < nAngularParameters; ++ip) {
875 theNewAngular[ie].SetValue(ip,theAngular[ie].GetValue(ip));
876 }
877 }
878 delete [] theAngular;
879 }
880 theAngular = theNewAngular;
881
882 // Interpolate the continuous energies for new array
883 std::set<G4double>::const_iterator iteet = theEnergiesTransformed.begin();
884
885 G4double e1Interp(0.);
886 G4double e2Interp(0.);
887 for (ie = nDiscreteEnergies; ie < nEnergies; ++ie, ++iteet) {
888 G4double eT = (*iteet);
889
890 //--- Use eT1 = eT: Get energy and parameters of copyAngpar1 for this eT
891 e1Interp = (maxEner1 - minEner1) * eT + minEner1;
892 //----- Get parameter value corresponding to this e1Interp
893 for (ie1 = nDiscreteEnergies1; ie1 < nEnergies1; ++ie1) {
894 if ((copyAngpar1.theAngular[ie1].GetLabel() - e1Interp) > 1.E-10*e1Interp) break;
895 }
896 ie1Prev = ie1 - 1;
897 if (ie1 == 0) ++ie1Prev;
898 if (ie1 == nEnergies1) {
899 ie1--;
900 ie1Prev = ie1;
901 }
902
903 //--- Use eT2 = eT: Get energy and parameters of copyAngpar2 for this eT
904 e2Interp = (maxEner2-minEner2) * eT + minEner2;
905 //----- Get parameter value corresponding to this e2Interp
906 for (ie2 = nDiscreteEnergies2; ie2 < nEnergies2; ++ie2) {
907 if ((copyAngpar2.theAngular[ie2].GetLabel() - e2Interp) > 1.E-10*e2Interp) break;
908 }
909 ie2Prev = ie2 - 1;
910 if (ie2 == 0) ++ie2Prev;
911 if (ie2 == nEnergies2) {
912 ie2--;
913 ie2Prev = ie2;
914 }
915
916 //---- Energy corresponding to energy transformed
917 G4double eN = (interMaxEner-interMinEner) * eT + interMinEner;
918
919 theAngular[ie].SetLabel(eN);
920 if (eN < theMinEner) {
921 theMinEner = eN;
922 }
923 if (eN > theMaxEner) {
924 theMaxEner = eN;
925 }
926
927 G4double val1(0.);
928 G4double val2(0.);
929 G4double value(0.);
930 for (G4int ip = 0; ip < nAngularParameters; ++ip) {
931 val1 = theInt.Interpolate2(theManager.GetScheme(ie),
932 e1Interp,
933 copyAngpar1.theAngular[ie1Prev].GetLabel(),
934 copyAngpar1.theAngular[ie1].GetLabel(),
935 copyAngpar1.theAngular[ie1Prev].GetValue(ip),
936 copyAngpar1.theAngular[ie1].GetValue(ip)) * (maxEner1-minEner1);
937 val2 = theInt.Interpolate2(theManager.GetScheme(ie),
938 e2Interp,
939 copyAngpar2.theAngular[ie2Prev].GetLabel(),
940 copyAngpar2.theAngular[ie2].GetLabel(),
941 copyAngpar2.theAngular[ie2Prev].GetValue(ip),
942 copyAngpar2.theAngular[ie2].GetValue(ip)) * (maxEner2-minEner2);
943
944 value = theInt.Interpolate(aScheme, anEnergy,
945 copyAngpar1.theEnergy, copyAngpar2.theEnergy,
946 val1, val2);
947 if (interMaxEner != interMinEner) {
948 value /= (interMaxEner-interMinEner);
949 } else if (value != 0) {
950 throw G4HadronicException(__FILE__, __LINE__,
951 "G4ParticleHPContAngularPar::PrepareTableInterpolation interMaxEner == interMinEner and value != 0.");
952 }
953 theAngular[ie].SetValue(ip, value);
954 }
955 } // end loop on nDiscreteEnergies
956
957 for (itv = vAngular.cbegin(); itv != vAngular.cend(); ++itv) delete (*itv);
958
959}
960
961
963{
964 G4cout << theEnergy << " " << nEnergies << " " << nDiscreteEnergies
965 << " " << nAngularParameters << G4endl;
966
967 for (G4int ii = 0; ii < nEnergies; ii++) theAngular[ii].Dump();
968}
969
G4InterpolationScheme
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
const G4double A[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
static G4Alpha * Alpha()
Definition: G4Alpha.cc:88
value_type & Get() const
Definition: G4Cache.hh:315
static G4Deuteron * Deuteron()
Definition: G4Deuteron.cc:93
static G4Electron * Electron()
Definition: G4Electron.cc:93
static G4Gamma * Gamma()
Definition: G4Gamma.cc:85
static G4He3 * He3()
Definition: G4He3.cc:93
void Init(G4int aScheme, G4int aRange)
G4InterpolationScheme GetScheme(G4int index) const
G4InterpolationScheme GetInverseScheme(G4int index)
static G4IonTable * GetIonTable()
Definition: G4IonTable.cc:170
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
static G4double GetNuclearMass(const G4double A, const G4double Z)
G4double GetPDGCharge() const
G4ReactionProduct * Sample(G4double anEnergy, G4double massCode, G4double mass, G4int angularRep, G4int interpol)
void Init(std::istream &aDataFile, G4ParticleDefinition *projectile)
std::map< G4double, G4int > GetDiscreteEnergiesOwn() const
void BuildByInterpolation(G4double anEnergy, G4InterpolationScheme aScheme, G4ParticleHPContAngularPar &store1, G4ParticleHPContAngularPar &store2)
G4double Interpolate(G4InterpolationScheme aScheme, G4double x, G4double x1, G4double x2, G4double y1, G4double y2) const
G4double GetWeightedBinIntegral(const G4InterpolationScheme &aScheme, const G4double x1, const G4double x2, const G4double y1, const G4double y2)
G4double Interpolate2(G4InterpolationScheme aScheme, G4double x, G4double x1, G4double x2, G4double y1, G4double y2) const
G4double GetBinIntegral(const G4InterpolationScheme &aScheme, const G4double x1, const G4double x2, const G4double y1, const G4double y2)
void SetCoeff(G4int i, G4int l, G4double coeff)
void Init(G4int i, G4double e, G4int n)
G4double SampleMax(G4double energy)
void SetManager(G4InterpolationManager &aManager)
void SetLabel(G4double aLabel)
void SetValue(G4int i, G4double y)
void Init(std::istream &aDataFile, G4int nPar, G4double unit=1.)
G4double GetValue(G4int i)
static G4ParticleHPManager * GetInstance()
void SetY(G4int i, G4double x)
void SetX(G4int i, G4double e)
void SetInterpolationManager(const G4InterpolationManager &aManager)
G4double GetY(G4double x)
G4double GetX(G4int i) const
G4int GetVectorLength() const
static G4Positron * Positron()
Definition: G4Positron.cc:93
static G4Proton * Proton()
Definition: G4Proton.cc:92
void SetMomentum(const G4double x, const G4double y, const G4double z)
G4double GetTotalMomentum() const
void SetDefinition(const G4ParticleDefinition *aParticleDefinition)
void SetKineticEnergy(const G4double en)
G4double GetMass() const
static G4Triton * Triton()
Definition: G4Triton.cc:93
#define DBL_MAX
Definition: templates.hh:62