Files
geant4/source/processes/hadronic/models/particle_hp/src/G4ParticleHPPhotonDist.cc
T
2024-06-21 15:46:33 +02:00

678 lines
26 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// neutron_hp -- source file
// J.P. Wellisch, Nov-1996
// A prototype of the low energy neutron transport model.
//
// 070523 Try to limit sum of secondary photon energy while keeping distribution shape
// in the of nDiscrete = 1 an nPartial = 1. Most case are satisfied.
// T. Koi
// 070606 Add Partial case by T. Koi
// 070618 fix memory leaking by T. Koi
// 080801 fix memory leaking by T. Koi
// 080801 Correcting data disorder which happened when both InitPartial
// and InitAnglurar methods was called in a same instance by T. Koi
// 090514 Fix bug in IC electron emission case
// Contribution from Chao Zhang (Chao.Zhang@usd.edu) and Dongming Mei(Dongming.Mei@usd.edu)
// But it looks like never cause real effect in G4NDL3.13 (at least Natural elements) TK
// 101111 Change warning message for "repFlag == 2 && isoFlag != 1" case
//
// there is a lot of unused (and undebugged) code in this file. Kept for the moment just in case. @@
// P. Arce, June-2014 Conversion neutron_hp to particle_hp
//
#include "G4ParticleHPPhotonDist.hh"
#include "G4Electron.hh"
#include "G4ParticleHPLegendreStore.hh"
#include "G4PhysicalConstants.hh"
#include "G4Poisson.hh"
#include "G4SystemOfUnits.hh"
#include <numeric>
G4bool G4ParticleHPPhotonDist::InitMean(std::istream& aDataFile)
{
G4bool result = true;
if (aDataFile >> repFlag) {
aDataFile >> targetMass;
if (repFlag == 1) {
// multiplicities
aDataFile >> nDiscrete;
const std::size_t msize = nDiscrete > 0 ? nDiscrete : 1;
disType = new G4int[msize];
energy = new G4double[msize];
// actualMult = new G4int[msize];
theYield = new G4ParticleHPVector[msize];
for (std::size_t i = 0; i < msize; ++i) {
aDataFile >> disType[i] >> energy[i];
energy[i] *= eV;
theYield[i].Init(aDataFile, eV);
}
}
else if (repFlag == 2) {
aDataFile >> theInternalConversionFlag;
aDataFile >> theBaseEnergy;
theBaseEnergy *= eV;
aDataFile >> theInternalConversionFlag;
aDataFile >> nGammaEnergies;
const std::size_t esize = nGammaEnergies > 0 ? nGammaEnergies : 1;
theLevelEnergies = new G4double[esize];
theTransitionProbabilities = new G4double[esize];
if (theInternalConversionFlag == 2)
thePhotonTransitionFraction = new G4double[esize];
for (std::size_t ii = 0; ii < esize; ++ii) {
if (theInternalConversionFlag == 1) {
aDataFile >> theLevelEnergies[ii] >> theTransitionProbabilities[ii];
theLevelEnergies[ii] *= eV;
}
else if (theInternalConversionFlag == 2) {
aDataFile >> theLevelEnergies[ii] >> theTransitionProbabilities[ii]
>> thePhotonTransitionFraction[ii];
theLevelEnergies[ii] *= eV;
}
else {
throw G4HadronicException(__FILE__, __LINE__,
"G4ParticleHPPhotonDist: Unknown conversion flag");
}
}
}
else {
G4cout << "Data representation in G4ParticleHPPhotonDist: " << repFlag << G4endl;
throw G4HadronicException(
__FILE__, __LINE__, "G4ParticleHPPhotonDist: This data representation is not implemented.");
}
}
else {
result = false;
}
return result;
}
void G4ParticleHPPhotonDist::InitAngular(std::istream& aDataFile)
{
G4int i, ii;
// angular distributions
aDataFile >> isoFlag;
if (isoFlag != 1) {
if (repFlag == 2)
G4cout << "G4ParticleHPPhotonDist: repFlag == 2 && isoFlag != 1 is unexpected! If you use "
"G4ND3.x, then please report to Geant4 HyperNews. "
<< G4endl;
aDataFile >> tabulationType >> nDiscrete2 >> nIso;
if (theGammas != nullptr && nDiscrete2 != nDiscrete)
G4cout << "080731c G4ParticleHPPhotonDist nDiscrete2 != nDiscrete, It looks like something "
"wrong in your NDL files. Please update the latest. If you still have this "
"messages after the update, then please report to Geant4 Hyper News."
<< G4endl;
// The order of cross section (InitPartials) and distribution
// (InitAngular here) data are different, we have to re-coordinate
// consistent data order.
std::vector<G4double> vct_gammas_par;
std::vector<G4double> vct_shells_par;
std::vector<G4int> vct_primary_par;
std::vector<G4int> vct_distype_par;
std::vector<G4ParticleHPVector*> vct_pXS_par;
if (theGammas != nullptr && theShells != nullptr) {
// copy the cross section data
for (i = 0; i < nDiscrete; ++i) {
vct_gammas_par.push_back(theGammas[i]);
vct_shells_par.push_back(theShells[i]);
vct_primary_par.push_back(isPrimary[i]);
vct_distype_par.push_back(disType[i]);
auto hpv = new G4ParticleHPVector;
*hpv = thePartialXsec[i];
vct_pXS_par.push_back(hpv);
}
}
const std::size_t psize = nDiscrete2 > 0 ? nDiscrete2 : 1;
if (theGammas == nullptr) theGammas = new G4double[psize];
if (theShells == nullptr) theShells = new G4double[psize];
for (i = 0; i < nIso; ++i) // isotropic photons
{
aDataFile >> theGammas[i] >> theShells[i];
theGammas[i] *= eV;
theShells[i] *= eV;
}
const std::size_t tsize = nDiscrete2 - nIso > 0 ? nDiscrete2 - nIso : 1;
nNeu = new G4int[tsize];
if (tabulationType == 1) theLegendre = new G4ParticleHPLegendreTable*[tsize];
if (tabulationType == 2) theAngular = new G4ParticleHPAngularP*[tsize];
for (i = nIso; i < nDiscrete2; ++i) {
if (tabulationType == 1) {
aDataFile >> theGammas[i] >> theShells[i] >> nNeu[i - nIso];
theGammas[i] *= eV;
theShells[i] *= eV;
const std::size_t lsize = nNeu[i - nIso] > 0 ? nNeu[i - nIso] : 1;
theLegendre[i - nIso] = new G4ParticleHPLegendreTable[lsize];
theLegendreManager.Init(aDataFile);
for (ii = 0; ii < nNeu[i - nIso]; ++ii) {
theLegendre[i - nIso][ii].Init(aDataFile);
}
}
else if (tabulationType == 2) {
aDataFile >> theGammas[i] >> theShells[i] >> nNeu[i - nIso];
theGammas[i] *= eV;
theShells[i] *= eV;
const std::size_t asize = nNeu[i - nIso] > 0 ? nNeu[i - nIso] : 1;
theAngular[i - nIso] = new G4ParticleHPAngularP[asize];
for (ii = 0; ii < nNeu[i - nIso]; ++ii) {
theAngular[i - nIso][ii].Init(aDataFile);
}
}
else {
G4cout << "tabulation type: tabulationType" << G4endl;
throw G4HadronicException(
__FILE__, __LINE__, "cannot deal with this tabulation type for angular distributions.");
}
}
if (!vct_gammas_par.empty()) {
// Reordering cross section data to corrsponding distribution data
for (i = 0; i < nDiscrete; ++i) {
for (G4int j = 0; j < nDiscrete; ++j) {
// Checking gamma and shell to identification
if (theGammas[i] == vct_gammas_par[j] && theShells[i] == vct_shells_par[j]) {
isPrimary[i] = vct_primary_par[j];
disType[i] = vct_distype_par[j];
thePartialXsec[i] = (*(vct_pXS_par[j]));
}
}
}
// Garbage collection
for (auto it = vct_pXS_par.cbegin(); it != vct_pXS_par.cend(); ++it) {
delete *it;
}
}
}
}
void G4ParticleHPPhotonDist::InitEnergies(std::istream& aDataFile)
{
G4int i, energyDistributionsNeeded = 0;
for (i = 0; i < nDiscrete; ++i) {
if (disType[i] == 1) energyDistributionsNeeded = 1;
}
if (energyDistributionsNeeded == 0) return;
aDataFile >> nPartials;
const std::size_t dsize = nPartials > 0 ? nPartials : 1;
distribution = new G4int[dsize];
probs = new G4ParticleHPVector[dsize];
partials = new G4ParticleHPPartial*[dsize];
G4int nen;
G4int dummy;
for (i = 0; i < nPartials; ++i) {
aDataFile >> dummy;
probs[i].Init(aDataFile, eV);
aDataFile >> nen;
partials[i] = new G4ParticleHPPartial(nen);
partials[i]->InitInterpolation(aDataFile);
partials[i]->Init(aDataFile);
}
}
void G4ParticleHPPhotonDist::InitPartials(std::istream& aDataFile, G4ParticleHPVector* theXsec)
{
if (theXsec != nullptr) theReactionXsec = theXsec;
aDataFile >> nDiscrete >> targetMass;
if (nDiscrete != 1) {
theTotalXsec.Init(aDataFile, eV);
}
const std::size_t dsize = nDiscrete > 0 ? nDiscrete : 1;
theGammas = new G4double[dsize];
theShells = new G4double[dsize];
isPrimary = new G4int[dsize];
disType = new G4int[dsize];
thePartialXsec = new G4ParticleHPVector[dsize];
for (std::size_t i = 0; i < dsize; ++i) {
aDataFile >> theGammas[i] >> theShells[i] >> isPrimary[i] >> disType[i];
theGammas[i] *= eV;
theShells[i] *= eV;
thePartialXsec[i].Init(aDataFile, eV);
}
}
G4ReactionProductVector* G4ParticleHPPhotonDist::GetPhotons(G4double anEnergy)
{
// the partial cross-section case is not all in this yet.
if (actualMult.Get() == nullptr) {
actualMult.Get() = new std::vector<G4int>(nDiscrete);
}
G4int i, ii, iii;
G4int nSecondaries = 0;
auto thePhotons = new G4ReactionProductVector;
if (repFlag == 1) {
G4double current = 0;
for (i = 0; i < nDiscrete; ++i) {
current = theYield[i].GetY(anEnergy);
actualMult.Get()->at(i) = (G4int)G4Poisson(current); // max cut-off still missing @@@
if (nDiscrete == 1 && current < 1.0001) {
actualMult.Get()->at(i) = static_cast<G4int>(current);
if (current < 1) {
actualMult.Get()->at(i) = 0;
if (G4UniformRand() < current) actualMult.Get()->at(i) = 1;
}
}
nSecondaries += actualMult.Get()->at(i);
}
for (i = 0; i < nSecondaries; ++i) {
auto theOne = new G4ReactionProduct;
theOne->SetDefinition(G4Gamma::Gamma());
thePhotons->push_back(theOne);
}
G4int count = 0;
if (nDiscrete == 1 && nPartials == 1) {
if (actualMult.Get()->at(0) > 0) {
if (disType[0] == 1) {
// continuum
G4ParticleHPVector* temp;
temp = partials[0]->GetY(anEnergy); //@@@ look at, seems fishy
G4double maximumE = temp->GetX(temp->GetVectorLength() - 1); // This is an assumption.
std::vector<G4double> photons_e_best(actualMult.Get()->at(0), 0.0);
G4double best = DBL_MAX;
G4int maxTry = 1000;
for (G4int j = 0; j < maxTry; ++j) {
std::vector<G4double> photons_e(actualMult.Get()->at(0), 0.0);
for (auto it = photons_e.begin(); it < photons_e.end(); ++it) {
*it = temp->Sample();
}
if (std::accumulate(photons_e.cbegin(), photons_e.cend(), 0.0) > maximumE) {
if (std::accumulate(photons_e.cbegin(), photons_e.cend(), 0.0) < best)
photons_e_best = photons_e;
continue;
}
G4int iphot = 0;
for (auto it = photons_e.cbegin(); it < photons_e.cend(); ++it) {
thePhotons->operator[](iphot)->SetKineticEnergy(
*it); // Replace index count, which was not incremented,
// with iphot, which is, as per Artem Zontikov,
// bug report 2167
++iphot;
}
break;
}
delete temp;
}
else {
// discrete
thePhotons->operator[](count)->SetKineticEnergy(energy[i]);
}
++count;
if (count > nSecondaries)
throw G4HadronicException(__FILE__, __LINE__,
"G4ParticleHPPhotonDist::GetPhotons inconsistency");
}
}
else { // nDiscrete != 1 or nPartials != 1
for (i = 0; i < nDiscrete; ++i) {
for (ii = 0; ii < actualMult.Get()->at(i); ++ii) {
if (disType[i] == 1) {
// continuum
G4double sum = 0, run = 0;
for (iii = 0; iii < nPartials; ++iii)
sum += probs[iii].GetY(anEnergy);
G4double random = G4UniformRand();
G4int theP = 0;
for (iii = 0; iii < nPartials; ++iii) {
run += probs[iii].GetY(anEnergy);
theP = iii;
if (random < run / sum) break;
}
if (theP == nPartials) theP = nPartials - 1; // das sortiert J aus.
sum = 0;
G4ParticleHPVector* temp;
temp = partials[theP]->GetY(anEnergy); //@@@ look at, seems fishy
G4double eGamm = temp->Sample();
thePhotons->operator[](count)->SetKineticEnergy(eGamm);
delete temp;
}
else {
// discrete
thePhotons->operator[](count)->SetKineticEnergy(energy[i]);
}
++count;
if (count > nSecondaries)
throw G4HadronicException(__FILE__, __LINE__,
"G4ParticleHPPhotonDist::GetPhotons inconsistency");
}
}
}
// now do the angular distributions...
if (isoFlag == 1) {
for (i = 0; i < nSecondaries; ++i) {
G4double costheta = 2. * G4UniformRand() - 1;
G4double theta = std::acos(costheta);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
G4double en = thePhotons->operator[](i)->GetTotalEnergy();
G4ThreeVector temp(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * std::cos(theta));
thePhotons->operator[](i)->SetMomentum(temp);
}
}
else {
for (i = 0; i < nSecondaries; ++i) {
G4double currentEnergy = thePhotons->operator[](i)->GetTotalEnergy();
for (ii = 0; ii < nDiscrete2; ++ii) {
if (std::abs(currentEnergy - theGammas[ii]) < 0.1 * keV) break;
}
if (ii == nDiscrete2)
--ii; // fix for what seems an (file12 vs file 14) inconsistency found in the ENDF 7N14
// data. @@
if (ii < nIso) {
// isotropic distribution
//
// Fix Bugzilla report #1745
// G4double theta = pi*G4UniformRand();
G4double costheta = 2. * G4UniformRand() - 1;
G4double theta = std::acos(costheta);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
G4double en = thePhotons->operator[](i)->GetTotalEnergy();
// DHW G4ThreeVector tempVector(en*sinth*std::cos(phi), en*sinth*std::sin(phi),
// en*std::cos(theta) );
G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * costheta);
thePhotons->operator[](i)->SetMomentum(tempVector);
}
else if (tabulationType == 1) {
// legendre polynomials
G4int it(0);
for (iii = 0; iii < nNeu[ii - nIso]; ++iii) // find the neutron energy
{
it = iii;
if (theLegendre[ii - nIso][iii].GetEnergy() > anEnergy) break;
}
G4ParticleHPLegendreStore aStore(2);
aStore.SetCoeff(1, &(theLegendre[ii - nIso][it]));
if (it > 0) {
aStore.SetCoeff(0, &(theLegendre[ii - nIso][it - 1]));
}
else {
aStore.SetCoeff(0, &(theLegendre[ii - nIso][it]));
}
G4double cosTh = aStore.SampleMax(anEnergy);
G4double theta = std::acos(cosTh);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
G4double en = thePhotons->operator[](i)->GetTotalEnergy();
G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * std::cos(theta));
thePhotons->operator[](i)->SetMomentum(tempVector);
}
else {
// tabulation of probabilities.
G4int it(0);
for (iii = 0; iii < nNeu[ii - nIso]; ++iii) // find the neutron energy
{
it = iii;
if (theAngular[ii - nIso][iii].GetEnergy() > anEnergy) break;
}
G4double costh = theAngular[ii - nIso][it].GetCosTh(); // no interpolation yet @@
G4double theta = std::acos(costh);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
G4double en = thePhotons->operator[](i)->GetTotalEnergy();
G4ThreeVector tmpVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * costh);
thePhotons->operator[](i)->SetMomentum(tmpVector);
}
}
}
}
else if (repFlag == 2) {
auto running = new G4double[nGammaEnergies];
running[0] = theTransitionProbabilities[0];
for (i = 1; i < nGammaEnergies; ++i) {
running[i] = running[i - 1] + theTransitionProbabilities[i];
}
G4double random = G4UniformRand();
G4int it = 0;
for (i = 0; i < nGammaEnergies; ++i) {
it = i;
if (random < running[i] / running[nGammaEnergies - 1]) break;
}
delete[] running;
G4double totalEnergy = theBaseEnergy - theLevelEnergies[it];
auto theOne = new G4ReactionProduct;
theOne->SetDefinition(G4Gamma::Gamma());
random = G4UniformRand();
if (theInternalConversionFlag == 2 && random > thePhotonTransitionFraction[it]) {
theOne->SetDefinition(G4Electron::Electron());
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009 But never enter at least with G4NDL3.13
totalEnergy +=
G4Electron::Electron()->GetPDGMass(); // proposed correction: add this line for electron
}
theOne->SetTotalEnergy(totalEnergy);
if (isoFlag == 1) {
G4double costheta = 2. * G4UniformRand() - 1;
G4double theta = std::acos(costheta);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009 G4double en = theOne->GetTotalEnergy();
G4double en = theOne->GetTotalMomentum();
// But never cause real effect at least with G4NDL3.13 TK
G4ThreeVector temp(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * std::cos(theta));
theOne->SetMomentum(temp);
}
else {
G4double currentEnergy = theOne->GetTotalEnergy();
for (ii = 0; ii < nDiscrete2; ++ii) {
if (std::abs(currentEnergy - theGammas[ii]) < 0.1 * keV) break;
}
if (ii == nDiscrete2)
--ii; // fix for what seems an (file12 vs file 14) inconsistency found in the ENDF 7N14
// data. @@
if (ii < nIso) {
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009
// isotropic distribution
// G4double theta = pi*G4UniformRand();
G4double theta = std::acos(2. * G4UniformRand() - 1.);
// But this is alos never cause real effect at least with G4NDL3.13 TK not repFlag == 2 AND
// isoFlag != 1
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009 G4double en = theOne->GetTotalEnergy();
G4double en = theOne->GetTotalMomentum();
// But never cause real effect at least with G4NDL3.13 TK
G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * std::cos(theta));
theOne->SetMomentum(tempVector);
}
else if (tabulationType == 1) {
// legendre polynomials
G4int itt(0);
for (iii = 0; iii < nNeu[ii - nIso]; ++iii) // find the neutron energy
{
itt = iii;
if (theLegendre[ii - nIso][iii].GetEnergy() > anEnergy) break;
}
G4ParticleHPLegendreStore aStore(2);
aStore.SetCoeff(1, &(theLegendre[ii - nIso][itt]));
// aStore.SetCoeff(0, &(theLegendre[ii-nIso][it-1]));
// TKDB 110512
if (itt > 0) {
aStore.SetCoeff(0, &(theLegendre[ii - nIso][itt - 1]));
}
else {
aStore.SetCoeff(0, &(theLegendre[ii - nIso][itt]));
}
G4double cosTh = aStore.SampleMax(anEnergy);
G4double theta = std::acos(cosTh);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009 G4double en = theOne->GetTotalEnergy();
G4double en = theOne->GetTotalMomentum();
// But never cause real effect at least with G4NDL3.13 TK
G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
en * std::cos(theta));
theOne->SetMomentum(tempVector);
}
else {
// tabulation of probabilities.
G4int itt(0);
for (iii = 0; iii < nNeu[ii - nIso]; ++iii) // find the neutron energy
{
itt = iii;
if (theAngular[ii - nIso][iii].GetEnergy() > anEnergy) break;
}
G4double costh = theAngular[ii - nIso][itt].GetCosTh(); // no interpolation yet @@
G4double theta = std::acos(costh);
G4double phi = twopi * G4UniformRand();
G4double sinth = std::sin(theta);
// Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
// 2009 G4double en = theOne->GetTotalEnergy();
G4double en = theOne->GetTotalMomentum();
// But never cause real effect at least with G4NDL3.13 TK
G4ThreeVector tmpVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi), en * costh);
theOne->SetMomentum(tmpVector);
}
}
thePhotons->push_back(theOne);
}
else if (repFlag == 0) {
if (thePartialXsec == nullptr) {
return thePhotons;
}
// Partial Case
auto theOne = new G4ReactionProduct;
theOne->SetDefinition(G4Gamma::Gamma());
thePhotons->push_back(theOne);
// Energy
G4double sum = 0.0;
std::vector<G4double> dif(nDiscrete, 0.0);
for (G4int j = 0; j < nDiscrete; ++j) {
G4double x = thePartialXsec[j].GetXsec(anEnergy); // x in barn
if (x > 0) {
sum += x;
}
dif[j] = sum;
}
G4double rand = G4UniformRand();
G4int iphoton = 0;
for (G4int j = 0; j < nDiscrete; ++j) {
G4double y = rand * sum;
if (dif[j] > y) {
iphoton = j;
break;
}
}
// Statistically suppress the photon according to reaction cross section
// Fix proposed by Artem Zontikov, Bug report #1824
if (theReactionXsec != nullptr) {
if (thePartialXsec[iphoton].GetXsec(anEnergy) / theReactionXsec->GetXsec(anEnergy)
< G4UniformRand())
{
delete thePhotons;
thePhotons = nullptr;
return thePhotons;
}
}
// Angle
G4double cosTheta = 0.0; // mu
if (isoFlag == 1) {
// Isotropic Case
cosTheta = 2. * G4UniformRand() - 1;
}
else {
if (iphoton < nIso) {
// still Isotropic
cosTheta = 2. * G4UniformRand() - 1;
}
else {
if (tabulationType == 1) {
// Legendre polynomials
G4int iangle = 0;
for (G4int j = 0; j < nNeu[iphoton - nIso]; ++j) {
iangle = j;
if (theLegendre[iphoton - nIso][j].GetEnergy() > anEnergy) break;
}
G4ParticleHPLegendreStore aStore(2);
aStore.SetCoeff(1, &(theLegendre[iphoton - nIso][iangle]));
aStore.SetCoeff(0, &(theLegendre[iphoton - nIso][iangle - 1]));
cosTheta = aStore.SampleMax(anEnergy);
}
else if (tabulationType == 2) {
// tabulation of probabilities.
G4int iangle = 0;
for (G4int j = 0; j < nNeu[iphoton - nIso]; ++j) {
iangle = j;
if (theAngular[iphoton - nIso][j].GetEnergy() > anEnergy) break;
}
cosTheta = theAngular[iphoton - nIso][iangle].GetCosTh();
// no interpolation yet @@
}
}
}
// Set
G4double phi = twopi * G4UniformRand();
G4double theta = std::acos(cosTheta);
G4double sinTheta = std::sin(theta);
G4double photonE = theGammas[iphoton];
G4ThreeVector direction(sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta);
G4ThreeVector photonP = photonE * direction;
thePhotons->operator[](0)->SetMomentum(photonP);
}
else {
delete thePhotons;
thePhotons = nullptr; // no gamma data available; some work needed @@@@@@@
}
return thePhotons;
}