Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/particle_hp/src/G4ParticleHPPhotonDist.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 // 070523 Try to limit sum of secondary photon energy while keeping distribution shape
 31 //        in the of nDiscrete = 1 an nPartial = 1. Most case are satisfied.
 32 //        T. Koi
 33 // 070606 Add Partial case by T. Koi
 34 // 070618 fix memory leaking by T. Koi
 35 // 080801 fix memory leaking by T. Koi
 36 // 080801 Correcting data disorder which happened when both InitPartial
 37 //        and InitAnglurar methods was called in a same instance by T. Koi
 38 // 090514 Fix bug in IC electron emission case
 39 //        Contribution from Chao Zhang (Chao.Zhang@usd.edu) and Dongming Mei(Dongming.Mei@usd.edu)
 40 //        But it looks like never cause real effect in G4NDL3.13 (at least Natural elements) TK
 41 // 101111 Change warning message for "repFlag == 2 && isoFlag != 1" case
 42 //
 43 // there is a lot of unused (and undebugged) code in this file. Kept for the moment just in case. @@
 44 // P. Arce, June-2014 Conversion neutron_hp to particle_hp
 45 //
 46 #include "G4ParticleHPPhotonDist.hh"
 47 
 48 #include "G4Electron.hh"
 49 #include "G4ParticleHPLegendreStore.hh"
 50 #include "G4PhysicalConstants.hh"
 51 #include "G4Poisson.hh"
 52 #include "G4SystemOfUnits.hh"
 53 
 54 #include <numeric>
 55 
 56 G4bool G4ParticleHPPhotonDist::InitMean(std::istream& aDataFile)
 57 {
 58   G4bool result = true;
 59   if (aDataFile >> repFlag) {
 60     aDataFile >> targetMass;
 61     if (repFlag == 1) {
 62       // multiplicities
 63       aDataFile >> nDiscrete;
 64       const std::size_t msize = nDiscrete > 0 ? nDiscrete : 1;
 65       disType = new G4int[msize];
 66       energy = new G4double[msize];
 67       // actualMult = new G4int[msize];
 68       theYield = new G4ParticleHPVector[msize];
 69       for (std::size_t i = 0; i < msize; ++i) {
 70         aDataFile >> disType[i] >> energy[i];
 71         energy[i] *= eV;
 72         theYield[i].Init(aDataFile, eV);
 73       }
 74     }
 75     else if (repFlag == 2) {
 76       aDataFile >> theInternalConversionFlag;
 77       aDataFile >> theBaseEnergy;
 78       theBaseEnergy *= eV;
 79       aDataFile >> theInternalConversionFlag;
 80       aDataFile >> nGammaEnergies;
 81       const std::size_t esize = nGammaEnergies > 0 ? nGammaEnergies : 1;
 82       theLevelEnergies = new G4double[esize];
 83       theTransitionProbabilities = new G4double[esize];
 84       if (theInternalConversionFlag == 2)
 85         thePhotonTransitionFraction = new G4double[esize];
 86       for (std::size_t ii = 0; ii < esize; ++ii) {
 87         if (theInternalConversionFlag == 1) {
 88           aDataFile >> theLevelEnergies[ii] >> theTransitionProbabilities[ii];
 89           theLevelEnergies[ii] *= eV;
 90         }
 91         else if (theInternalConversionFlag == 2) {
 92           aDataFile >> theLevelEnergies[ii] >> theTransitionProbabilities[ii]
 93             >> thePhotonTransitionFraction[ii];
 94           theLevelEnergies[ii] *= eV;
 95         }
 96         else {
 97           throw G4HadronicException(__FILE__, __LINE__,
 98                                     "G4ParticleHPPhotonDist: Unknown conversion flag");
 99         }
100       }
101     }
102     else {
103       G4cout << "Data representation in G4ParticleHPPhotonDist: " << repFlag << G4endl;
104       throw G4HadronicException(
105         __FILE__, __LINE__, "G4ParticleHPPhotonDist: This data representation is not implemented.");
106     }
107   }
108   else {
109     result = false;
110   }
111   return result;
112 }
113 
114 void G4ParticleHPPhotonDist::InitAngular(std::istream& aDataFile)
115 {
116   G4int i, ii;
117   // angular distributions
118   aDataFile >> isoFlag;
119   if (isoFlag != 1) {
120     if (repFlag == 2)
121       G4cout << "G4ParticleHPPhotonDist: repFlag == 2 && isoFlag != 1 is unexpected! If you use "
122                 "G4ND3.x, then please report to Geant4 HyperNews. "
123              << G4endl;
124     aDataFile >> tabulationType >> nDiscrete2 >> nIso;
125     if (theGammas != nullptr && nDiscrete2 != nDiscrete)
126       G4cout << "080731c G4ParticleHPPhotonDist nDiscrete2 != nDiscrete, It looks like something "
127                 "wrong in your NDL files. Please update the latest. If you still have this "
128                 "messages after the update, then please report to Geant4 Hyper News."
129              << G4endl;
130 
131     // The order of cross section (InitPartials) and distribution
132     // (InitAngular here) data are different, we have to re-coordinate
133     // consistent data order.
134     std::vector<G4double> vct_gammas_par;
135     std::vector<G4double> vct_shells_par;
136     std::vector<G4int> vct_primary_par;
137     std::vector<G4int> vct_distype_par;
138     std::vector<G4ParticleHPVector*> vct_pXS_par;
139     if (theGammas != nullptr && theShells != nullptr) {
140       // copy the cross section data
141       for (i = 0; i < nDiscrete; ++i) {
142         vct_gammas_par.push_back(theGammas[i]);
143         vct_shells_par.push_back(theShells[i]);
144         vct_primary_par.push_back(isPrimary[i]);
145         vct_distype_par.push_back(disType[i]);
146         auto hpv = new G4ParticleHPVector;
147         *hpv = thePartialXsec[i];
148         vct_pXS_par.push_back(hpv);
149       }
150     }
151     const std::size_t psize = nDiscrete2 > 0 ? nDiscrete2 : 1;
152     if (theGammas == nullptr) theGammas = new G4double[psize];
153     if (theShells == nullptr) theShells = new G4double[psize];
154 
155     for (i = 0; i < nIso; ++i)  // isotropic photons
156     {
157       aDataFile >> theGammas[i] >> theShells[i];
158       theGammas[i] *= eV;
159       theShells[i] *= eV;
160     }
161     const std::size_t tsize = nDiscrete2 - nIso > 0 ? nDiscrete2 - nIso : 1;
162     nNeu = new G4int[tsize];
163     if (tabulationType == 1) theLegendre = new G4ParticleHPLegendreTable*[tsize];
164     if (tabulationType == 2) theAngular = new G4ParticleHPAngularP*[tsize];
165     for (i = nIso; i < nDiscrete2; ++i) {
166       if (tabulationType == 1) {
167         aDataFile >> theGammas[i] >> theShells[i] >> nNeu[i - nIso];
168         theGammas[i] *= eV;
169         theShells[i] *= eV;
170         const std::size_t lsize = nNeu[i - nIso] > 0 ? nNeu[i - nIso] : 1;
171         theLegendre[i - nIso] = new G4ParticleHPLegendreTable[lsize];
172         theLegendreManager.Init(aDataFile);
173         for (ii = 0; ii < nNeu[i - nIso]; ++ii) {
174           theLegendre[i - nIso][ii].Init(aDataFile);
175         }
176       }
177       else if (tabulationType == 2) {
178         aDataFile >> theGammas[i] >> theShells[i] >> nNeu[i - nIso];
179         theGammas[i] *= eV;
180         theShells[i] *= eV;
181         const std::size_t asize = nNeu[i - nIso] > 0 ? nNeu[i - nIso] : 1;
182         theAngular[i - nIso] = new G4ParticleHPAngularP[asize];
183         for (ii = 0; ii < nNeu[i - nIso]; ++ii) {
184           theAngular[i - nIso][ii].Init(aDataFile);
185         }
186       }
187       else {
188         G4cout << "tabulation type: tabulationType" << G4endl;
189         throw G4HadronicException(
190           __FILE__, __LINE__, "cannot deal with this tabulation type for angular distributions.");
191       }
192     }
193 
194     if (!vct_gammas_par.empty()) {
195       // Reordering cross section data to corrsponding distribution data
196       for (i = 0; i < nDiscrete; ++i) {
197         for (G4int j = 0; j < nDiscrete; ++j) {
198           // Checking gamma and shell to identification
199           if (theGammas[i] == vct_gammas_par[j] && theShells[i] == vct_shells_par[j]) {
200             isPrimary[i] = vct_primary_par[j];
201             disType[i] = vct_distype_par[j];
202             thePartialXsec[i] = (*(vct_pXS_par[j]));
203           }
204         }
205       }
206       // Garbage collection
207       for (auto it = vct_pXS_par.cbegin(); it != vct_pXS_par.cend(); ++it) {
208         delete *it;
209       }
210     }
211   }
212 }
213 
214 void G4ParticleHPPhotonDist::InitEnergies(std::istream& aDataFile)
215 {
216   G4int i, energyDistributionsNeeded = 0;
217   for (i = 0; i < nDiscrete; ++i) {
218     if (disType[i] == 1) energyDistributionsNeeded = 1;
219   }
220   if (energyDistributionsNeeded == 0) return;
221   aDataFile >> nPartials;
222   const std::size_t dsize = nPartials > 0 ? nPartials : 1;
223   distribution = new G4int[dsize];
224   probs = new G4ParticleHPVector[dsize];
225   partials = new G4ParticleHPPartial*[dsize];
226   G4int nen;
227   G4int dummy;
228   for (i = 0; i < nPartials; ++i) {
229     aDataFile >> dummy;
230     probs[i].Init(aDataFile, eV);
231     aDataFile >> nen;
232     partials[i] = new G4ParticleHPPartial(nen);
233     partials[i]->InitInterpolation(aDataFile);
234     partials[i]->Init(aDataFile);
235   }
236 }
237 
238 void G4ParticleHPPhotonDist::InitPartials(std::istream& aDataFile, G4ParticleHPVector* theXsec)
239 {
240   if (theXsec != nullptr) theReactionXsec = theXsec;
241 
242   aDataFile >> nDiscrete >> targetMass;
243   if (nDiscrete != 1) {
244     theTotalXsec.Init(aDataFile, eV);
245   }
246   const std::size_t dsize = nDiscrete > 0 ? nDiscrete : 1;
247   theGammas = new G4double[dsize];
248   theShells = new G4double[dsize];
249   isPrimary = new G4int[dsize];
250   disType = new G4int[dsize];
251   thePartialXsec = new G4ParticleHPVector[dsize];
252   for (std::size_t i = 0; i < dsize; ++i) {
253     aDataFile >> theGammas[i] >> theShells[i] >> isPrimary[i] >> disType[i];
254     theGammas[i] *= eV;
255     theShells[i] *= eV;
256     thePartialXsec[i].Init(aDataFile, eV);
257   }
258 }
259 
260 G4ReactionProductVector* G4ParticleHPPhotonDist::GetPhotons(G4double anEnergy)
261 {
262   // the partial cross-section case is not all in this yet.
263   if (actualMult.Get() == nullptr) {
264     actualMult.Get() = new std::vector<G4int>(nDiscrete);
265   }
266   G4int i, ii, iii;
267   G4int nSecondaries = 0;
268   auto thePhotons = new G4ReactionProductVector;
269 
270   if (repFlag == 1) {
271     G4double current = 0;
272     for (i = 0; i < nDiscrete; ++i) {
273       current = theYield[i].GetY(anEnergy);
274       actualMult.Get()->at(i) = (G4int)G4Poisson(current);  // max cut-off still missing @@@
275       if (nDiscrete == 1 && current < 1.0001) {
276         actualMult.Get()->at(i) = static_cast<G4int>(current);
277         if (current < 1) {
278           actualMult.Get()->at(i) = 0;
279           if (G4UniformRand() < current) actualMult.Get()->at(i) = 1;
280         }
281       }
282       nSecondaries += actualMult.Get()->at(i);
283     }
284     for (i = 0; i < nSecondaries; ++i) {
285       auto theOne = new G4ReactionProduct;
286       theOne->SetDefinition(G4Gamma::Gamma());
287       thePhotons->push_back(theOne);
288     }
289 
290     G4int count = 0;
291 
292     if (nDiscrete == 1 && nPartials == 1) {
293       if (actualMult.Get()->at(0) > 0) {
294         if (disType[0] == 1) {
295           // continuum
296           G4ParticleHPVector* temp;
297           temp = partials[0]->GetY(anEnergy);  //@@@ look at, seems fishy
298           G4double maximumE = temp->GetX(temp->GetVectorLength() - 1);  // This is an assumption.
299 
300           std::vector<G4double> photons_e_best(actualMult.Get()->at(0), 0.0);
301           G4double best = DBL_MAX;
302           G4int maxTry = 1000;
303           for (G4int j = 0; j < maxTry; ++j) {
304             std::vector<G4double> photons_e(actualMult.Get()->at(0), 0.0);
305             for (auto it = photons_e.begin(); it < photons_e.end(); ++it) {
306               *it = temp->Sample();
307             }
308 
309             if (std::accumulate(photons_e.cbegin(), photons_e.cend(), 0.0) > maximumE) {
310               if (std::accumulate(photons_e.cbegin(), photons_e.cend(), 0.0) < best)
311                 photons_e_best = std::move(photons_e);
312               continue;
313             }
314             G4int iphot = 0;
315             for (auto it = photons_e.cbegin(); it < photons_e.cend(); ++it) {
316               thePhotons->operator[](iphot)->SetKineticEnergy(
317                 *it);  // Replace index count, which was not incremented,
318                        // with iphot, which is, as per Artem Zontikov,
319                        // bug report 2167
320               ++iphot;
321             }
322 
323             break;
324           }
325           delete temp;
326         }
327         else {
328           // discrete
329           thePhotons->operator[](count)->SetKineticEnergy(energy[i]);
330         }
331         ++count;
332         if (count > nSecondaries)
333           throw G4HadronicException(__FILE__, __LINE__,
334                                     "G4ParticleHPPhotonDist::GetPhotons inconsistency");
335       }
336     }
337     else {  // nDiscrete != 1 or nPartials != 1
338       for (i = 0; i < nDiscrete; ++i) {
339         for (ii = 0; ii < actualMult.Get()->at(i); ++ii) {
340           if (disType[i] == 1) {
341             // continuum
342             G4double sum = 0, run = 0;
343             for (iii = 0; iii < nPartials; ++iii)
344               sum += probs[iii].GetY(anEnergy);
345             G4double random = G4UniformRand();
346             G4int theP = 0;
347             for (iii = 0; iii < nPartials; ++iii) {
348               run += probs[iii].GetY(anEnergy);
349               theP = iii;
350               if (random < run / sum) break;
351             }
352 
353             if (theP == nPartials) theP = nPartials - 1;  // das sortiert J aus.
354             sum = 0;
355             G4ParticleHPVector* temp;
356             temp = partials[theP]->GetY(anEnergy);  //@@@ look at, seems fishy
357             G4double eGamm = temp->Sample();
358             thePhotons->operator[](count)->SetKineticEnergy(eGamm);
359             delete temp;
360           }
361           else {
362             // discrete
363             thePhotons->operator[](count)->SetKineticEnergy(energy[i]);
364           }
365           ++count;
366           if (count > nSecondaries)
367             throw G4HadronicException(__FILE__, __LINE__,
368                                       "G4ParticleHPPhotonDist::GetPhotons inconsistency");
369         }
370       }
371     }
372 
373     // now do the angular distributions...
374     if (isoFlag == 1) {
375       for (i = 0; i < nSecondaries; ++i) {
376         G4double costheta = 2. * G4UniformRand() - 1;
377         G4double theta = std::acos(costheta);
378         G4double phi = twopi * G4UniformRand();
379         G4double sinth = std::sin(theta);
380         G4double en = thePhotons->operator[](i)->GetTotalEnergy();
381         G4ThreeVector temp(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
382                            en * std::cos(theta));
383         thePhotons->operator[](i)->SetMomentum(temp);
384       }
385     }
386     else {
387       for (i = 0; i < nSecondaries; ++i) {
388         G4double currentEnergy = thePhotons->operator[](i)->GetTotalEnergy();
389         for (ii = 0; ii < nDiscrete2; ++ii) {
390           if (std::abs(currentEnergy - theGammas[ii]) < 0.1 * keV) break;
391         }
392         if (ii == nDiscrete2)
393           --ii;  // fix for what seems an (file12 vs file 14) inconsistency found in the ENDF 7N14
394                  // data. @@
395         if (ii < nIso) {
396           // isotropic distribution
397           //
398           // Fix Bugzilla report #1745
399           // G4double theta = pi*G4UniformRand();
400           G4double costheta = 2. * G4UniformRand() - 1;
401           G4double theta = std::acos(costheta);
402           G4double phi = twopi * G4UniformRand();
403           G4double sinth = std::sin(theta);
404           G4double en = thePhotons->operator[](i)->GetTotalEnergy();
405           // DHW G4ThreeVector tempVector(en*sinth*std::cos(phi), en*sinth*std::sin(phi),
406           // en*std::cos(theta) );
407           G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
408                                    en * costheta);
409           thePhotons->operator[](i)->SetMomentum(tempVector);
410         }
411         else if (tabulationType == 1) {
412           // legendre polynomials
413           G4int it(0);
414           for (iii = 0; iii < nNeu[ii - nIso]; ++iii)  // find the neutron energy
415           {
416             it = iii;
417             if (theLegendre[ii - nIso][iii].GetEnergy() > anEnergy) break;
418           }
419           G4ParticleHPLegendreStore aStore(2);
420           aStore.SetCoeff(1, &(theLegendre[ii - nIso][it]));
421           if (it > 0) {
422             aStore.SetCoeff(0, &(theLegendre[ii - nIso][it - 1]));
423           }
424           else {
425             aStore.SetCoeff(0, &(theLegendre[ii - nIso][it]));
426           }
427           G4double cosTh = aStore.SampleMax(anEnergy);
428           G4double theta = std::acos(cosTh);
429           G4double phi = twopi * G4UniformRand();
430           G4double sinth = std::sin(theta);
431           G4double en = thePhotons->operator[](i)->GetTotalEnergy();
432           G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
433                                    en * std::cos(theta));
434           thePhotons->operator[](i)->SetMomentum(tempVector);
435         }
436         else {
437           // tabulation of probabilities.
438           G4int it(0);
439           for (iii = 0; iii < nNeu[ii - nIso]; ++iii)  // find the neutron energy
440           {
441             it = iii;
442             if (theAngular[ii - nIso][iii].GetEnergy() > anEnergy) break;
443           }
444           G4double costh = theAngular[ii - nIso][it].GetCosTh();  // no interpolation yet @@
445           G4double theta = std::acos(costh);
446           G4double phi = twopi * G4UniformRand();
447           G4double sinth = std::sin(theta);
448           G4double en = thePhotons->operator[](i)->GetTotalEnergy();
449           G4ThreeVector tmpVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
450                                   en * costh);
451           thePhotons->operator[](i)->SetMomentum(tmpVector);
452         }
453       }
454     }
455   }
456   else if (repFlag == 2) {
457     auto running = new G4double[nGammaEnergies];
458     running[0] = theTransitionProbabilities[0];
459     for (i = 1; i < nGammaEnergies; ++i) {
460       running[i] = running[i - 1] + theTransitionProbabilities[i];
461     }
462     G4double random = G4UniformRand();
463     G4int it = 0;
464     for (i = 0; i < nGammaEnergies; ++i) {
465       it = i;
466       if (random < running[i] / running[nGammaEnergies - 1]) break;
467     }
468     delete[] running;
469     G4double totalEnergy = theBaseEnergy - theLevelEnergies[it];
470     auto theOne = new G4ReactionProduct;
471     theOne->SetDefinition(G4Gamma::Gamma());
472     random = G4UniformRand();
473     if (theInternalConversionFlag == 2 && random > thePhotonTransitionFraction[it]) {
474       theOne->SetDefinition(G4Electron::Electron());
475       // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
476       // 2009 But never enter at least with G4NDL3.13
477       totalEnergy +=
478         G4Electron::Electron()->GetPDGMass();  // proposed correction: add this line for electron
479     }
480     theOne->SetTotalEnergy(totalEnergy);
481     if (isoFlag == 1) {
482       G4double costheta = 2. * G4UniformRand() - 1;
483       G4double theta = std::acos(costheta);
484       G4double phi = twopi * G4UniformRand();
485       G4double sinth = std::sin(theta);
486       // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
487       // 2009 G4double en = theOne->GetTotalEnergy();
488       G4double en = theOne->GetTotalMomentum();
489       // But never cause real effect at least with G4NDL3.13 TK
490       G4ThreeVector temp(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
491                          en * std::cos(theta));
492       theOne->SetMomentum(temp);
493     }
494     else {
495       G4double currentEnergy = theOne->GetTotalEnergy();
496       for (ii = 0; ii < nDiscrete2; ++ii) {
497         if (std::abs(currentEnergy - theGammas[ii]) < 0.1 * keV) break;
498       }
499       if (ii == nDiscrete2)
500         --ii;  // fix for what seems an (file12 vs file 14) inconsistency found in the ENDF 7N14
501                // data. @@
502       if (ii < nIso) {
503         // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
504         // 2009
505         //  isotropic distribution
506         // G4double theta = pi*G4UniformRand();
507         G4double theta = std::acos(2. * G4UniformRand() - 1.);
508         // But this is alos never cause real effect at least with G4NDL3.13 TK  not repFlag == 2 AND
509         // isoFlag != 1
510         G4double phi = twopi * G4UniformRand();
511         G4double sinth = std::sin(theta);
512         // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
513         // 2009 G4double en = theOne->GetTotalEnergy();
514         G4double en = theOne->GetTotalMomentum();
515         // But never cause real effect at least with G4NDL3.13 TK
516         G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
517                                  en * std::cos(theta));
518         theOne->SetMomentum(tempVector);
519       }
520       else if (tabulationType == 1) {
521         // legendre polynomials
522         G4int itt(0);
523         for (iii = 0; iii < nNeu[ii - nIso]; ++iii)  // find the neutron energy
524         {
525           itt = iii;
526           if (theLegendre[ii - nIso][iii].GetEnergy() > anEnergy) break;
527         }
528         G4ParticleHPLegendreStore aStore(2);
529         aStore.SetCoeff(1, &(theLegendre[ii - nIso][itt]));
530         // aStore.SetCoeff(0, &(theLegendre[ii-nIso][it-1]));
531         // TKDB 110512
532         if (itt > 0) {
533           aStore.SetCoeff(0, &(theLegendre[ii - nIso][itt - 1]));
534         }
535         else {
536           aStore.SetCoeff(0, &(theLegendre[ii - nIso][itt]));
537         }
538         G4double cosTh = aStore.SampleMax(anEnergy);
539         G4double theta = std::acos(cosTh);
540         G4double phi = twopi * G4UniformRand();
541         G4double sinth = std::sin(theta);
542         // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
543         // 2009 G4double en = theOne->GetTotalEnergy();
544         G4double en = theOne->GetTotalMomentum();
545         // But never cause real effect at least with G4NDL3.13 TK
546         G4ThreeVector tempVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi),
547                                  en * std::cos(theta));
548         theOne->SetMomentum(tempVector);
549       }
550       else {
551         // tabulation of probabilities.
552         G4int itt(0);
553         for (iii = 0; iii < nNeu[ii - nIso]; ++iii)  // find the neutron energy
554         {
555           itt = iii;
556           if (theAngular[ii - nIso][iii].GetEnergy() > anEnergy) break;
557         }
558         G4double costh = theAngular[ii - nIso][itt].GetCosTh();  // no interpolation yet @@
559         G4double theta = std::acos(costh);
560         G4double phi = twopi * G4UniformRand();
561         G4double sinth = std::sin(theta);
562         // Bug reported Chao Zhang (Chao.Zhang@usd.edu), Dongming Mei(Dongming.Mei@usd.edu) Feb. 25,
563         // 2009 G4double en = theOne->GetTotalEnergy();
564         G4double en = theOne->GetTotalMomentum();
565         // But never cause real effect at least with G4NDL3.13 TK
566         G4ThreeVector tmpVector(en * sinth * std::cos(phi), en * sinth * std::sin(phi), en * costh);
567         theOne->SetMomentum(tmpVector);
568       }
569     }
570     thePhotons->push_back(theOne);
571   }
572   else if (repFlag == 0) {
573     if (thePartialXsec == nullptr) {
574       return thePhotons;
575     }
576 
577     // Partial Case
578 
579     auto theOne = new G4ReactionProduct;
580     theOne->SetDefinition(G4Gamma::Gamma());
581     thePhotons->push_back(theOne);
582 
583     // Energy
584 
585     G4double sum = 0.0;
586     std::vector<G4double> dif(nDiscrete, 0.0);
587     for (G4int j = 0; j < nDiscrete; ++j) {
588       G4double x = thePartialXsec[j].GetXsec(anEnergy);  // x in barn
589       if (x > 0) {
590         sum += x;
591       }
592       dif[j] = sum;
593     }
594 
595     G4double rand = G4UniformRand();
596 
597     G4int iphoton = 0;
598     for (G4int j = 0; j < nDiscrete; ++j) {
599       G4double y = rand * sum;
600       if (dif[j] > y) {
601         iphoton = j;
602         break;
603       }
604     }
605 
606     // Statistically suppress the photon according to reaction cross section
607     // Fix proposed by Artem Zontikov, Bug report #1824
608     if (theReactionXsec != nullptr) {
609       if (thePartialXsec[iphoton].GetXsec(anEnergy) / theReactionXsec->GetXsec(anEnergy)
610           < G4UniformRand())
611       {
612         delete thePhotons;
613         thePhotons = nullptr;
614         return thePhotons;
615       }
616     }
617 
618     // Angle
619     G4double cosTheta = 0.0;  // mu
620 
621     if (isoFlag == 1) {
622       // Isotropic Case
623 
624       cosTheta = 2. * G4UniformRand() - 1;
625     }
626     else {
627       if (iphoton < nIso) {
628         // still Isotropic
629 
630         cosTheta = 2. * G4UniformRand() - 1;
631       }
632       else {
633         if (tabulationType == 1) {
634           // Legendre polynomials
635 
636           G4int iangle = 0;
637           for (G4int j = 0; j < nNeu[iphoton - nIso]; ++j) {
638             iangle = j;
639             if (theLegendre[iphoton - nIso][j].GetEnergy() > anEnergy) break;
640           }
641 
642           G4ParticleHPLegendreStore aStore(2);
643           aStore.SetCoeff(1, &(theLegendre[iphoton - nIso][iangle]));
644           aStore.SetCoeff(0, &(theLegendre[iphoton - nIso][iangle - 1]));
645 
646           cosTheta = aStore.SampleMax(anEnergy);
647         }
648         else if (tabulationType == 2) {
649           // tabulation of probabilities.
650 
651           G4int iangle = 0;
652           for (G4int j = 0; j < nNeu[iphoton - nIso]; ++j) {
653             iangle = j;
654             if (theAngular[iphoton - nIso][j].GetEnergy() > anEnergy) break;
655           }
656           cosTheta = theAngular[iphoton - nIso][iangle].GetCosTh();
657           // no interpolation yet @@
658         }
659       }
660     }
661 
662     // Set
663     G4double phi = twopi * G4UniformRand();
664     G4double theta = std::acos(cosTheta);
665     G4double sinTheta = std::sin(theta);
666 
667     G4double photonE = theGammas[iphoton];
668     G4ThreeVector direction(sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta);
669     G4ThreeVector photonP = photonE * direction;
670     thePhotons->operator[](0)->SetMomentum(photonP);
671   }
672   else {
673     delete thePhotons;
674     thePhotons = nullptr;  // no gamma data available; some work needed @@@@@@@
675   }
676   return thePhotons;
677 }
678