Files
geant4/source/processes/hadronic/models/particle_hp/include/G4ParticleHPVector.hh
T
2023-06-30 09:09:57 +02:00

536 lines
16 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. *
// ********************************************************************
//
//
// 070606 fix with Valgrind by T. Koi
// 080409 Fix div0 error with G4FPE by T. Koi
// 080811 Comment out unused method SetBlocked and SetBuffered
// Add required cleaning up in CleanUp by T. Koi
//
// P. Arce, June-2014 Conversion neutron_hp to particle_hp
//
#ifndef G4ParticleHPVector_h
#define G4ParticleHPVector_h 1
#include "G4Exp.hh"
#include "G4InterpolationManager.hh"
#include "G4Log.hh"
#include "G4ParticleHPDataPoint.hh"
#include "G4ParticleHPHash.hh"
#include "G4ParticleHPInterpolator.hh"
#include "G4PhysicsVector.hh"
#include "G4Pow.hh"
#include "G4ios.hh"
#include "Randomize.hh"
#include <cmath>
#include <fstream>
#include <vector>
#if defined WIN32 - VC
# include <float.h>
#endif
class G4ParticleHPVector
{
friend G4ParticleHPVector& operator+(G4ParticleHPVector& left, G4ParticleHPVector& right);
public:
G4ParticleHPVector();
G4ParticleHPVector(G4int n);
~G4ParticleHPVector();
G4ParticleHPVector& operator=(const G4ParticleHPVector& right);
inline void SetVerbose(G4int ff) { Verbose = ff; }
inline void Times(G4double factor)
{
G4int i;
for (i = 0; i < nEntries; i++) {
theData[i].SetY(theData[i].GetY() * factor);
}
if (theIntegral != nullptr) {
theIntegral[i] *= factor;
}
}
inline void SetPoint(G4int i, const G4ParticleHPDataPoint& it)
{
G4double x = it.GetX();
G4double y = it.GetY();
SetData(i, x, y);
}
inline void SetData(G4int i, G4double x, G4double y)
{
// G4cout <<"G4ParticleHPVector::SetData called"<<nPoints<<" "<<nEntries<<G4endl;
Check(i);
if (y > maxValue) maxValue = y;
theData[i].SetData(x, y);
}
inline void SetX(G4int i, G4double e)
{
Check(i);
theData[i].SetX(e);
}
inline void SetEnergy(G4int i, G4double e)
{
Check(i);
theData[i].SetX(e);
}
inline void SetY(G4int i, G4double x)
{
Check(i);
if (x > maxValue) maxValue = x;
theData[i].SetY(x);
}
inline void SetXsec(G4int i, G4double x)
{
Check(i);
if (x > maxValue) maxValue = x;
theData[i].SetY(x);
}
inline G4double GetEnergy(G4int i) const { return theData[i].GetX(); }
inline G4double GetXsec(G4int i) { return theData[i].GetY(); }
inline G4double GetX(G4int i) const
{
if (i < 0) i = 0;
if (i >= GetVectorLength()) i = GetVectorLength() - 1;
return theData[i].GetX();
}
inline const G4ParticleHPDataPoint& GetPoint(G4int i) const { return theData[i]; }
void Hash()
{
G4int i;
G4double x, y;
for (i = 0; i < nEntries; i++) {
if (0 == (i + 1) % 10) {
x = GetX(i);
y = GetY(i);
theHash.SetData(i, x, y);
}
}
}
void ReHash()
{
theHash.Clear();
Hash();
}
G4double GetXsec(G4double e);
G4double GetXsec(G4double e, G4int min)
{
G4int i;
for (i = min; i < nEntries; i++) {
if (theData[i].GetX() > e) break;
}
G4int low = i - 1;
G4int high = i;
if (i == 0) {
low = 0;
high = 1;
}
else if (i == nEntries) {
low = nEntries - 2;
high = nEntries - 1;
}
G4double y;
if (e < theData[nEntries - 1].GetX()) {
// Protect against doubled-up x values
if ((theData[high].GetX() - theData[low].GetX()) / theData[high].GetX() < 0.000001) {
y = theData[low].GetY();
}
else {
y = theInt.Interpolate(theManager.GetScheme(high), e, theData[low].GetX(),
theData[high].GetX(), theData[low].GetY(), theData[high].GetY());
}
}
else {
y = theData[nEntries - 1].GetY();
}
return y;
}
inline G4double GetY(G4double x) { return GetXsec(x); }
inline G4int GetVectorLength() const { return nEntries; }
inline G4double GetY(G4int i)
{
if (i < 0) i = 0;
if (i >= GetVectorLength()) i = GetVectorLength() - 1;
return theData[i].GetY();
}
inline G4double GetY(G4int i) const
{
if (i < 0) i = 0;
if (i >= GetVectorLength()) i = GetVectorLength() - 1;
return theData[i].GetY();
}
void Dump();
inline void InitInterpolation(std::istream& aDataFile) { theManager.Init(aDataFile); }
void Init(std::istream& aDataFile, G4int total, G4double ux = 1., G4double uy = 1.)
{
G4double x, y;
for (G4int i = 0; i < total; i++) {
aDataFile >> x >> y;
x *= ux;
y *= uy;
SetData(i, x, y);
if (0 == nEntries % 10) {
theHash.SetData(nEntries - 1, x, y);
}
}
}
void Init(std::istream& aDataFile, G4double ux = 1., G4double uy = 1.)
{
G4int total;
aDataFile >> total;
delete[] theData;
theData = new G4ParticleHPDataPoint[total];
nPoints = total;
nEntries = 0;
theManager.Init(aDataFile);
Init(aDataFile, total, ux, uy);
}
void ThinOut(G4double precision);
inline void SetLabel(G4double aLabel) { label = aLabel; }
inline G4double GetLabel() { return label; }
inline void CleanUp()
{
nEntries = 0;
theManager.CleanUp();
maxValue = -DBL_MAX;
theHash.Clear();
// 080811 TK DB
delete[] theIntegral;
theIntegral = nullptr;
}
// merges the vectors active and passive into *this
inline void Merge(G4ParticleHPVector* active, G4ParticleHPVector* passive)
{
CleanUp();
G4int s_tmp = 0, n = 0, m_tmp = 0;
G4ParticleHPVector* tmp;
G4int a = s_tmp, p = n, t;
while (a < active->GetVectorLength()
&& p < passive->GetVectorLength()) // Loop checking, 11.05.2015, T. Koi
{
if (active->GetEnergy(a) <= passive->GetEnergy(p)) {
G4double xa = active->GetEnergy(a);
G4double yy = active->GetXsec(a);
SetData(m_tmp, xa, yy);
theManager.AppendScheme(m_tmp, active->GetScheme(a));
m_tmp++;
a++;
G4double xp = passive->GetEnergy(p);
// 080409 TKDB
// if( std::abs(std::abs(xp-xa)/xa)<0.001 ) p++;
if (!(xa == 0) && std::abs(std::abs(xp - xa) / xa) < 0.001) p++;
}
else {
tmp = active;
t = a;
active = passive;
a = p;
passive = tmp;
p = t;
}
}
while (a != active->GetVectorLength()) // Loop checking, 11.05.2015, T. Koi
{
SetData(m_tmp, active->GetEnergy(a), active->GetXsec(a));
theManager.AppendScheme(m_tmp++, active->GetScheme(a));
a++;
}
while (p != passive->GetVectorLength()) // Loop checking, 11.05.2015, T. Koi
{
if (std::abs(GetEnergy(m_tmp - 1) - passive->GetEnergy(p)) / passive->GetEnergy(p) > 0.001)
// if(std::abs(GetEnergy(m)-passive->GetEnergy(p))/passive->GetEnergy(p)>0.001)
{
SetData(m_tmp, passive->GetEnergy(p), passive->GetXsec(p));
theManager.AppendScheme(m_tmp++, active->GetScheme(p));
}
p++;
}
}
void Merge(G4InterpolationScheme aScheme, G4double aValue, G4ParticleHPVector* active,
G4ParticleHPVector* passive);
G4double SampleLin() // Samples X according to distribution Y, linear int
{
G4double result;
if (theIntegral == nullptr) IntegrateAndNormalise();
if (GetVectorLength() == 1) {
result = theData[0].GetX();
}
else {
G4int i;
G4double rand = G4UniformRand();
// this was replaced
// for(i=1;i<GetVectorLength();i++)
// {
// if(rand<theIntegral[i]/theIntegral[GetVectorLength()-1]) break;
// }
// by this (begin)
for (i = GetVectorLength() - 1; i >= 0; i--) {
if (rand > theIntegral[i] / theIntegral[GetVectorLength() - 1]) break;
}
if (i != GetVectorLength() - 1) i++;
// until this (end)
G4double x1, x2, y1, y2;
y1 = theData[i - 1].GetX();
x1 = theIntegral[i - 1];
y2 = theData[i].GetX();
x2 = theIntegral[i];
if (std::abs((y2 - y1) / y2)
< 0.0000001) // not really necessary, since the case is excluded by construction
{
y1 = theData[i - 2].GetX();
x1 = theIntegral[i - 2];
}
result = theLin.Lin(rand, x1, x2, y1, y2);
}
return result;
}
G4double Sample(); // Samples X according to distribution Y
G4double* Debug() { return theIntegral; }
inline void IntegrateAndNormalise()
{
G4int i;
if (theIntegral != nullptr) return;
theIntegral = new G4double[nEntries];
if (nEntries == 1) {
theIntegral[0] = 1;
return;
}
theIntegral[0] = 0;
G4double sum = 0;
G4double x1 = 0;
G4double x0 = 0;
for (i = 1; i < GetVectorLength(); i++) {
x1 = theData[i].GetX();
x0 = theData[i - 1].GetX();
if (std::abs(x1 - x0) > std::abs(x1 * 0.0000001)) {
//********************************************************************
// EMendoza -> the interpolation scheme is not always lin-lin
/*
sum+= 0.5*(theData[i].GetY()+theData[i-1].GetY())*
(x1-x0);
*/
//********************************************************************
G4InterpolationScheme aScheme = theManager.GetScheme(i);
G4double y0 = theData[i - 1].GetY();
G4double y1 = theData[i].GetY();
G4double integ = theInt.GetBinIntegral(aScheme, x0, x1, y0, y1);
#if defined WIN32 - VC
if (!_finite(integ)) {
integ = 0;
}
#elif defined __IBMCPP__
if (isinf(integ) || isnan(integ)) {
integ = 0;
}
#else
if (std::isinf(integ) || std::isnan(integ)) {
integ = 0;
}
#endif
sum += integ;
//********************************************************************
}
theIntegral[i] = sum;
}
G4double total = theIntegral[GetVectorLength() - 1];
for (i = 1; i < GetVectorLength(); i++) {
theIntegral[i] /= total;
}
}
inline void Integrate()
{
G4int i;
if (nEntries == 1) {
totalIntegral = 0;
return;
}
G4double sum = 0;
for (i = 1; i < GetVectorLength(); i++) {
if (std::abs((theData[i].GetX() - theData[i - 1].GetX()) / theData[i].GetX()) > 0.0000001) {
G4double x1 = theData[i - 1].GetX();
G4double x2 = theData[i].GetX();
G4double y1 = theData[i - 1].GetY();
G4double y2 = theData[i].GetY();
G4InterpolationScheme aScheme = theManager.GetScheme(i);
if (aScheme == LINLIN || aScheme == CLINLIN || aScheme == ULINLIN) {
sum += 0.5 * (y2 + y1) * (x2 - x1);
}
else if (aScheme == LINLOG || aScheme == CLINLOG || aScheme == ULINLOG) {
G4double a = y1;
G4double b = (y2 - y1) / (G4Log(x2) - G4Log(x1));
sum += (a - b) * (x2 - x1) + b * (x2 * G4Log(x2) - x1 * G4Log(x1));
}
else if (aScheme == LOGLIN || aScheme == CLOGLIN || aScheme == ULOGLIN) {
G4double a = G4Log(y1);
G4double b = (G4Log(y2) - G4Log(y1)) / (x2 - x1);
sum += (G4Exp(a) / b) * (G4Exp(b * x2) - G4Exp(b * x1));
}
else if (aScheme == HISTO || aScheme == CHISTO || aScheme == UHISTO) {
sum += y1 * (x2 - x1);
}
else if (aScheme == LOGLOG || aScheme == CLOGLOG || aScheme == ULOGLOG) {
G4double a = G4Log(y1);
G4double b = (G4Log(y2) - G4Log(y1)) / (G4Log(x2) - G4Log(x1));
sum +=
(G4Exp(a) / (b + 1))
* (G4Pow::GetInstance()->powA(x2, b + 1) - G4Pow::GetInstance()->powA(x1, b + 1));
}
else {
throw G4HadronicException(
__FILE__, __LINE__, "Unknown interpolation scheme in G4ParticleHPVector::Integrate");
}
}
}
totalIntegral = sum;
}
inline G4double GetIntegral() // linear interpolation; use with care
{
if (totalIntegral < -0.5) Integrate();
return totalIntegral;
}
inline void SetInterpolationManager(const G4InterpolationManager& aManager)
{
theManager = aManager;
}
inline const G4InterpolationManager& GetInterpolationManager() const { return theManager; }
inline void SetInterpolationManager(G4InterpolationManager& aMan) { theManager = aMan; }
inline void SetScheme(G4int aPoint, const G4InterpolationScheme& aScheme)
{
theManager.AppendScheme(aPoint, aScheme);
}
inline G4InterpolationScheme GetScheme(G4int anIndex) { return theManager.GetScheme(anIndex); }
G4double GetMeanX()
{
G4double result;
G4double running = 0;
G4double weighted = 0;
for (G4int i = 1; i < nEntries; i++) {
running +=
theInt.GetBinIntegral(theManager.GetScheme(i - 1), theData[i - 1].GetX(),
theData[i].GetX(), theData[i - 1].GetY(), theData[i].GetY());
weighted += theInt.GetWeightedBinIntegral(theManager.GetScheme(i - 1),
theData[i - 1].GetX(), theData[i].GetX(),
theData[i - 1].GetY(), theData[i].GetY());
}
result = weighted / running;
return result;
}
// Finds maximum cross section between two values of kinetic energy
G4double GetMaxY(G4double emin, G4double emax);
/*
void Block(G4double aX)
{
theBlocked.push_back(aX);
}
void Buffer(G4double aX)
{
theBuffered.push_back(aX);
}
*/
std::vector<G4double> GetBlocked() { return theBlocked; }
std::vector<G4double> GetBuffered() { return theBuffered; }
// void SetBlocked(const std::vector<G4double> &aBlocked) {theBlocked = aBlocked;}
// void SetBuffered(const std::vector<G4double> &aBuffer) {theBuffered = aBuffer;}
G4double Get15percentBorder();
G4double Get50percentBorder();
private:
void Check(G4int i);
G4bool IsBlocked(G4double aX);
private:
G4ParticleHPInterpolator theLin;
private:
G4double totalIntegral;
G4ParticleHPDataPoint* theData; // the data
G4InterpolationManager theManager; // knows how to interpolate the data.
G4double* theIntegral;
G4int nEntries;
G4int nPoints;
G4double label;
G4ParticleHPInterpolator theInt;
G4int Verbose;
// debug only
G4int isFreed;
G4ParticleHPHash theHash;
G4double maxValue;
std::vector<G4double> theBlocked;
std::vector<G4double> theBuffered;
G4double the15percentBorderCash;
G4double the50percentBorderCash;
};
#endif