Import Geant4 10.7.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2020-06-26 10:23:25 +02:00
parent c02c370437
commit 67ba86d073
1871 changed files with 174422 additions and 131884 deletions
@@ -23,21 +23,23 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4AnalyticalPolSolver class implementation
//
//
// Author: V.Grichine, 24.04.97
// --------------------------------------------------------------------
#include "globals.hh"
#include <complex>
#include "globals.hh"
#include <complex>
#include "G4AnalyticalPolSolver.hh"
//////////////////////////////////////////////////////////////////////////////
G4AnalyticalPolSolver::G4AnalyticalPolSolver() {;}
G4AnalyticalPolSolver::G4AnalyticalPolSolver() { ; }
//////////////////////////////////////////////////////////////////////////////
G4AnalyticalPolSolver::~G4AnalyticalPolSolver() {;}
G4AnalyticalPolSolver::~G4AnalyticalPolSolver() { ; }
//////////////////////////////////////////////////////////////////////////////
//
@@ -46,29 +48,29 @@ G4AnalyticalPolSolver::~G4AnalyticalPolSolver() {;}
//
// x = r[1][k] + i r[2][k]; k = 1, 2
G4int G4AnalyticalPolSolver::QuadRoots( G4double p[5], G4double r[3][5] )
G4int G4AnalyticalPolSolver::QuadRoots(G4double p[5], G4double r[3][5])
{
G4double b, c, d2, d;
b = -p[1]/p[0]/2.;
c = p[2]/p[0];
d2 = b*b - c;
if( d2 >= 0. )
b = -p[1] / p[0] / 2.;
c = p[2] / p[0];
d2 = b * b - c;
if(d2 >= 0.)
{
d = std::sqrt(d2);
r[1][1] = b - d;
r[1][2] = b + d;
r[2][1] = 0.;
r[1][1] = b - d;
r[1][2] = b + d;
r[2][1] = 0.;
r[2][2] = 0.;
}
else
{
d = std::sqrt(-d2);
r[2][1] = d;
r[2][1] = d;
r[2][2] = -d;
r[1][1] = b;
r[1][2] = b;
r[1][1] = b;
r[1][2] = b;
}
return 2;
@@ -81,83 +83,113 @@ G4int G4AnalyticalPolSolver::QuadRoots( G4double p[5], G4double r[3][5] )
// x=r[1][k] + i r[2][k] k=1,...,3
// Assumes 0<arctan(x)<pi/2 for x>0
G4int G4AnalyticalPolSolver::CubicRoots( G4double p[5], G4double r[3][5] )
G4int G4AnalyticalPolSolver::CubicRoots(G4double p[5], G4double r[3][5])
{
G4double x,t,b,c,d;
G4double x, t, b, c, d;
G4int k;
if( p[0] != 1. )
if(p[0] != 1.)
{
for(k = 1; k < 4; k++ ) { p[k] = p[k]/p[0]; }
for(k = 1; k < 4; k++)
{
p[k] = p[k] / p[0];
}
p[0] = 1.;
}
x = p[1]/3.0;
t = x*p[1];
b = 0.5*( x*( t/1.5 - p[2] ) + p[3] );
t = ( t - p[2] )/3.0;
c = t*t*t;
d = b*b - c;
x = p[1] / 3.0;
t = x * p[1];
b = 0.5 * (x * (t / 1.5 - p[2]) + p[3]);
t = (t - p[2]) / 3.0;
c = t * t * t;
d = b * b - c;
if( d >= 0. )
if(d >= 0.)
{
d = std::pow( (std::sqrt(d) + std::fabs(b) ), 1.0/3.0 );
if( d != 0. )
{
if( b > 0. ) { b = -d; }
else { b = d; }
c = t/b;
}
d = std::sqrt(0.75)*(b - c);
r[2][2] = d;
b = b + c;
c = -0.5*b-x;
r[1][2] = c;
d = std::pow((std::sqrt(d) + std::fabs(b)), 1.0 / 3.0);
if( ( b > 0. && x <= 0. ) || ( b < 0. && x > 0. ) )
if(d != 0.)
{
r[1][1] = c;
r[2][1] = -d;
r[1][3] = b - x;
r[2][3] = 0;
if(b > 0.)
{
b = -d;
}
else
{
b = d;
}
c = t / b;
}
d = std::sqrt(0.75) * (b - c);
r[2][2] = d;
b = b + c;
c = -0.5 * b - x;
r[1][2] = c;
if((b > 0. && x <= 0.) || (b < 0. && x > 0.))
{
r[1][1] = c;
r[2][1] = -d;
r[1][3] = b - x;
r[2][3] = 0;
}
else
{
r[1][1] = b - x;
r[2][1] = 0.;
r[1][3] = c;
r[2][3] = -d;
r[1][1] = b - x;
r[2][1] = 0.;
r[1][3] = c;
r[2][3] = -d;
}
} // end of 2 equal or complex roots
} // end of 2 equal or complex roots
else
{
if( b == 0. ) { d = std::atan(1.0)/1.5; }
else { d = std::atan( std::sqrt(-d)/std::fabs(b) )/3.0; }
if( b < 0. ) { b = std::sqrt(t)*2.0; }
else { b = -2.0*std::sqrt(t); }
c = std::cos(d)*b;
t = -std::sqrt(0.75)*std::sin(d)*b - 0.5*c;
d = -t - c - x;
c = c - x;
t = t - x;
if( std::fabs(c) > std::fabs(t) ) { r[1][3] = c; }
if(b == 0.)
{
d = std::atan(1.0) / 1.5;
}
else
{
r[1][3] = t;
d = std::atan(std::sqrt(-d) / std::fabs(b)) / 3.0;
}
if(b < 0.)
{
b = std::sqrt(t) * 2.0;
}
else
{
b = -2.0 * std::sqrt(t);
}
c = std::cos(d) * b;
t = -std::sqrt(0.75) * std::sin(d) * b - 0.5 * c;
d = -t - c - x;
c = c - x;
t = t - x;
if(std::fabs(c) > std::fabs(t))
{
r[1][3] = c;
}
else
{
r[1][3] = t;
t = c;
}
if( std::fabs(d) > std::fabs(t) ) { r[1][2] = d; }
if(std::fabs(d) > std::fabs(t))
{
r[1][2] = d;
}
else
{
r[1][2] = t;
r[1][2] = t;
t = d;
}
r[1][1] = t;
for(k = 1; k < 4; k++ ) { r[2][k] = 0.; }
for(k = 1; k < 4; k++)
{
r[2][k] = 0.;
}
}
return 0;
}
@@ -168,107 +200,143 @@ G4int G4AnalyticalPolSolver::CubicRoots( G4double p[5], G4double r[3][5] )
// Roots of poly p[0] x^4 + p[1] x^3...+p[4]=0
// x=r[1][k] + i r[2][k] k=1,...,4
G4int G4AnalyticalPolSolver::BiquadRoots( G4double p[5], G4double r[3][5] )
G4int G4AnalyticalPolSolver::BiquadRoots(G4double p[5], G4double r[3][5])
{
G4double a, b, c, d, e;
G4int i, k, j;
if(p[0] != 1.0)
{
for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
for(k = 1; k < 5; k++)
{
p[k] = p[k] / p[0];
}
p[0] = 1.;
}
e = 0.25*p[1];
b = 2*e;
c = b*b;
d = 0.75*c;
b = p[3] + b*( c - p[2] );
e = 0.25 * p[1];
b = 2 * e;
c = b * b;
d = 0.75 * c;
b = p[3] + b * (c - p[2]);
a = p[2] - d;
c = p[4] + e*( e*a - p[3] );
c = p[4] + e * (e * a - p[3]);
a = a - d;
p[1] = 0.5*a;
p[2] = (p[1]*p[1]-c)*0.25;
p[3] = b*b/(-64.0);
p[1] = 0.5 * a;
p[2] = (p[1] * p[1] - c) * 0.25;
p[3] = b * b / (-64.0);
if( p[3] < 0. )
if(p[3] < 0.)
{
CubicRoots(p,r);
CubicRoots(p, r);
for( k = 1; k < 4; k++ )
for(k = 1; k < 4; k++)
{
if( r[2][k] == 0. && r[1][k] > 0 )
if(r[2][k] == 0. && r[1][k] > 0)
{
d = r[1][k]*4;
d = r[1][k] * 4;
a = a + d;
if ( a >= 0. && b >= 0.) { p[1] = std::sqrt(d); }
else if( a <= 0. && b <= 0.) { p[1] = std::sqrt(d); }
else { p[1] = -std::sqrt(d); }
b = 0.5*( a + b/p[1] );
p[2] = c/b;
QuadRoots(p,r);
for( i = 1; i < 3; i++ )
if(a >= 0. && b >= 0.)
{
for( j = 1; j < 3; j++ ) { r[j][i+2] = r[j][i]; }
p[1] = std::sqrt(d);
}
else if(a <= 0. && b <= 0.)
{
p[1] = std::sqrt(d);
}
else
{
p[1] = -std::sqrt(d);
}
p[1] = -p[1];
p[2] = b;
QuadRoots(p,r);
for( i = 1; i < 5; i++ ) { r[1][i] = r[1][i] - e; }
b = 0.5 * (a + b / p[1]);
p[2] = c / b;
QuadRoots(p, r);
for(i = 1; i < 3; i++)
{
for(j = 1; j < 3; j++)
{
r[j][i + 2] = r[j][i];
}
}
p[1] = -p[1];
p[2] = b;
QuadRoots(p, r);
for(i = 1; i < 5; i++)
{
r[1][i] = r[1][i] - e;
}
return 4;
}
}
}
if( p[2] < 0. )
if(p[2] < 0.)
{
b = std::sqrt(c);
b = std::sqrt(c);
d = b + b - a;
p[1] = 0.;
if( d > 0. ) { p[1] = std::sqrt(d); }
p[1] = 0.;
if(d > 0.)
{
p[1] = std::sqrt(d);
}
}
else
{
if( p[1] > 0.) { b = std::sqrt(p[2])*2.0 + p[1]; }
else { b = -std::sqrt(p[2])*2.0 + p[1]; }
if( b != 0.) { p[1] = 0; }
if(p[1] > 0.)
{
b = std::sqrt(p[2]) * 2.0 + p[1];
}
else
{
for(k = 1; k < 5; k++ )
b = -std::sqrt(p[2]) * 2.0 + p[1];
}
if(b != 0.)
{
p[1] = 0;
}
else
{
for(k = 1; k < 5; k++)
{
r[1][k] = -e;
r[2][k] = 0;
r[1][k] = -e;
r[2][k] = 0;
}
return 0;
}
}
p[2] = c/b;
QuadRoots(p,r);
p[2] = c / b;
QuadRoots(p, r);
for( k = 1; k < 3; k++ )
for(k = 1; k < 3; k++)
{
for( j = 1; j < 3; j++ ) { r[j][k+2] = r[j][k]; }
for(j = 1; j < 3; j++)
{
r[j][k + 2] = r[j][k];
}
}
p[1] = -p[1];
p[2] = b;
QuadRoots(p,r);
p[1] = -p[1];
p[2] = b;
QuadRoots(p, r);
for( k = 1; k < 5; k++ ) { r[1][k] = r[1][k] - e; }
for(k = 1; k < 5; k++)
{
r[1][k] = r[1][k] - e;
}
return 4;
}
//////////////////////////////////////////////////////////////////////////////
G4int G4AnalyticalPolSolver::QuarticRoots( G4double p[5], G4double r[3][5])
G4int G4AnalyticalPolSolver::QuarticRoots(G4double p[5], G4double r[3][5])
{
G4double a0, a1, a2, a3, y1;
G4double R2, D2, E2, D, E, R = 0.;
@@ -276,12 +344,18 @@ G4int G4AnalyticalPolSolver::QuarticRoots( G4double p[5], G4double r[3][5])
G4double reRoot[4];
G4int k, noReRoots = 0;
for( k = 0; k < 4; k++ ) { reRoot[k] = DBL_MAX; }
if( p[0] != 1.0 )
for(k = 0; k < 4; k++)
{
for( k = 1; k < 5; k++) { p[k] = p[k]/p[0]; }
reRoot[k] = DBL_MAX;
}
if(p[0] != 1.0)
{
for(k = 1; k < 5; k++)
{
p[k] = p[k] / p[0];
}
p[0] = 1.;
}
a3 = p[1];
@@ -292,148 +366,152 @@ G4int G4AnalyticalPolSolver::QuarticRoots( G4double p[5], G4double r[3][5])
// resolvent cubic equation cofs:
p[1] = -a2;
p[2] = a1*a3 - 4*a0;
p[3] = 4*a2*a0 - a1*a1 - a3*a3*a0;
p[2] = a1 * a3 - 4 * a0;
p[3] = 4 * a2 * a0 - a1 * a1 - a3 * a3 * a0;
CubicRoots(p,r);
CubicRoots(p, r);
for( k = 1; k < 4; k++ )
for(k = 1; k < 4; k++)
{
if( r[2][k] == 0. ) // find a real root
if(r[2][k] == 0.) // find a real root
{
noReRoots++;
reRoot[k] = r[1][k];
}
else reRoot[k] = DBL_MAX; // kInfinity;
else
reRoot[k] = DBL_MAX; // kInfinity;
}
y1 = DBL_MAX; // kInfinity;
for( k = 1; k < 4; k++ )
y1 = DBL_MAX; // kInfinity;
for(k = 1; k < 4; k++)
{
if ( reRoot[k] < y1 ) { y1 = reRoot[k]; }
if(reRoot[k] < y1)
{
y1 = reRoot[k];
}
}
R2 = 0.25*a3*a3 - a2 + y1;
b = 0.25*(4*a3*a2 - 8*a1 - a3*a3*a3);
c = 0.75*a3*a3 - 2*a2;
R2 = 0.25 * a3 * a3 - a2 + y1;
b = 0.25 * (4 * a3 * a2 - 8 * a1 - a3 * a3 * a3);
c = 0.75 * a3 * a3 - 2 * a2;
a = c - R2;
d = 4*y1*y1 - 16*a0;
d = 4 * y1 * y1 - 16 * a0;
if( R2 > 0.)
if(R2 > 0.)
{
R = std::sqrt(R2);
D2 = a + b/R;
E2 = a - b/R;
R = std::sqrt(R2);
D2 = a + b / R;
E2 = a - b / R;
if( D2 >= 0. )
if(D2 >= 0.)
{
D = std::sqrt(D2);
r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
r[1][1] = -0.25 * a3 + 0.5 * R + 0.5 * D;
r[1][2] = -0.25 * a3 + 0.5 * R - 0.5 * D;
r[2][1] = 0.;
r[2][2] = 0.;
}
else
{
D = std::sqrt(-D2);
r[1][1] = -0.25*a3 + 0.5*R;
r[1][2] = -0.25*a3 + 0.5*R;
r[2][1] = 0.5*D;
r[2][2] = -0.5*D;
r[1][1] = -0.25 * a3 + 0.5 * R;
r[1][2] = -0.25 * a3 + 0.5 * R;
r[2][1] = 0.5 * D;
r[2][2] = -0.5 * D;
}
if( E2 >= 0. )
if(E2 >= 0.)
{
E = std::sqrt(E2);
r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
r[1][3] = -0.25 * a3 - 0.5 * R + 0.5 * E;
r[1][4] = -0.25 * a3 - 0.5 * R - 0.5 * E;
r[2][3] = 0.;
r[2][4] = 0.;
}
else
{
E = std::sqrt(-E2);
r[1][3] = -0.25*a3 - 0.5*R;
r[1][4] = -0.25*a3 - 0.5*R;
r[2][3] = 0.5*E;
r[2][4] = -0.5*E;
r[1][3] = -0.25 * a3 - 0.5 * R;
r[1][4] = -0.25 * a3 - 0.5 * R;
r[2][3] = 0.5 * E;
r[2][4] = -0.5 * E;
}
}
else if( R2 < 0.)
else if(R2 < 0.)
{
R = std::sqrt(-R2);
G4complex CD2(a,-b/R);
G4complex CD2(a, -b / R);
G4complex CD = std::sqrt(CD2);
r[1][1] = -0.25*a3 + 0.5*real(CD);
r[1][2] = -0.25*a3 - 0.5*real(CD);
r[2][1] = 0.5*R + 0.5*imag(CD);
r[2][2] = 0.5*R - 0.5*imag(CD);
G4complex CE2(a,b/R);
r[1][1] = -0.25 * a3 + 0.5 * real(CD);
r[1][2] = -0.25 * a3 - 0.5 * real(CD);
r[2][1] = 0.5 * R + 0.5 * imag(CD);
r[2][2] = 0.5 * R - 0.5 * imag(CD);
G4complex CE2(a, b / R);
G4complex CE = std::sqrt(CE2);
r[1][3] = -0.25*a3 + 0.5*real(CE);
r[1][4] = -0.25*a3 - 0.5*real(CE);
r[2][3] = -0.5*R + 0.5*imag(CE);
r[2][4] = -0.5*R - 0.5*imag(CE);
r[1][3] = -0.25 * a3 + 0.5 * real(CE);
r[1][4] = -0.25 * a3 - 0.5 * real(CE);
r[2][3] = -0.5 * R + 0.5 * imag(CE);
r[2][4] = -0.5 * R - 0.5 * imag(CE);
}
else // R2=0 case
else // R2=0 case
{
if(d >= 0.)
{
D2 = c + std::sqrt(d);
E2 = c - std::sqrt(d);
if( D2 >= 0. )
if(D2 >= 0.)
{
D = std::sqrt(D2);
r[1][1] = -0.25*a3 + 0.5*R + 0.5*D;
r[1][2] = -0.25*a3 + 0.5*R - 0.5*D;
r[1][1] = -0.25 * a3 + 0.5 * R + 0.5 * D;
r[1][2] = -0.25 * a3 + 0.5 * R - 0.5 * D;
r[2][1] = 0.;
r[2][2] = 0.;
}
else
{
D = std::sqrt(-D2);
r[1][1] = -0.25*a3 + 0.5*R;
r[1][2] = -0.25*a3 + 0.5*R;
r[2][1] = 0.5*D;
r[2][2] = -0.5*D;
r[1][1] = -0.25 * a3 + 0.5 * R;
r[1][2] = -0.25 * a3 + 0.5 * R;
r[2][1] = 0.5 * D;
r[2][2] = -0.5 * D;
}
if( E2 >= 0. )
if(E2 >= 0.)
{
E = std::sqrt(E2);
r[1][3] = -0.25*a3 - 0.5*R + 0.5*E;
r[1][4] = -0.25*a3 - 0.5*R - 0.5*E;
r[1][3] = -0.25 * a3 - 0.5 * R + 0.5 * E;
r[1][4] = -0.25 * a3 - 0.5 * R - 0.5 * E;
r[2][3] = 0.;
r[2][4] = 0.;
}
else
{
E = std::sqrt(-E2);
r[1][3] = -0.25*a3 - 0.5*R;
r[1][4] = -0.25*a3 - 0.5*R;
r[2][3] = 0.5*E;
r[2][4] = -0.5*E;
r[1][3] = -0.25 * a3 - 0.5 * R;
r[1][4] = -0.25 * a3 - 0.5 * R;
r[2][3] = 0.5 * E;
r[2][4] = -0.5 * E;
}
}
else
{
ds = std::sqrt(-d);
G4complex CD2(c,ds);
G4complex CD2(c, ds);
G4complex CD = std::sqrt(CD2);
r[1][1] = -0.25*a3 + 0.5*real(CD);
r[1][2] = -0.25*a3 - 0.5*real(CD);
r[2][1] = 0.5*R + 0.5*imag(CD);
r[2][2] = 0.5*R - 0.5*imag(CD);
r[1][1] = -0.25 * a3 + 0.5 * real(CD);
r[1][2] = -0.25 * a3 - 0.5 * real(CD);
r[2][1] = 0.5 * R + 0.5 * imag(CD);
r[2][2] = 0.5 * R - 0.5 * imag(CD);
G4complex CE2(c,-ds);
G4complex CE2(c, -ds);
G4complex CE = std::sqrt(CE2);
r[1][3] = -0.25*a3 + 0.5*real(CE);
r[1][4] = -0.25*a3 - 0.5*real(CE);
r[2][3] = -0.5*R + 0.5*imag(CE);
r[2][4] = -0.5*R - 0.5*imag(CE);
}
r[1][3] = -0.25 * a3 + 0.5 * real(CE);
r[1][4] = -0.25 * a3 - 0.5 * real(CE);
r[2][3] = -0.5 * R + 0.5 * imag(CE);
r[2][4] = -0.5 * R - 0.5 * imag(CE);
}
}
return 4;
}
@@ -23,8 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4ChebyshevApproximation class implementation
//
//
// Author: V.Grichine, 24.04.97
// --------------------------------------------------------------------
#include "G4ChebyshevApproximation.hh"
#include "G4PhysicalConstants.hh"
@@ -33,39 +35,39 @@
// It creates the array fChebyshevCof[0,...,fNumber-1], fNumber = n ;
// which consists of Chebyshev coefficients describing the function
// pointed by pFunction. The values a and b fix the interval of validity
// of the Chebyshev approximation.
// of the Chebyshev approximation.
G4ChebyshevApproximation::G4ChebyshevApproximation( function pFunction,
G4int n,
G4double a,
G4double b )
: fFunction(pFunction), fNumber(n),
fChebyshevCof(new G4double[fNumber]),
fMean(0.5*(b+a)), fDiff(0.5*(b-a))
G4ChebyshevApproximation::G4ChebyshevApproximation(function pFunction, G4int n,
G4double a, G4double b)
: fFunction(pFunction)
, fNumber(n)
, fChebyshevCof(new G4double[fNumber])
, fMean(0.5 * (b + a))
, fDiff(0.5 * (b - a))
{
G4int i=0, j=0 ;
G4double rootSum=0.0, cofj=0.0 ;
G4double* tempFunction = new G4double[fNumber] ;
G4double weight = 2.0/fNumber ;
G4double cof = 0.5*weight*pi ; // pi/n
for (i=0;i<fNumber;i++)
{
rootSum = std::cos(cof*(i+0.5)) ;
tempFunction[i]= fFunction(rootSum*fDiff+fMean) ;
}
for (j=0;j<fNumber;j++)
{
cofj = cof*j ;
rootSum = 0.0 ;
for (i=0;i<fNumber;i++)
{
rootSum += tempFunction[i]*std::cos(cofj*(i+0.5)) ;
}
fChebyshevCof[j] = weight*rootSum ;
}
delete[] tempFunction ;
G4int i = 0, j = 0;
G4double rootSum = 0.0, cofj = 0.0;
G4double* tempFunction = new G4double[fNumber];
G4double weight = 2.0 / fNumber;
G4double cof = 0.5 * weight * pi; // pi/n
for(i = 0; i < fNumber; ++i)
{
rootSum = std::cos(cof * (i + 0.5));
tempFunction[i] = fFunction(rootSum * fDiff + fMean);
}
for(j = 0; j < fNumber; ++j)
{
cofj = cof * j;
rootSum = 0.0;
for(i = 0; i < fNumber; ++i)
{
rootSum += tempFunction[i] * std::cos(cofj * (i + 0.5));
}
fChebyshevCof[j] = weight * rootSum;
}
delete[] tempFunction;
}
// --------------------------------------------------------------------
@@ -73,55 +75,56 @@ G4ChebyshevApproximation::G4ChebyshevApproximation( function pFunction,
// Constructor for creation of Chebyshev coefficients for mx-derivative
// from pFunction. The value of mx ! MUST BE ! < nx , because the result
// array of fChebyshevCof will be of (nx-mx) size. The values a and b
// fix the interval of validity of the Chebyshev approximation.
// fix the interval of validity of the Chebyshev approximation.
G4ChebyshevApproximation::
G4ChebyshevApproximation( function pFunction,
G4int nx, G4int mx,
G4double a, G4double b )
: fFunction(pFunction), fNumber(nx),
fChebyshevCof(new G4double[fNumber]),
fMean(0.5*(b+a)), fDiff(0.5*(b-a))
G4ChebyshevApproximation::G4ChebyshevApproximation(function pFunction, G4int nx,
G4int mx, G4double a,
G4double b)
: fFunction(pFunction)
, fNumber(nx)
, fChebyshevCof(new G4double[fNumber])
, fMean(0.5 * (b + a))
, fDiff(0.5 * (b - a))
{
if(nx <= mx)
{
G4Exception("G4ChebyshevApproximation::G4ChebyshevApproximation()",
"InvalidCall", FatalException, "Invalid arguments !") ;
}
G4int i=0, j=0 ;
G4double rootSum = 0.0, cofj=0.0;
G4double* tempFunction = new G4double[fNumber] ;
G4double weight = 2.0/fNumber ;
G4double cof = 0.5*weight*pi ; // pi/nx
for (i=0;i<fNumber;i++)
{
rootSum = std::cos(cof*(i+0.5)) ;
tempFunction[i] = fFunction(rootSum*fDiff+fMean) ;
}
for (j=0;j<fNumber;j++)
{
cofj = cof*j ;
rootSum = 0.0 ;
for (i=0;i<fNumber;i++)
{
rootSum += tempFunction[i]*std::cos(cofj*(i+0.5)) ;
}
fChebyshevCof[j] = weight*rootSum ; // corresponds to pFunction
}
// Chebyshev coefficients for (mx)-derivative of pFunction
for(i=1;i<=mx;i++)
{
DerivativeChebyshevCof(tempFunction) ;
fNumber-- ;
for(j=0;j<fNumber;j++)
{
fChebyshevCof[j] = tempFunction[j] ; // corresponds to (i)-derivative
}
}
delete[] tempFunction ; // delete of dynamically allocated tempFunction
if(nx <= mx)
{
G4Exception("G4ChebyshevApproximation::G4ChebyshevApproximation()",
"InvalidCall", FatalException, "Invalid arguments !");
}
G4int i = 0, j = 0;
G4double rootSum = 0.0, cofj = 0.0;
G4double* tempFunction = new G4double[fNumber];
G4double weight = 2.0 / fNumber;
G4double cof = 0.5 * weight * pi; // pi/nx
for(i = 0; i < fNumber; ++i)
{
rootSum = std::cos(cof * (i + 0.5));
tempFunction[i] = fFunction(rootSum * fDiff + fMean);
}
for(j = 0; j < fNumber; ++j)
{
cofj = cof * j;
rootSum = 0.0;
for(i = 0; i < fNumber; ++i)
{
rootSum += tempFunction[i] * std::cos(cofj * (i + 0.5));
}
fChebyshevCof[j] = weight * rootSum; // corresponds to pFunction
}
// Chebyshev coefficients for (mx)-derivative of pFunction
for(i = 1; i <= mx; ++i)
{
DerivativeChebyshevCof(tempFunction);
fNumber--;
for(j = 0; j < fNumber; ++j)
{
fChebyshevCof[j] = tempFunction[j]; // corresponds to (i)-derivative
}
}
delete[] tempFunction; // delete of dynamically allocated tempFunction
}
// ------------------------------------------------------
@@ -129,55 +132,54 @@ G4ChebyshevApproximation( function pFunction,
// Constructor for creation of Chebyshev coefficients for integral
// from pFunction.
G4ChebyshevApproximation::G4ChebyshevApproximation( function pFunction,
G4double a,
G4double b,
G4int n )
: fFunction(pFunction), fNumber(n),
fChebyshevCof(new G4double[fNumber]),
fMean(0.5*(b+a)), fDiff(0.5*(b-a))
G4ChebyshevApproximation::G4ChebyshevApproximation(function pFunction,
G4double a, G4double b,
G4int n)
: fFunction(pFunction)
, fNumber(n)
, fChebyshevCof(new G4double[fNumber])
, fMean(0.5 * (b + a))
, fDiff(0.5 * (b - a))
{
G4int i=0, j=0;
G4double rootSum=0.0, cofj=0.0;
G4double* tempFunction = new G4double[fNumber] ;
G4double weight = 2.0/fNumber;
G4double cof = 0.5*weight*pi ; // pi/n
for (i=0;i<fNumber;i++)
{
rootSum = std::cos(cof*(i+0.5)) ;
tempFunction[i]= fFunction(rootSum*fDiff+fMean) ;
}
for (j=0;j<fNumber;j++)
{
cofj = cof*j ;
rootSum = 0.0 ;
for (i=0;i<fNumber;i++)
{
rootSum += tempFunction[i]*std::cos(cofj*(i+0.5)) ;
}
fChebyshevCof[j] = weight*rootSum ; // corresponds to pFunction
}
// Chebyshev coefficients for integral of pFunction
IntegralChebyshevCof(tempFunction) ;
for(j=0;j<fNumber;j++)
{
fChebyshevCof[j] = tempFunction[j] ; // corresponds to integral
}
delete[] tempFunction ; // delete of dynamically allocated tempFunction
G4int i = 0, j = 0;
G4double rootSum = 0.0, cofj = 0.0;
G4double* tempFunction = new G4double[fNumber];
G4double weight = 2.0 / fNumber;
G4double cof = 0.5 * weight * pi; // pi/n
for(i = 0; i < fNumber; ++i)
{
rootSum = std::cos(cof * (i + 0.5));
tempFunction[i] = fFunction(rootSum * fDiff + fMean);
}
for(j = 0; j < fNumber; ++j)
{
cofj = cof * j;
rootSum = 0.0;
for(i = 0; i < fNumber; ++i)
{
rootSum += tempFunction[i] * std::cos(cofj * (i + 0.5));
}
fChebyshevCof[j] = weight * rootSum; // corresponds to pFunction
}
// Chebyshev coefficients for integral of pFunction
IntegralChebyshevCof(tempFunction);
for(j = 0; j < fNumber; ++j)
{
fChebyshevCof[j] = tempFunction[j]; // corresponds to integral
}
delete[] tempFunction; // delete of dynamically allocated tempFunction
}
// ---------------------------------------------------------------
//
// Destructor deletes the array of Chebyshev coefficients
G4ChebyshevApproximation::~G4ChebyshevApproximation()
{
delete[] fChebyshevCof ;
delete[] fChebyshevCof;
}
// ---------------------------------------------------------------
@@ -185,16 +187,14 @@ G4ChebyshevApproximation::~G4ChebyshevApproximation()
// Access function for Chebyshev coefficients
//
G4double
G4ChebyshevApproximation::GetChebyshevCof(G4int number) const
G4double G4ChebyshevApproximation::GetChebyshevCof(G4int number) const
{
if(number < 0 && number >= fNumber)
{
G4Exception("G4ChebyshevApproximation::GetChebyshevCof()",
"InvalidCall", FatalException, "Argument out of range !") ;
}
return fChebyshevCof[number] ;
if(number < 0 && number >= fNumber)
{
G4Exception("G4ChebyshevApproximation::GetChebyshevCof()", "InvalidCall",
FatalException, "Argument out of range !");
}
return fChebyshevCof[number];
}
// --------------------------------------------------------------
@@ -202,69 +202,67 @@ G4ChebyshevApproximation::GetChebyshevCof(G4int number) const
// Evaluate the value of fFunction at the point x via the Chebyshev coefficients
// fChebyshevCof[0,...,fNumber-1]
G4double
G4ChebyshevApproximation::ChebyshevEvaluation(G4double x) const
G4double G4ChebyshevApproximation::ChebyshevEvaluation(G4double x) const
{
G4double evaluate = 0.0, evaluate2 = 0.0, temp = 0.0,
xReduced = 0.0, xReduced2 = 0.0 ;
G4double evaluate = 0.0, evaluate2 = 0.0, temp = 0.0, xReduced = 0.0,
xReduced2 = 0.0;
if ((x-fMean+fDiff)*(x-fMean-fDiff) > 0.0)
{
G4Exception("G4ChebyshevApproximation::ChebyshevEvaluation()",
"InvalidCall", FatalException, "Invalid argument !") ;
}
xReduced = (x-fMean)/fDiff ;
xReduced2 = 2.0*xReduced ;
for (G4int i=fNumber-1;i>=1;i--)
{
temp = evaluate ;
evaluate = xReduced2*evaluate - evaluate2 + fChebyshevCof[i] ;
evaluate2 = temp ;
}
return xReduced*evaluate - evaluate2 + 0.5*fChebyshevCof[0] ;
if((x - fMean + fDiff) * (x - fMean - fDiff) > 0.0)
{
G4Exception("G4ChebyshevApproximation::ChebyshevEvaluation()",
"InvalidCall", FatalException, "Invalid argument !");
}
xReduced = (x - fMean) / fDiff;
xReduced2 = 2.0 * xReduced;
for(G4int i = fNumber - 1; i >= 1; --i)
{
temp = evaluate;
evaluate = xReduced2 * evaluate - evaluate2 + fChebyshevCof[i];
evaluate2 = temp;
}
return xReduced * evaluate - evaluate2 + 0.5 * fChebyshevCof[0];
}
// ------------------------------------------------------------------
//
// Returns the array derCof[0,...,fNumber-2], the Chebyshev coefficients of the
// Returns the array derCof[0,...,fNumber-2], the Chebyshev coefficients of the
// derivative of the function whose coefficients are fChebyshevCof
void
G4ChebyshevApproximation::DerivativeChebyshevCof(G4double derCof[]) const
void G4ChebyshevApproximation::DerivativeChebyshevCof(G4double derCof[]) const
{
G4double cof = 1.0/fDiff ;
derCof[fNumber-1] = 0.0 ;
derCof[fNumber-2] = 2*(fNumber-1)*fChebyshevCof[fNumber-1] ;
for(G4int i=fNumber-3;i>=0;i--)
{
derCof[i] = derCof[i+2] + 2*(i+1)*fChebyshevCof[i+1] ;
}
for(G4int j=0;j<fNumber;j++)
{
derCof[j] *= cof ;
}
G4double cof = 1.0 / fDiff;
derCof[fNumber - 1] = 0.0;
derCof[fNumber - 2] = 2 * (fNumber - 1) * fChebyshevCof[fNumber - 1];
for(G4int i = fNumber - 3; i >= 0; --i)
{
derCof[i] = derCof[i + 2] + 2 * (i + 1) * fChebyshevCof[i + 1];
}
for(G4int j = 0; j < fNumber; ++j)
{
derCof[j] *= cof;
}
}
// ------------------------------------------------------------------------
//
// This function produces the array integralCof[0,...,fNumber-1] , the Chebyshev
// coefficients of the integral of the function whose coefficients are
// fChebyshevCof[]. The constant of integration is set so that the integral
// vanishes at the point (fMean - fDiff), i.e. at the begining of the interval of
// validity (we start the integration from this point).
// coefficients of the integral of the function whose coefficients are
// fChebyshevCof[]. The constant of integration is set so that the integral
// vanishes at the point (fMean - fDiff), i.e. at the begining of the interval
// of validity (we start the integration from this point).
//
void
G4ChebyshevApproximation::IntegralChebyshevCof(G4double integralCof[]) const
void G4ChebyshevApproximation::IntegralChebyshevCof(
G4double integralCof[]) const
{
G4double cof = 0.5*fDiff, sum = 0.0, factor = 1.0 ;
for(G4int i=1;i<fNumber-1;i++)
{
integralCof[i] = cof*(fChebyshevCof[i-1] - fChebyshevCof[i+1])/i ;
sum += factor*integralCof[i] ;
factor = -factor ;
}
integralCof[fNumber-1] = cof*fChebyshevCof[fNumber-2]/(fNumber-1) ;
sum += factor*integralCof[fNumber-1] ;
integralCof[0] = 2.0*sum ; // set the constant of integration
}
G4double cof = 0.5 * fDiff, sum = 0.0, factor = 1.0;
for(G4int i = 1; i < fNumber - 1; ++i)
{
integralCof[i] = cof * (fChebyshevCof[i - 1] - fChebyshevCof[i + 1]) / i;
sum += factor * integralCof[i];
factor = -factor;
}
integralCof[fNumber - 1] = cof * fChebyshevCof[fNumber - 2] / (fNumber - 1);
sum += factor * integralCof[fNumber - 1];
integralCof[0] = 2.0 * sum; // set the constant of integration
}
File diff suppressed because it is too large Load Diff
@@ -23,8 +23,11 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4DataInterpolation class implementation
//
//
// Author: V.Grichine, 03.04.1997
// --------------------------------------------------------------------
#include "G4DataInterpolation.hh"
//////////////////////////////////////////////////////////////////////////////
@@ -32,108 +35,108 @@
// Constructor for initializing of fArgument, fFunction and fNumber
// data members
G4DataInterpolation::G4DataInterpolation( G4double pX[],
G4double pY[],
G4int number )
: fArgument(new G4double[number]),
fFunction(new G4double[number]),
fSecondDerivative(0),
fNumber(number)
G4DataInterpolation::G4DataInterpolation(G4double pX[], G4double pY[],
G4int number)
: fArgument(new G4double[number])
, fFunction(new G4double[number])
, fNumber(number)
{
for(G4int i=0;i<fNumber;i++)
{
fArgument[i] = pX[i] ;
fFunction[i] = pY[i] ;
}
}
for(G4int i = 0; i < fNumber; ++i)
{
fArgument[i] = pX[i];
fFunction[i] = pY[i];
}
}
////////////////////////////////////////////////////////////////////////////
//
// Constructor for cubic spline interpolation. It creates the array
// Constructor for cubic spline interpolation. It creates the array
// fSecondDerivative[0,...fNumber-1] which is used in this interpolation by
// the function
// the function
G4DataInterpolation::G4DataInterpolation( G4double pX[],
G4double pY[],
G4int number,
G4double pFirstDerStart,
G4double pFirstDerFinish )
: fArgument(new G4double[number]),
fFunction(new G4double[number]),
fSecondDerivative(new G4double[number]),
fNumber(number)
G4DataInterpolation::G4DataInterpolation(G4double pX[], G4double pY[],
G4int number, G4double pFirstDerStart,
G4double pFirstDerFinish)
: fArgument(new G4double[number])
, fFunction(new G4double[number])
, fSecondDerivative(new G4double[number])
, fNumber(number)
{
G4int i=0 ;
G4double p=0.0, qn=0.0, sig=0.0, un=0.0 ;
const G4double maxDerivative = 0.99e30 ;
G4double* u = new G4double[fNumber - 1] ;
G4int i = 0;
G4double p = 0.0, qn = 0.0, sig = 0.0, un = 0.0;
const G4double maxDerivative = 0.99e30;
G4double* u = new G4double[fNumber - 1];
for(i=0;i<fNumber;i++)
{
fArgument[i] = pX[i] ;
fFunction[i] = pY[i] ;
}
if(pFirstDerStart > maxDerivative)
{
fSecondDerivative[0] = 0.0 ;
u[0] = 0.0 ;
}
else
{
fSecondDerivative[0] = -0.5 ;
u[0] = (3.0/(fArgument[1]-fArgument[0]))
* ((fFunction[1]-fFunction[0])/(fArgument[1]-fArgument[0])
- pFirstDerStart) ;
}
// Decomposition loop for tridiagonal algorithm. fSecondDerivative[i]
// and u[i] are used for temporary storage of the decomposed factors.
for(i=1;i<fNumber-1;i++)
{
sig = (fArgument[i]-fArgument[i-1])/(fArgument[i+1]-fArgument[i-1]) ;
p = sig*fSecondDerivative[i-1] + 2.0 ;
fSecondDerivative[i] = (sig - 1.0)/p ;
u[i] = (fFunction[i+1]-fFunction[i])/(fArgument[i+1]-fArgument[i]) -
(fFunction[i]-fFunction[i-1])/(fArgument[i]-fArgument[i-1]) ;
u[i] =(6.0*u[i]/(fArgument[i+1]-fArgument[i-1]) - sig*u[i-1])/p ;
}
if(pFirstDerFinish > maxDerivative)
{
qn = 0.0 ;
un = 0.0 ;
}
else
{
qn = 0.5 ;
un = (3.0/(fArgument[fNumber-1]-fArgument[fNumber-2]))
* (pFirstDerFinish - (fFunction[fNumber-1]-fFunction[fNumber-2])
/ (fArgument[fNumber-1]-fArgument[fNumber-2])) ;
}
fSecondDerivative[fNumber-1] = (un - qn*u[fNumber-2])/
(qn*fSecondDerivative[fNumber-2] + 1.0) ;
// The backsubstitution loop for the triagonal algorithm of solving
// a linear system of equations.
for(G4int k=fNumber-2;k>=0;k--)
{
fSecondDerivative[k] = fSecondDerivative[k]*fSecondDerivative[k+1] + u[k];
}
delete[] u ;
}
for(i = 0; i < fNumber; ++i)
{
fArgument[i] = pX[i];
fFunction[i] = pY[i];
}
if(pFirstDerStart > maxDerivative)
{
fSecondDerivative[0] = 0.0;
u[0] = 0.0;
}
else
{
fSecondDerivative[0] = -0.5;
u[0] = (3.0 / (fArgument[1] - fArgument[0])) *
((fFunction[1] - fFunction[0]) / (fArgument[1] - fArgument[0]) -
pFirstDerStart);
}
// Decomposition loop for tridiagonal algorithm. fSecondDerivative[i]
// and u[i] are used for temporary storage of the decomposed factors.
for(i = 1; i < fNumber - 1; ++i)
{
sig =
(fArgument[i] - fArgument[i - 1]) / (fArgument[i + 1] - fArgument[i - 1]);
p = sig * fSecondDerivative[i - 1] + 2.0;
fSecondDerivative[i] = (sig - 1.0) / p;
u[i] =
(fFunction[i + 1] - fFunction[i]) / (fArgument[i + 1] - fArgument[i]) -
(fFunction[i] - fFunction[i - 1]) / (fArgument[i] - fArgument[i - 1]);
u[i] =
(6.0 * u[i] / (fArgument[i + 1] - fArgument[i - 1]) - sig * u[i - 1]) / p;
}
if(pFirstDerFinish > maxDerivative)
{
qn = 0.0;
un = 0.0;
}
else
{
qn = 0.5;
un =
(3.0 / (fArgument[fNumber - 1] - fArgument[fNumber - 2])) *
(pFirstDerFinish - (fFunction[fNumber - 1] - fFunction[fNumber - 2]) /
(fArgument[fNumber - 1] - fArgument[fNumber - 2]));
}
fSecondDerivative[fNumber - 1] =
(un - qn * u[fNumber - 2]) / (qn * fSecondDerivative[fNumber - 2] + 1.0);
// The backsubstitution loop for the triagonal algorithm of solving
// a linear system of equations.
for(G4int k = fNumber - 2; k >= 0; --k)
{
fSecondDerivative[k] =
fSecondDerivative[k] * fSecondDerivative[k + 1] + u[k];
}
delete[] u;
}
/////////////////////////////////////////////////////////////////////////////
//
// Destructor deletes dynamically created arrays for data members: fArgument,
// fFunction and fSecondDerivative, all have dimension of fNumber
G4DataInterpolation::~G4DataInterpolation()
{
delete [] fArgument ;
delete [] fFunction ;
if(fSecondDerivative) { delete [] fSecondDerivative; }
delete[] fArgument;
delete[] fFunction;
delete[] fSecondDerivative;
}
/////////////////////////////////////////////////////////////////////////////
@@ -143,50 +146,50 @@ G4DataInterpolation::~G4DataInterpolation()
// This is Lagrange's form of interpolation and it is based on Neville's
// algorithm
G4double
G4DataInterpolation::PolynomInterpolation(G4double pX,
G4double& deltaY ) const
G4double G4DataInterpolation::PolynomInterpolation(G4double pX,
G4double& deltaY) const
{
G4int i=0, j=1, k=0 ;
G4double mult=0.0, difi=0.0, deltaLow=0.0, deltaUp=0.0, cd=0.0, y=0.0 ;
G4double* c = new G4double[fNumber] ;
G4double* d = new G4double[fNumber] ;
G4double diff = std::fabs(pX-fArgument[0]) ;
for(i=0;i<fNumber;i++)
{
difi = std::fabs(pX-fArgument[i]) ;
if(difi <diff)
G4int i = 0, j = 1, k = 0;
G4double mult = 0.0, difi = 0.0, deltaLow = 0.0, deltaUp = 0.0, cd = 0.0,
y = 0.0;
G4double* c = new G4double[fNumber];
G4double* d = new G4double[fNumber];
G4double diff = std::fabs(pX - fArgument[0]);
for(i = 0; i < fNumber; ++i)
{
difi = std::fabs(pX - fArgument[i]);
if(difi < diff)
{
k = i;
diff = difi;
}
c[i] = fFunction[i];
d[i] = fFunction[i];
}
y = fFunction[k--];
for(j = 1; j < fNumber; ++j)
{
for(i = 0; i < fNumber - j; ++i)
{
deltaLow = fArgument[i] - pX;
deltaUp = fArgument[i + j] - pX;
cd = c[i + 1] - d[i];
mult = deltaLow - deltaUp;
if(!(mult != 0.0))
{
k = i ;
diff = difi ;
G4Exception("G4DataInterpolation::PolynomInterpolation()", "Error",
FatalException, "Coincident nodes !");
}
c[i] = fFunction[i] ;
d[i] = fFunction[i] ;
}
y = fFunction[k--] ;
for(j=1;j<fNumber;j++)
{
for(i=0;i<fNumber-j;i++)
{
deltaLow = fArgument[i] - pX ;
deltaUp = fArgument[i+j] - pX ;
cd = c[i+1] - d[i] ;
mult = deltaLow - deltaUp ;
if (!(mult != 0.0))
{
G4Exception("G4DataInterpolation::PolynomInterpolation()",
"Error", FatalException, "Coincident nodes !") ;
}
mult = cd/mult ;
d[i] = deltaUp*mult ;
c[i] = deltaLow*mult ;
}
y += (deltaY = (2*k < (fNumber - j -1) ? c[k+1] : d[k--] )) ;
}
delete[] c ;
delete[] d ;
return y ;
mult = cd / mult;
d[i] = deltaUp * mult;
c[i] = deltaLow * mult;
}
y += (deltaY = (2 * k < (fNumber - j - 1) ? c[k + 1] : d[k--]));
}
delete[] c;
delete[] d;
return y;
}
////////////////////////////////////////////////////////////////////////////
@@ -194,47 +197,46 @@ G4DataInterpolation::PolynomInterpolation(G4double pX,
// Given arrays fArgument[0,..,fNumber-1] and fFunction[0,..,fNumber-1], this
// function calculates an array of coefficients. The coefficients don't provide
// usually (fNumber>10) better accuracy for polynom interpolation, as compared
// with PolynomInterpolation function. They could be used instead for derivate
// with PolynomInterpolation function. They could be used instead for derivate
// calculations and some other applications.
void
G4DataInterpolation::PolIntCoefficient( G4double cof[]) const
void G4DataInterpolation::PolIntCoefficient(G4double cof[]) const
{
G4int i=0, j=0 ;
G4double factor;
G4double reducedY=0.0, mult=1.0 ;
G4double* tempArgument = new G4double[fNumber] ;
for(i=0;i<fNumber;i++)
{
tempArgument[i] = cof[i] = 0.0 ;
}
tempArgument[fNumber-1] = -fArgument[0] ;
for(i=1;i<fNumber;i++)
{
for(j=fNumber-1-i;j<fNumber-1;j++)
{
tempArgument[j] -= fArgument[i]*tempArgument[j+1] ;
}
tempArgument[fNumber-1] -= fArgument[i] ;
}
for(i=0;i<fNumber;i++)
{
factor = fNumber ;
for(j=fNumber-1;j>=1;j--)
{
factor = j*tempArgument[j] + factor*fArgument[i] ;
}
reducedY = fFunction[i]/factor ;
mult = 1.0 ;
for(j=fNumber-1;j>=0;j--)
{
cof[j] += mult*reducedY ;
mult = tempArgument[j] + mult*fArgument[i] ;
}
}
delete[] tempArgument ;
G4int i = 0, j = 0;
G4double factor;
G4double reducedY = 0.0, mult = 1.0;
G4double* tempArgument = new G4double[fNumber];
for(i = 0; i < fNumber; ++i)
{
tempArgument[i] = cof[i] = 0.0;
}
tempArgument[fNumber - 1] = -fArgument[0];
for(i = 1; i < fNumber; ++i)
{
for(j = fNumber - 1 - i; j < fNumber - 1; ++j)
{
tempArgument[j] -= fArgument[i] * tempArgument[j + 1];
}
tempArgument[fNumber - 1] -= fArgument[i];
}
for(i = 0; i < fNumber; ++i)
{
factor = fNumber;
for(j = fNumber - 1; j >= 1; --j)
{
factor = j * tempArgument[j] + factor * fArgument[i];
}
reducedY = fFunction[i] / factor;
mult = 1.0;
for(j = fNumber - 1; j >= 0; --j)
{
cof[j] += mult * reducedY;
mult = tempArgument[j] + mult * fArgument[i];
}
}
delete[] tempArgument;
}
/////////////////////////////////////////////////////////////////////////////
@@ -244,59 +246,58 @@ G4DataInterpolation::PolIntCoefficient( G4double cof[]) const
// Tests showed the method is not stable and hasn't advantage if compared
// with polynomial interpolation ?!
G4double
G4DataInterpolation::RationalPolInterpolation(G4double pX,
G4double& deltaY ) const
G4double G4DataInterpolation::RationalPolInterpolation(G4double pX,
G4double& deltaY) const
{
G4int i=0, j=1, k=0 ;
const G4double tolerance = 1.6e-24 ;
G4double mult=0.0, difi=0.0, cd=0.0, y=0.0, cof=0.0 ;
G4double* c = new G4double[fNumber] ;
G4double* d = new G4double[fNumber] ;
G4double diff = std::fabs(pX-fArgument[0]) ;
for(i=0;i<fNumber;i++)
{
difi = std::fabs(pX-fArgument[i]) ;
if (!(difi != 0.0))
G4int i = 0, j = 1, k = 0;
const G4double tolerance = 1.6e-24;
G4double mult = 0.0, difi = 0.0, cd = 0.0, y = 0.0, cof = 0.0;
G4double* c = new G4double[fNumber];
G4double* d = new G4double[fNumber];
G4double diff = std::fabs(pX - fArgument[0]);
for(i = 0; i < fNumber; ++i)
{
difi = std::fabs(pX - fArgument[i]);
if(!(difi != 0.0))
{
y = fFunction[i];
deltaY = 0.0;
delete[] c;
delete[] d;
return y;
}
else if(difi < diff)
{
k = i;
diff = difi;
}
c[i] = fFunction[i];
d[i] = fFunction[i] + tolerance; // to prevent rare zero/zero cases
}
y = fFunction[k--];
for(j = 1; j < fNumber; ++j)
{
for(i = 0; i < fNumber - j; ++i)
{
cd = c[i + 1] - d[i];
difi = fArgument[i + j] - pX;
cof = (fArgument[i] - pX) * d[i] / difi;
mult = cof - c[i + 1];
if(!(mult != 0.0)) // function to be interpolated has pole at pX
{
y = fFunction[i] ;
deltaY = 0.0 ;
delete[] c ;
delete[] d ;
return y ;
G4Exception("G4DataInterpolation::RationalPolInterpolation()", "Error",
FatalException, "Coincident nodes !");
}
else if(difi < diff)
{
k = i ;
diff = difi ;
}
c[i] = fFunction[i] ;
d[i] = fFunction[i] + tolerance ; // to prevent rare zero/zero cases
}
y = fFunction[k--] ;
for(j=1;j<fNumber;j++)
{
for(i=0;i<fNumber-j;i++)
{
cd = c[i+1] - d[i] ;
difi = fArgument[i+j] - pX ;
cof = (fArgument[i] - pX)*d[i]/difi ;
mult = cof - c[i+1] ;
if (!(mult != 0.0)) // function to be interpolated has pole at pX
{
G4Exception("G4DataInterpolation::RationalPolInterpolation()",
"Error", FatalException, "Coincident nodes !") ;
}
mult = cd/mult ;
d[i] = c[i+1]*mult ;
c[i] = cof*mult ;
}
y += (deltaY = (2*k < (fNumber - j - 1) ? c[k+1] : d[k--] )) ;
}
delete[] c ;
delete[] d ;
return y ;
mult = cd / mult;
d[i] = c[i + 1] * mult;
c[i] = cof * mult;
}
y += (deltaY = (2 * k < (fNumber - j - 1) ? c[k + 1] : d[k--]));
}
delete[] c;
delete[] d;
return y;
}
/////////////////////////////////////////////////////////////////////////////
@@ -306,40 +307,40 @@ G4DataInterpolation::RationalPolInterpolation(G4double pX,
// must be called before. The function works optimal, if sequential calls
// are in random values of pX.
G4double
G4DataInterpolation::CubicSplineInterpolation(G4double pX) const
G4double G4DataInterpolation::CubicSplineInterpolation(G4double pX) const
{
G4int kLow=0, kHigh=fNumber-1, k=0 ;
// Searching in the table by means of bisection method.
// fArgument must be monotonic, either increasing or decreasing
while((kHigh - kLow) > 1)
{
k = (kHigh + kLow) >> 1 ; // compute midpoint 'bisection'
if(fArgument[k] > pX)
{
kHigh = k ;
}
else
{
kLow = k ;
}
} // kLow and kHigh now bracket the input value of pX
G4double deltaHL = fArgument[kHigh] - fArgument[kLow] ;
if (!(deltaHL != 0.0))
{
G4Exception("G4DataInterpolation::CubicSplineInterpolation()",
"Error", FatalException, "Bad fArgument input !") ;
}
G4double a = (fArgument[kHigh] - pX)/deltaHL ;
G4double b = (pX - fArgument[kLow])/deltaHL ;
// Final evaluation of cubic spline polynomial for return
return a*fFunction[kLow] + b*fFunction[kHigh] +
((a*a*a - a)*fSecondDerivative[kLow] +
(b*b*b - b)*fSecondDerivative[kHigh])*deltaHL*deltaHL/6.0 ;
G4int kLow = 0, kHigh = fNumber - 1, k = 0;
// Searching in the table by means of bisection method.
// fArgument must be monotonic, either increasing or decreasing
while((kHigh - kLow) > 1)
{
k = (kHigh + kLow) >> 1; // compute midpoint 'bisection'
if(fArgument[k] > pX)
{
kHigh = k;
}
else
{
kLow = k;
}
} // kLow and kHigh now bracket the input value of pX
G4double deltaHL = fArgument[kHigh] - fArgument[kLow];
if(!(deltaHL != 0.0))
{
G4Exception("G4DataInterpolation::CubicSplineInterpolation()", "Error",
FatalException, "Bad fArgument input !");
}
G4double a = (fArgument[kHigh] - pX) / deltaHL;
G4double b = (pX - fArgument[kLow]) / deltaHL;
// Final evaluation of cubic spline polynomial for return
return a * fFunction[kLow] + b * fFunction[kHigh] +
((a * a * a - a) * fSecondDerivative[kLow] +
(b * b * b - b) * fSecondDerivative[kHigh]) *
deltaHL * deltaHL / 6.0;
}
///////////////////////////////////////////////////////////////////////////
@@ -348,24 +349,23 @@ G4DataInterpolation::CubicSplineInterpolation(G4double pX) const
// fArgument[index] and fArgument[index+1]. It is usually called in sequence
// of known from external analysis values of index.
G4double
G4DataInterpolation::FastCubicSpline(G4double pX,
G4int index) const
G4double G4DataInterpolation::FastCubicSpline(G4double pX, G4int index) const
{
G4double delta = fArgument[index+1] - fArgument[index] ;
if (!(delta != 0.0))
{
G4Exception("G4DataInterpolation::FastCubicSpline()",
"Error", FatalException, "Bad fArgument input !") ;
}
G4double a = (fArgument[index+1] - pX)/delta ;
G4double b = (pX - fArgument[index])/delta ;
// Final evaluation of cubic spline polynomial for return
return a*fFunction[index] + b*fFunction[index+1] +
((a*a*a - a)*fSecondDerivative[index] +
(b*b*b - b)*fSecondDerivative[index+1])*delta*delta/6.0 ;
G4double delta = fArgument[index + 1] - fArgument[index];
if(!(delta != 0.0))
{
G4Exception("G4DataInterpolation::FastCubicSpline()", "Error",
FatalException, "Bad fArgument input !");
}
G4double a = (fArgument[index + 1] - pX) / delta;
G4double b = (pX - fArgument[index]) / delta;
// Final evaluation of cubic spline polynomial for return
return a * fFunction[index] + b * fFunction[index + 1] +
((a * a * a - a) * fSecondDerivative[index] +
(b * b * b - b) * fSecondDerivative[index + 1]) *
delta * delta / 6.0;
}
////////////////////////////////////////////////////////////////////////////
@@ -373,32 +373,32 @@ G4DataInterpolation::FastCubicSpline(G4double pX,
// Given argument pX, returns index k, so that pX bracketed by fArgument[k]
// and fArgument[k+1]
G4int
G4DataInterpolation::LocateArgument(G4double pX) const
G4int G4DataInterpolation::LocateArgument(G4double pX) const
{
G4int kLow=-1, kHigh=fNumber, k=0 ;
G4bool ascend=(fArgument[fNumber-1] >= fArgument[0]) ;
while((kHigh - kLow) > 1)
{
k = (kHigh + kLow) >> 1 ; // compute midpoint 'bisection'
if( (pX >= fArgument[k]) == ascend)
{
kLow = k ;
}
else
{
kHigh = k ;
}
}
if (!(pX != fArgument[0]))
{
return 1 ;
}
else if (!(pX != fArgument[fNumber-1]))
{
return fNumber - 2 ;
}
else return kLow ;
G4int kLow = -1, kHigh = fNumber, k = 0;
G4bool ascend = (fArgument[fNumber - 1] >= fArgument[0]);
while((kHigh - kLow) > 1)
{
k = (kHigh + kLow) >> 1; // compute midpoint 'bisection'
if((pX >= fArgument[k]) == ascend)
{
kLow = k;
}
else
{
kHigh = k;
}
}
if(!(pX != fArgument[0]))
{
return 1;
}
else if(!(pX != fArgument[fNumber - 1]))
{
return fNumber - 2;
}
else
return kLow;
}
/////////////////////////////////////////////////////////////////////////////
@@ -409,88 +409,86 @@ G4DataInterpolation::LocateArgument(G4double pX) const
// that pX is out of range. The value index on input is taken as the initial
// approximation for index on output.
void
G4DataInterpolation::CorrelatedSearch( G4double pX,
G4int& index ) const
void G4DataInterpolation::CorrelatedSearch(G4double pX, G4int& index) const
{
G4int kHigh=0, k=0, Increment=0 ;
// ascend = true for ascending order of table, false otherwise
G4bool ascend = (fArgument[fNumber-1] >= fArgument[0]) ;
if(index < 0 || index > fNumber-1)
{
index = -1 ;
kHigh = fNumber ;
}
else
{
Increment = 1 ; // What value would be the best ?
if((pX >= fArgument[index]) == ascend)
G4int kHigh = 0, k = 0, Increment = 0;
// ascend = true for ascending order of table, false otherwise
G4bool ascend = (fArgument[fNumber - 1] >= fArgument[0]);
if(index < 0 || index > fNumber - 1)
{
index = -1;
kHigh = fNumber;
}
else
{
Increment = 1; // What value would be the best ?
if((pX >= fArgument[index]) == ascend)
{
if(index == fNumber - 1)
{
if(index == fNumber -1)
{
index = fNumber ;
return ;
}
kHigh = index + 1 ;
while((pX >= fArgument[kHigh]) == ascend)
{
index = kHigh ;
Increment += Increment ; // double the Increment
kHigh = index + Increment ;
if(kHigh > (fNumber - 1))
{
kHigh = fNumber ;
break ;
}
}
index = fNumber;
return;
}
else
kHigh = index + 1;
while((pX >= fArgument[kHigh]) == ascend)
{
if(index == 0)
{
index = -1 ;
return ;
}
kHigh = index-- ;
while((pX < fArgument[index]) == ascend)
{
kHigh = index ;
Increment <<= 1 ; // double the Increment
if(Increment >= kHigh)
{
index = -1 ;
break ;
}
else
{
index = kHigh - Increment ;
}
}
} // Value bracketed
}
// final bisection searching
index = kHigh;
Increment += Increment; // double the Increment
kHigh = index + Increment;
if(kHigh > (fNumber - 1))
{
kHigh = fNumber;
break;
}
}
}
else
{
if(index == 0)
{
index = -1;
return;
}
kHigh = --index;
while((pX < fArgument[index]) == ascend)
{
kHigh = index;
Increment <<= 1; // double the Increment
if(Increment >= kHigh)
{
index = -1;
break;
}
else
{
index = kHigh - Increment;
}
}
} // Value bracketed
}
// final bisection searching
while((kHigh - index) != 1)
{
k = (kHigh + index) >> 1 ;
if((pX >= fArgument[k]) == ascend)
{
index = k ;
}
else
{
kHigh = k ;
}
}
if (!(pX != fArgument[fNumber-1]))
{
index = fNumber - 2 ;
}
if (!(pX != fArgument[0]))
{
index = 0 ;
}
return ;
while((kHigh - index) != 1)
{
k = (kHigh + index) >> 1;
if((pX >= fArgument[k]) == ascend)
{
index = k;
}
else
{
kHigh = k;
}
}
if(!(pX != fArgument[fNumber - 1]))
{
index = fNumber - 2;
}
if(!(pX != fArgument[0]))
{
index = 0;
}
return;
}
//
@@ -23,53 +23,51 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4GaussChebyshevQ class implementation
//
//
// Author: V.Grichine, 13.05.1997
// --------------------------------------------------------------------
#include "G4GaussChebyshevQ.hh"
#include "G4PhysicalConstants.hh"
// -----------------------------------------------------
//
// Constructor for Gauss-Chebyshev quadrature method
G4GaussChebyshevQ::G4GaussChebyshevQ( function pFunction ,
G4int nChebyshev )
: G4VGaussianQuadrature(pFunction)
//
G4GaussChebyshevQ::G4GaussChebyshevQ(function pFunction, G4int nChebyshev)
: G4VGaussianQuadrature(pFunction)
{
fNumber = nChebyshev ; // Try to reduce fNumber twice ??
G4double cof = pi/fNumber ;
fAbscissa = new G4double[fNumber] ;
fWeight = new G4double[fNumber] ;
for(G4int i=0;i<fNumber;i++)
{
fAbscissa[i] = std::cos(cof*(i + 0.5)) ;
fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ;
}
fNumber = nChebyshev; // Try to reduce fNumber twice ??
G4double cof = pi / fNumber;
fAbscissa = new G4double[fNumber];
fWeight = new G4double[fNumber];
for(G4int i = 0; i < fNumber; ++i)
{
fAbscissa[i] = std::cos(cof * (i + 0.5));
fWeight[i] = cof * std::sqrt(1 - fAbscissa[i] * fAbscissa[i]);
}
}
// ----------------------------------------------------------------------
//
G4GaussChebyshevQ::~G4GaussChebyshevQ()
{
}
G4GaussChebyshevQ::~G4GaussChebyshevQ() {}
// -------------------------------------------------------------------------------
//
// Integrates function pointed by fFunction from a to b by Gauss-Chebyshev
// Integrates function pointed by fFunction from a to b by Gauss-Chebyshev
// quadrature method
G4double
G4GaussChebyshevQ::Integral(G4double a, G4double b) const
//
G4double G4GaussChebyshevQ::Integral(G4double a, G4double b) const
{
G4double xDiff=0.5*(b - a),
xMean=0.5*(a + b),
dx=0.0, integral=0.0 ;
for(G4int i=0;i<fNumber;i++)
{
dx = xDiff*fAbscissa[i] ;
integral += fWeight[i]*fFunction(xMean + dx) ;
}
return integral *= xDiff ;
G4double xDiff = 0.5 * (b - a), xMean = 0.5 * (a + b), dx = 0.0,
integral = 0.0;
for(G4int i = 0; i < fNumber; ++i)
{
dx = xDiff * fAbscissa[i];
integral += fWeight[i] * fFunction(xMean + dx);
}
return integral *= xDiff;
}
@@ -23,8 +23,10 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4GaussHermiteQ class implementation
//
//
// Author: V.Grichine, 13.05.1997 V.Grichine
// --------------------------------------------------------------------
#include "G4GaussHermiteQ.hh"
#include "G4PhysicalConstants.hh"
@@ -33,88 +35,87 @@
//
// Constructor for Gauss-Hermite
G4GaussHermiteQ::G4GaussHermiteQ ( function pFunction,
G4int nHermite )
: G4VGaussianQuadrature(pFunction)
G4GaussHermiteQ::G4GaussHermiteQ(function pFunction, G4int nHermite)
: G4VGaussianQuadrature(pFunction)
{
const G4double tolerance = 1.0e-12 ;
const G4int maxNumber = 12 ;
G4int i=1, j=1, k=1 ;
G4double newton0=0.;
G4double newton1=0.0, temp1=0.0, temp2=0.0, temp3=0.0, temp=0.0 ;
G4double piInMinusQ = std::pow(pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ??
const G4double tolerance = 1.0e-12;
const G4int maxNumber = 12;
fNumber = (nHermite +1)/2 ;
fAbscissa = new G4double[fNumber] ;
fWeight = new G4double[fNumber] ;
G4int i = 1, j = 1, k = 1;
G4double newton0 = 0.;
G4double newton1 = 0.0, temp1 = 0.0, temp2 = 0.0, temp3 = 0.0, temp = 0.0;
G4double piInMinusQ = std::pow(pi, -0.25); // 1.0/std::sqrt(std::sqrt(pi)) ??
for(i=1;i<=fNumber;i++)
{
if(i == 1)
fNumber = (nHermite + 1) / 2;
fAbscissa = new G4double[fNumber];
fWeight = new G4double[fNumber];
for(i = 1; i <= fNumber; ++i)
{
if(i == 1)
{
newton0 =
std::sqrt((G4double)(2 * nHermite + 1)) -
1.85575001 * std::pow((G4double)(2 * nHermite + 1), -0.16666999);
}
else if(i == 2)
{
newton0 -= 1.14001 * std::pow((G4double) nHermite, 0.425999) / newton0;
}
else if(i == 3)
{
newton0 = 1.86002 * newton0 - 0.86002 * fAbscissa[0];
}
else if(i == 4)
{
newton0 = 1.91001 * newton0 - 0.91001 * fAbscissa[1];
}
else
{
newton0 = 2.0 * newton0 - fAbscissa[i - 3];
}
for(k = 1; k <= maxNumber; ++k)
{
temp1 = piInMinusQ;
temp2 = 0.0;
for(j = 1; j <= nHermite; ++j)
{
newton0 = std::sqrt((G4double)(2*nHermite + 1)) -
1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ;
temp3 = temp2;
temp2 = temp1;
temp1 = newton0 * std::sqrt(2.0 / j) * temp2 -
std::sqrt(((G4double)(j - 1)) / j) * temp3;
}
else if(i == 2)
temp = std::sqrt((G4double) 2 * nHermite) * temp2;
newton1 = newton0;
newton0 = newton1 - temp1 / temp;
if(std::fabs(newton0 - newton1) <= tolerance)
{
newton0 -= 1.14001*std::pow((G4double)nHermite,0.425999)/newton0 ;
break;
}
else if(i == 3)
{
newton0 = 1.86002*newton0 - 0.86002*fAbscissa[0] ;
}
else if(i == 4)
{
newton0 = 1.91001*newton0 - 0.91001*fAbscissa[1] ;
}
else
{
newton0 = 2.0*newton0 - fAbscissa[i - 3] ;
}
for(k=1;k<=maxNumber;k++)
{
temp1 = piInMinusQ ;
temp2 = 0.0 ;
for(j=1;j<=nHermite;j++)
{
temp3 = temp2 ;
temp2 = temp1 ;
temp1 = newton0*std::sqrt(2.0/j)*temp2
- std::sqrt(((G4double)(j - 1))/j)*temp3 ;
}
temp = std::sqrt((G4double)2*nHermite)*temp2 ;
newton1 = newton0 ;
newton0 = newton1 - temp1/temp ;
if(std::fabs(newton0 - newton1) <= tolerance)
{
break ;
}
}
if(k > maxNumber)
{
G4Exception("G4GaussHermiteQ::G4GaussHermiteQ()",
"OutOfRange", FatalException,
"Too many iterations in Gauss-Hermite constructor.") ;
}
fAbscissa[i-1] = newton0 ;
fWeight[i-1] = 2.0/(temp*temp) ;
}
}
if(k > maxNumber)
{
G4Exception("G4GaussHermiteQ::G4GaussHermiteQ()", "OutOfRange",
FatalException,
"Too many iterations in Gauss-Hermite constructor.");
}
fAbscissa[i - 1] = newton0;
fWeight[i - 1] = 2.0 / (temp * temp);
}
}
// ----------------------------------------------------------
//
// Gauss-Hermite method for integration of std::exp(-x*x)*nFunction(x)
// from minus infinity to plus infinity .
// from minus infinity to plus infinity .
G4double G4GaussHermiteQ::Integral() const
G4double G4GaussHermiteQ::Integral() const
{
G4double integral = 0.0 ;
for(G4int i=0;i<fNumber;i++)
{
integral += fWeight[i]*(fFunction(fAbscissa[i])
+ fFunction(-fAbscissa[i])) ;
}
return integral ;
G4double integral = 0.0;
for(G4int i = 0; i < fNumber; ++i)
{
integral +=
fWeight[i] * (fFunction(fAbscissa[i]) + fFunction(-fAbscissa[i]));
}
return integral;
}
+112 -112
View File
@@ -23,138 +23,138 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4GaussJacobiQ class implementation
//
//
#include "G4GaussJacobiQ.hh"
// Author: V.Grichine, 13.05.1997
// --------------------------------------------------------------------
#include "G4GaussJacobiQ.hh"
// -------------------------------------------------------------
//
// Constructor for Gauss-Jacobi integration method.
// Constructor for Gauss-Jacobi integration method.
//
G4GaussJacobiQ::G4GaussJacobiQ( function pFunction,
G4double alpha,
G4double beta,
G4int nJacobi )
: G4VGaussianQuadrature(pFunction)
G4GaussJacobiQ::G4GaussJacobiQ(function pFunction, G4double alpha,
G4double beta, G4int nJacobi)
: G4VGaussianQuadrature(pFunction)
{
const G4double tolerance = 1.0e-12 ;
const G4double maxNumber = 12 ;
G4int i=1, k=1 ;
G4double root=0.;
G4double alphaBeta=0.0, alphaReduced=0.0, betaReduced=0.0,
root1=0.0, root2=0.0, root3=0.0 ;
G4double a=0.0, b=0.0, c=0.0,
newton1=0.0, newton2=0.0, newton3=0.0, newton0=0.0,
temp=0.0, rootTemp=0.0 ;
const G4double tolerance = 1.0e-12;
const G4double maxNumber = 12;
G4int i = 1, k = 1;
G4double root = 0.;
G4double alphaBeta = 0.0, alphaReduced = 0.0, betaReduced = 0.0, root1 = 0.0,
root2 = 0.0, root3 = 0.0;
G4double a = 0.0, b = 0.0, c = 0.0, newton1 = 0.0, newton2 = 0.0,
newton3 = 0.0, newton0 = 0.0, temp = 0.0, rootTemp = 0.0;
fNumber = nJacobi ;
fAbscissa = new G4double[fNumber] ;
fWeight = new G4double[fNumber] ;
fNumber = nJacobi;
fAbscissa = new G4double[fNumber];
fWeight = new G4double[fNumber];
for (i=1;i<=nJacobi;i++)
for(i = 1; i <= nJacobi; ++i)
{
if (i == 1)
{
alphaReduced = alpha/nJacobi ;
betaReduced = beta/nJacobi ;
root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+
0.767999*alphaReduced/nJacobi) ;
root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced
+ 0.451998*alphaReduced*alphaReduced
+ 0.83001*alphaReduced*betaReduced ;
root = 1.0-root1/root2 ;
}
else if (i == 2)
{
root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ;
root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ;
root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ;
root -= (1.0-root)*root1*root2*root3 ;
}
else if (i == 3)
{
root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ;
root2=1.0+0.22*(nJacobi-8.0)/nJacobi ;
root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ;
root -= (fAbscissa[0]-root)*root1*root2*root3 ;
}
else if (i == nJacobi-1)
{
root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ;
root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ;
root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ;
root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ;
}
else if (i == nJacobi)
{
root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ;
root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ;
root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ;
root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ;
}
else
{
root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ;
}
alphaBeta = alpha + beta ;
for (k=1;k<=maxNumber;k++)
{
temp = 2.0 + alphaBeta ;
newton1 = (alpha-beta+temp*root)/2.0 ;
newton2 = 1.0 ;
for (G4int j=2;j<=nJacobi;j++)
{
newton3 = newton2 ;
newton2 = newton1 ;
temp = 2*j+alphaBeta ;
a = 2*j*(j+alphaBeta)*(temp-2.0) ;
b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ;
c = 2.0*(j-1+alpha)*(j-1+beta)*temp ;
newton1 = (b*newton2-c*newton3)/a ;
}
newton0 = (nJacobi*(alpha - beta - temp*root)*newton1 +
2.0*(nJacobi + alpha)*(nJacobi + beta)*newton2)/
(temp*(1.0 - root*root)) ;
rootTemp = root ;
root = rootTemp - newton1/newton0 ;
if (std::fabs(root-rootTemp) <= tolerance)
{
break ;
}
}
if (k > maxNumber)
{
G4Exception("G4GaussJacobiQ::G4GaussJacobiQ()", "OutOfRange",
FatalException, "Too many iterations in constructor.") ;
}
fAbscissa[i-1] = root ;
fWeight[i-1] = std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) +
GammaLogarithm((G4double)(beta+nJacobi)) -
GammaLogarithm((G4double)(nJacobi+1.0)) -
GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0)))
*temp*std::pow(2.0,alphaBeta)/(newton0*newton2) ;
if(i == 1)
{
alphaReduced = alpha / nJacobi;
betaReduced = beta / nJacobi;
root1 = (1.0 + alpha) * (2.78002 / (4.0 + nJacobi * nJacobi) +
0.767999 * alphaReduced / nJacobi);
root2 = 1.0 + 1.48 * alphaReduced + 0.96002 * betaReduced +
0.451998 * alphaReduced * alphaReduced +
0.83001 * alphaReduced * betaReduced;
root = 1.0 - root1 / root2;
}
else if(i == 2)
{
root1 = (4.1002 + alpha) / ((1.0 + alpha) * (1.0 + 0.155998 * alpha));
root2 = 1.0 + 0.06 * (nJacobi - 8.0) * (1.0 + 0.12 * alpha) / nJacobi;
root3 =
1.0 + 0.012002 * beta * (1.0 + 0.24997 * std::fabs(alpha)) / nJacobi;
root -= (1.0 - root) * root1 * root2 * root3;
}
else if(i == 3)
{
root1 = (1.67001 + 0.27998 * alpha) / (1.0 + 0.37002 * alpha);
root2 = 1.0 + 0.22 * (nJacobi - 8.0) / nJacobi;
root3 = 1.0 + 8.0 * beta / ((6.28001 + beta) * nJacobi * nJacobi);
root -= (fAbscissa[0] - root) * root1 * root2 * root3;
}
else if(i == nJacobi - 1)
{
root1 = (1.0 + 0.235002 * beta) / (0.766001 + 0.118998 * beta);
root2 = 1.0 / (1.0 + 0.639002 * (nJacobi - 4.0) /
(1.0 + 0.71001 * (nJacobi - 4.0)));
root3 = 1.0 / (1.0 + 20.0 * alpha / ((7.5 + alpha) * nJacobi * nJacobi));
root += (root - fAbscissa[nJacobi - 4]) * root1 * root2 * root3;
}
else if(i == nJacobi)
{
root1 = (1.0 + 0.37002 * beta) / (1.67001 + 0.27998 * beta);
root2 = 1.0 / (1.0 + 0.22 * (nJacobi - 8.0) / nJacobi);
root3 =
1.0 / (1.0 + 8.0 * alpha / ((6.28002 + alpha) * nJacobi * nJacobi));
root += (root - fAbscissa[nJacobi - 3]) * root1 * root2 * root3;
}
else
{
root = 3.0 * fAbscissa[i - 2] - 3.0 * fAbscissa[i - 3] + fAbscissa[i - 4];
}
alphaBeta = alpha + beta;
for(k = 1; k <= maxNumber; ++k)
{
temp = 2.0 + alphaBeta;
newton1 = (alpha - beta + temp * root) / 2.0;
newton2 = 1.0;
for(G4int j = 2; j <= nJacobi; ++j)
{
newton3 = newton2;
newton2 = newton1;
temp = 2 * j + alphaBeta;
a = 2 * j * (j + alphaBeta) * (temp - 2.0);
b = (temp - 1.0) *
(alpha * alpha - beta * beta + temp * (temp - 2.0) * root);
c = 2.0 * (j - 1 + alpha) * (j - 1 + beta) * temp;
newton1 = (b * newton2 - c * newton3) / a;
}
newton0 = (nJacobi * (alpha - beta - temp * root) * newton1 +
2.0 * (nJacobi + alpha) * (nJacobi + beta) * newton2) /
(temp * (1.0 - root * root));
rootTemp = root;
root = rootTemp - newton1 / newton0;
if(std::fabs(root - rootTemp) <= tolerance)
{
break;
}
}
if(k > maxNumber)
{
G4Exception("G4GaussJacobiQ::G4GaussJacobiQ()", "OutOfRange",
FatalException, "Too many iterations in constructor.");
}
fAbscissa[i - 1] = root;
fWeight[i - 1] =
std::exp(GammaLogarithm((G4double)(alpha + nJacobi)) +
GammaLogarithm((G4double)(beta + nJacobi)) -
GammaLogarithm((G4double)(nJacobi + 1.0)) -
GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0))) *
temp * std::pow(2.0, alphaBeta) / (newton0 * newton2);
}
}
// ----------------------------------------------------------
//
// Gauss-Jacobi method for integration of
// ((1-x)^alpha)*((1+x)^beta)*pFunction(x)
// from minus unit to plus unit .
G4double
G4GaussJacobiQ::Integral() const
G4double G4GaussJacobiQ::Integral() const
{
G4double integral = 0.0 ;
for(G4int i=0;i<fNumber;i++)
{
integral += fWeight[i]*fFunction(fAbscissa[i]) ;
}
return integral ;
G4double integral = 0.0;
for(G4int i = 0; i < fNumber; ++i)
{
integral += fWeight[i] * fFunction(fAbscissa[i]);
}
return integral;
}
@@ -23,84 +23,85 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4GaussLaguerreQ class implementation
//
//
// Author: V.Grichine, 13.05.1997
// --------------------------------------------------------------------
#include "G4GaussLaguerreQ.hh"
// ------------------------------------------------------------
//
// Constructor for Gauss-Laguerre quadrature method: integral from zero to
// infinity of std::pow(x,alpha)*std::exp(-x)*f(x).
// The value of nLaguerre sets the accuracy.
// The constructor creates arrays fAbscissa[0,..,nLaguerre-1] and
// fWeight[0,..,nLaguerre-1] .
// The constructor creates arrays fAbscissa[0,..,nLaguerre-1] and
// fWeight[0,..,nLaguerre-1] .
//
G4GaussLaguerreQ::G4GaussLaguerreQ( function pFunction,
G4double alpha,
G4int nLaguerre )
: G4VGaussianQuadrature(pFunction)
G4GaussLaguerreQ::G4GaussLaguerreQ(function pFunction, G4double alpha,
G4int nLaguerre)
: G4VGaussianQuadrature(pFunction)
{
const G4double tolerance = 1.0e-10 ;
const G4int maxNumber = 12 ;
G4int i=1, k=1 ;
G4double newton0=0.0, newton1=0.0,
temp1=0.0, temp2=0.0, temp3=0.0, temp=0.0, cofi=0.0 ;
const G4double tolerance = 1.0e-10;
const G4int maxNumber = 12;
G4int i = 1, k = 1;
G4double newton0 = 0.0, newton1 = 0.0, temp1 = 0.0, temp2 = 0.0, temp3 = 0.0,
temp = 0.0, cofi = 0.0;
fNumber = nLaguerre ;
fAbscissa = new G4double[fNumber] ;
fWeight = new G4double[fNumber] ;
for(i=1;i<=fNumber;i++) // Loop over the desired roots
{
if(i == 1)
fNumber = nLaguerre;
fAbscissa = new G4double[fNumber];
fWeight = new G4double[fNumber];
for(i = 1; i <= fNumber; ++i) // Loop over the desired roots
{
if(i == 1)
{
newton0 = (1.0 + alpha) * (3.0 + 0.92 * alpha) /
(1.0 + 2.4 * fNumber + 1.8 * alpha);
}
else if(i == 2)
{
newton0 += (15.0 + 6.25 * alpha) / (1.0 + 0.9 * alpha + 2.5 * fNumber);
}
else
{
cofi = i - 2;
newton0 += ((1.0 + 2.55 * cofi) / (1.9 * cofi) +
1.26 * cofi * alpha / (1.0 + 3.5 * cofi)) *
(newton0 - fAbscissa[i - 3]) / (1.0 + 0.3 * alpha);
}
for(k = 1; k <= maxNumber; ++k)
{
temp1 = 1.0;
temp2 = 0.0;
for(G4int j = 1; j <= fNumber; ++j)
{
newton0 = (1.0 + alpha)*(3.0 + 0.92*alpha)
/ (1.0 + 2.4*fNumber + 1.8*alpha) ;
temp3 = temp2;
temp2 = temp1;
temp1 =
((2 * j - 1 + alpha - newton0) * temp2 - (j - 1 + alpha) * temp3) / j;
}
else if(i == 2)
temp = (fNumber * temp1 - (fNumber + alpha) * temp2) / newton0;
newton1 = newton0;
newton0 = newton1 - temp1 / temp;
if(std::fabs(newton0 - newton1) <= tolerance)
{
newton0 += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ;
break;
}
else
{
cofi = i - 2 ;
newton0 += ((1.0+2.55*cofi)/(1.9*cofi)
+ 1.26*cofi*alpha/(1.0+3.5*cofi))
* (newton0 - fAbscissa[i-3])/(1.0 + 0.3*alpha) ;
}
for(k=1;k<=maxNumber;k++)
{
temp1 = 1.0 ;
temp2 = 0.0 ;
for(G4int j=1;j<=fNumber;j++)
{
temp3 = temp2 ;
temp2 = temp1 ;
temp1 = ((2*j - 1 + alpha - newton0)*temp2
- (j - 1 + alpha)*temp3)/j ;
}
temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/newton0 ;
newton1 = newton0 ;
newton0 = newton1 - temp1/temp ;
if(std::fabs(newton0 - newton1) <= tolerance)
{
break ;
}
}
if(k > maxNumber)
{
G4Exception("G4GaussLaguerreQ::G4GaussLaguerreQ()",
"OutOfRange", FatalException,
"Too many iterations in Gauss-Laguerre constructor") ;
}
fAbscissa[i-1] = newton0 ;
fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber)
- GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ;
}
}
if(k > maxNumber)
{
G4Exception("G4GaussLaguerreQ::G4GaussLaguerreQ()", "OutOfRange",
FatalException,
"Too many iterations in Gauss-Laguerre constructor");
}
fAbscissa[i - 1] = newton0;
fWeight[i - 1] = -std::exp(GammaLogarithm(alpha + fNumber) -
GammaLogarithm((G4double) fNumber)) /
(temp * fNumber * temp2);
}
}
// -----------------------------------------------------------------
@@ -111,13 +112,12 @@ G4GaussLaguerreQ::G4GaussLaguerreQ( function pFunction,
// for which fAbscissa[i] and fWeight[i] arrays were created in
// G4VGaussianQuadrature(double,int) constructor
G4double
G4GaussLaguerreQ::Integral() const
G4double G4GaussLaguerreQ::Integral() const
{
G4double integral = 0.0 ;
for(G4int i=0;i<fNumber;i++)
{
integral += fWeight[i]*fFunction(fAbscissa[i]) ;
}
return integral ;
G4double integral = 0.0;
for(G4int i = 0; i < fNumber; ++i)
{
integral += fWeight[i] * fFunction(fAbscissa[i]);
}
return integral;
}
+146 -155
View File
@@ -23,66 +23,65 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4GaussLegendreQ class implementation
//
//
// Author: V.Grichine, 13.05.1997
// --------------------------------------------------------------------
#include "G4GaussLegendreQ.hh"
#include "G4PhysicalConstants.hh"
G4GaussLegendreQ::G4GaussLegendreQ( function pFunction )
: G4VGaussianQuadrature(pFunction)
{
}
G4GaussLegendreQ::G4GaussLegendreQ(function pFunction)
: G4VGaussianQuadrature(pFunction)
{}
// --------------------------------------------------------------------------
//
// Constructor for GaussLegendre quadrature method. The value nLegendre sets
// the accuracy required, i.e the number of points where the function pFunction
// will be evaluated during integration. The constructor creates the arrays for
// abscissas and weights that are used in Gauss-Legendre quadrature method.
// abscissas and weights that are used in Gauss-Legendre quadrature method.
// The values a and b are the limits of integration of the pFunction.
// nLegendre MUST BE EVEN !!!
G4GaussLegendreQ::G4GaussLegendreQ( function pFunction,
G4int nLegendre )
: G4VGaussianQuadrature(pFunction)
G4GaussLegendreQ::G4GaussLegendreQ(function pFunction, G4int nLegendre)
: G4VGaussianQuadrature(pFunction)
{
const G4double tolerance = 1.6e-10 ;
G4int k = nLegendre ;
fNumber = (nLegendre + 1)/2 ;
if(2*fNumber != k)
{
G4Exception("G4GaussLegendreQ::G4GaussLegendreQ()", "InvalidCall",
FatalException, "Invalid nLegendre argument !") ;
}
G4double newton0=0.0, newton1=0.0,
temp1=0.0, temp2=0.0, temp3=0.0, temp=0.0 ;
const G4double tolerance = 1.6e-10;
G4int k = nLegendre;
fNumber = (nLegendre + 1) / 2;
if(2 * fNumber != k)
{
G4Exception("G4GaussLegendreQ::G4GaussLegendreQ()", "InvalidCall",
FatalException, "Invalid nLegendre argument !");
}
G4double newton0 = 0.0, newton1 = 0.0, temp1 = 0.0, temp2 = 0.0, temp3 = 0.0,
temp = 0.0;
fAbscissa = new G4double[fNumber] ;
fWeight = new G4double[fNumber] ;
for(G4int i=1;i<=fNumber;i++) // Loop over the desired roots
{
newton0 = std::cos(pi*(i - 0.25)/(k + 0.5)) ; // Initial root
do // approximation
{ // loop of Newton's method
temp1 = 1.0 ;
temp2 = 0.0 ;
for(G4int j=1;j<=k;j++)
{
temp3 = temp2 ;
temp2 = temp1 ;
temp1 = ((2.0*j - 1.0)*newton0*temp2 - (j - 1.0)*temp3)/j ;
}
temp = k*(newton0*temp1 - temp2)/(newton0*newton0 - 1.0) ;
newton1 = newton0 ;
newton0 = newton1 - temp1/temp ; // Newton's method
fAbscissa = new G4double[fNumber];
fWeight = new G4double[fNumber];
for(G4int i = 1; i <= fNumber; ++i) // Loop over the desired roots
{
newton0 = std::cos(pi * (i - 0.25) / (k + 0.5)); // Initial root
do // approximation
{ // loop of Newton's method
temp1 = 1.0;
temp2 = 0.0;
for(G4int j = 1; j <= k; ++j)
{
temp3 = temp2;
temp2 = temp1;
temp1 = ((2.0 * j - 1.0) * newton0 * temp2 - (j - 1.0) * temp3) / j;
}
while(std::fabs(newton0 - newton1) > tolerance) ;
temp = k * (newton0 * temp1 - temp2) / (newton0 * newton0 - 1.0);
newton1 = newton0;
newton0 = newton1 - temp1 / temp; // Newton's method
} while(std::fabs(newton0 - newton1) > tolerance);
fAbscissa[fNumber-i] = newton0 ;
fWeight[fNumber-i] = 2.0/((1.0 - newton0*newton0)*temp*temp) ;
}
fAbscissa[fNumber - i] = newton0;
fWeight[fNumber - i] = 2.0 / ((1.0 - newton0 * newton0) * temp * temp);
}
}
// --------------------------------------------------------------------------
@@ -94,18 +93,16 @@ G4GaussLegendreQ::G4GaussLegendreQ( function pFunction,
// around the midpoint of the range of integration, there are actually only
// fNumber distinct values of each.
G4double
G4GaussLegendreQ::Integral(G4double a, G4double b) const
G4double G4GaussLegendreQ::Integral(G4double a, G4double b) const
{
G4double xMean = 0.5*(a + b),
xDiff = 0.5*(b - a),
integral = 0.0, dx = 0.0 ;
for(G4int i=0;i<fNumber;i++)
{
dx = xDiff*fAbscissa[i] ;
integral += fWeight[i]*(fFunction(xMean + dx) + fFunction(xMean - dx)) ;
}
return integral *= xDiff ;
G4double xMean = 0.5 * (a + b), xDiff = 0.5 * (b - a), integral = 0.0,
dx = 0.0;
for(G4int i = 0; i < fNumber; ++i)
{
dx = xDiff * fAbscissa[i];
integral += fWeight[i] * (fFunction(xMean + dx) + fFunction(xMean - dx));
}
return integral *= xDiff;
}
// --------------------------------------------------------------------------
@@ -117,27 +114,25 @@ G4GaussLegendreQ::Integral(G4double a, G4double b) const
// the range of integration, there are actually only five distinct values of
// each.
G4double
G4GaussLegendreQ::QuickIntegral(G4double a, G4double b) const
G4double G4GaussLegendreQ::QuickIntegral(G4double a, G4double b) const
{
// From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
// From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
0.679409568299024, 0.865063366688985,
0.973906528517172 } ;
static const G4double weight[] = { 0.295524224714753, 0.269266719309996,
0.219086362515982, 0.149451349150581,
0.066671344308688 } ;
G4double xMean = 0.5*(a + b),
xDiff = 0.5*(b - a),
integral = 0.0, dx = 0.0 ;
for(G4int i=0;i<5;i++)
{
dx = xDiff*abscissa[i] ;
integral += weight[i]*(fFunction(xMean + dx) + fFunction(xMean - dx)) ;
}
return integral *= xDiff ;
static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
0.679409568299024, 0.865063366688985,
0.973906528517172 };
static const G4double weight[] = { 0.295524224714753, 0.269266719309996,
0.219086362515982, 0.149451349150581,
0.066671344308688 };
G4double xMean = 0.5 * (a + b), xDiff = 0.5 * (b - a), integral = 0.0,
dx = 0.0;
for(G4int i = 0; i < 5; ++i)
{
dx = xDiff * abscissa[i];
integral += weight[i] * (fFunction(xMean + dx) + fFunction(xMean - dx));
}
return integral *= xDiff;
}
// -------------------------------------------------------------------------
@@ -149,87 +144,83 @@ G4double
// the range of integration, there are actually only five distinct values of
// each.
G4double
G4GaussLegendreQ::AccurateIntegral(G4double a, G4double b) const
{
// From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
static const
G4double abscissa[] = {
0.016276744849602969579, 0.048812985136049731112,
0.081297495464425558994, 0.113695850110665920911,
0.145973714654896941989, 0.178096882367618602759, // 6
0.210031310460567203603, 0.241743156163840012328,
0.273198812591049141487, 0.304364944354496353024,
0.335208522892625422616, 0.365696861472313635031, // 12
0.395797649828908603285, 0.425478988407300545365,
0.454709422167743008636, 0.483457973920596359768,
0.511694177154667673586, 0.539388108324357436227, // 18
0.566510418561397168404, 0.593032364777572080684,
0.618925840125468570386, 0.644163403784967106798,
0.668718310043916153953, 0.692564536642171561344, // 24
0.715676812348967626225, 0.738030643744400132851,
0.759602341176647498703, 0.780369043867433217604,
0.800308744139140817229, 0.819400310737931675539, // 30
0.837623511228187121494, 0.854959033434601455463,
0.871388505909296502874, 0.886894517402420416057,
0.901460635315852341319, 0.915071423120898074206, // 36
0.927712456722308690965, 0.939370339752755216932,
0.950032717784437635756, 0.959688291448742539300,
0.968326828463264212174, 0.975939174585136466453, // 42
0.982517263563014677447, 0.988054126329623799481,
0.992543900323762624572, 0.995981842987209290650,
0.998364375863181677724, 0.999689503883230766828 // 48
} ;
static const
G4double weight[] = {
0.032550614492363166242, 0.032516118713868835987,
0.032447163714064269364, 0.032343822568575928429,
0.032206204794030250669, 0.032034456231992663218, // 6
0.031828758894411006535, 0.031589330770727168558,
0.031316425596862355813, 0.031010332586313837423,
0.030671376123669149014, 0.030299915420827593794, // 12
0.029896344136328385984, 0.029461089958167905970,
0.028994614150555236543, 0.028497411065085385646,
0.027970007616848334440, 0.027412962726029242823, // 18
0.026826866725591762198, 0.026212340735672413913,
0.025570036005349361499, 0.024900633222483610288,
0.024204841792364691282, 0.023483399085926219842, // 24
0.022737069658329374001, 0.021966644438744349195,
0.021172939892191298988, 0.020356797154333324595,
0.019519081140145022410, 0.018660679627411467385, // 30
0.017782502316045260838, 0.016885479864245172450,
0.015970562902562291381, 0.015038721026994938006,
0.014090941772314860916, 0.013128229566961572637, // 36
0.012151604671088319635, 0.011162102099838498591,
0.010160770535008415758, 0.009148671230783386633,
0.008126876925698759217, 0.007096470791153865269, // 42
0.006058545504235961683, 0.005014202742927517693,
0.003964554338444686674, 0.002910731817934946408,
0.001853960788946921732, 0.000796792065552012429 // 48
} ;
G4double xMean = 0.5*(a + b),
xDiff = 0.5*(b - a),
integral = 0.0, dx = 0.0 ;
for(G4int i=0;i<48;i++)
{
dx = xDiff*abscissa[i] ;
integral += weight[i]*(fFunction(xMean + dx) + fFunction(xMean - dx)) ;
}
return integral *= xDiff ;
G4double G4GaussLegendreQ::AccurateIntegral(G4double a, G4double b) const
{
// From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
static const G4double abscissa[] = {
0.016276744849602969579, 0.048812985136049731112,
0.081297495464425558994, 0.113695850110665920911,
0.145973714654896941989, 0.178096882367618602759, // 6
0.210031310460567203603, 0.241743156163840012328,
0.273198812591049141487, 0.304364944354496353024,
0.335208522892625422616, 0.365696861472313635031, // 12
0.395797649828908603285, 0.425478988407300545365,
0.454709422167743008636, 0.483457973920596359768,
0.511694177154667673586, 0.539388108324357436227, // 18
0.566510418561397168404, 0.593032364777572080684,
0.618925840125468570386, 0.644163403784967106798,
0.668718310043916153953, 0.692564536642171561344, // 24
0.715676812348967626225, 0.738030643744400132851,
0.759602341176647498703, 0.780369043867433217604,
0.800308744139140817229, 0.819400310737931675539, // 30
0.837623511228187121494, 0.854959033434601455463,
0.871388505909296502874, 0.886894517402420416057,
0.901460635315852341319, 0.915071423120898074206, // 36
0.927712456722308690965, 0.939370339752755216932,
0.950032717784437635756, 0.959688291448742539300,
0.968326828463264212174, 0.975939174585136466453, // 42
0.982517263563014677447, 0.988054126329623799481,
0.992543900323762624572, 0.995981842987209290650,
0.998364375863181677724, 0.999689503883230766828 // 48
};
static const G4double weight[] = {
0.032550614492363166242, 0.032516118713868835987,
0.032447163714064269364, 0.032343822568575928429,
0.032206204794030250669, 0.032034456231992663218, // 6
0.031828758894411006535, 0.031589330770727168558,
0.031316425596862355813, 0.031010332586313837423,
0.030671376123669149014, 0.030299915420827593794, // 12
0.029896344136328385984, 0.029461089958167905970,
0.028994614150555236543, 0.028497411065085385646,
0.027970007616848334440, 0.027412962726029242823, // 18
0.026826866725591762198, 0.026212340735672413913,
0.025570036005349361499, 0.024900633222483610288,
0.024204841792364691282, 0.023483399085926219842, // 24
0.022737069658329374001, 0.021966644438744349195,
0.021172939892191298988, 0.020356797154333324595,
0.019519081140145022410, 0.018660679627411467385, // 30
0.017782502316045260838, 0.016885479864245172450,
0.015970562902562291381, 0.015038721026994938006,
0.014090941772314860916, 0.013128229566961572637, // 36
0.012151604671088319635, 0.011162102099838498591,
0.010160770535008415758, 0.009148671230783386633,
0.008126876925698759217, 0.007096470791153865269, // 42
0.006058545504235961683, 0.005014202742927517693,
0.003964554338444686674, 0.002910731817934946408,
0.001853960788946921732, 0.000796792065552012429 // 48
};
G4double xMean = 0.5 * (a + b), xDiff = 0.5 * (b - a), integral = 0.0,
dx = 0.0;
for(G4int i = 0; i < 48; ++i)
{
dx = xDiff * abscissa[i];
integral += weight[i] * (fFunction(xMean + dx) + fFunction(xMean - dx));
}
return integral *= xDiff;
}
File diff suppressed because it is too large Load Diff
@@ -23,161 +23,134 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4SimpleIntegration class implementation
//
//
// Implementation file for simple integration methods
//
// Author: V.Grichine, 26.03.1997
// --------------------------------------------------------------------
#include "globals.hh"
#include "G4SimpleIntegration.hh"
#include "globals.hh"
G4SimpleIntegration::G4SimpleIntegration(function pFunction)
: fFunction(pFunction)
{}
G4SimpleIntegration::G4SimpleIntegration( function pFunction )
: fFunction(pFunction),
fTolerance(.0001),
fMaxDepth(100)
G4SimpleIntegration::G4SimpleIntegration(function pFunction,
G4double pTolerance)
: fFunction(pFunction)
, fTolerance(pTolerance)
{}
G4SimpleIntegration::~G4SimpleIntegration() {}
// Simple integration methods
G4double G4SimpleIntegration::Trapezoidal(G4double xInitial, G4double xFinal,
G4int iterationNumber)
{
G4double Step = (xFinal - xInitial) / iterationNumber;
G4double mean = (fFunction(xInitial) + fFunction(xFinal)) * 0.5;
G4double x = xInitial;
for(G4int i = 1; i < iterationNumber; ++i)
{
x += Step;
mean += fFunction(x);
}
return mean * Step;
}
G4SimpleIntegration::G4SimpleIntegration( function pFunction,
G4double pTolerance)
: fFunction(pFunction),
fTolerance(pTolerance),
fMaxDepth(100)
G4double G4SimpleIntegration::MidPoint(G4double xInitial, G4double xFinal,
G4int iterationNumber)
{
G4double Step = (xFinal - xInitial) / iterationNumber;
G4double x = xInitial + 0.5 * Step;
G4double mean = fFunction(x);
for(G4int i = 1; i < iterationNumber; ++i)
{
x += Step;
mean += fFunction(x);
}
return mean * Step;
}
G4SimpleIntegration::~G4SimpleIntegration()
G4double G4SimpleIntegration::Gauss(G4double xInitial, G4double xFinal,
G4int iterationNumber)
{
}
// Simple integration methods
G4double
G4SimpleIntegration::Trapezoidal(G4double xInitial,
G4double xFinal,
G4int iterationNumber )
{
G4double Step = (xFinal - xInitial)/iterationNumber ;
G4double mean = (fFunction(xInitial) + fFunction(xFinal))*0.5 ;
G4double x = xInitial ;
for(G4int i=1;i<iterationNumber;i++)
{
x += Step ;
mean += fFunction(x) ;
}
return mean*Step ;
G4double x = 0.;
static const G4double root = 1.0 / std::sqrt(3.0);
G4double Step = (xFinal - xInitial) / (2.0 * iterationNumber);
G4double delta = Step * root;
G4double mean = 0.0;
for(G4int i = 0; i < iterationNumber; ++i)
{
x = (2 * i + 1) * Step;
mean += (fFunction(x + delta) + fFunction(x - delta));
}
return mean * Step;
}
G4double
G4SimpleIntegration::MidPoint(G4double xInitial,
G4double xFinal,
G4int iterationNumber )
G4double G4SimpleIntegration::Simpson(G4double xInitial, G4double xFinal,
G4int iterationNumber)
{
G4double Step = (xFinal - xInitial)/iterationNumber ;
G4double x = xInitial + 0.5*Step;
G4double mean = fFunction(x) ;
for(G4int i=1;i<iterationNumber;i++)
{
x += Step ;
mean += fFunction(x) ;
}
return mean*Step ;
G4double Step = (xFinal - xInitial) / iterationNumber;
G4double x = xInitial;
G4double xPlus = xInitial + 0.5 * Step;
G4double mean = (fFunction(xInitial) + fFunction(xFinal)) * 0.5;
G4double sum = fFunction(xPlus);
for(G4int i = 1; i < iterationNumber; ++i)
{
x += Step;
xPlus += Step;
mean += fFunction(x);
sum += fFunction(xPlus);
}
mean += 2.0 * sum;
return mean * Step / 3.0;
}
G4double
G4SimpleIntegration::Gauss(G4double xInitial,
G4double xFinal,
G4int iterationNumber )
// Adaptive Gauss integration
G4double G4SimpleIntegration::AdaptGaussIntegration(G4double xInitial,
G4double xFinal)
{
G4double x=0.;
static const G4double root = 1.0/std::sqrt(3.0) ;
G4double Step = (xFinal - xInitial)/(2.0*iterationNumber) ;
G4double delta = Step*root ;
G4double mean = 0.0 ;
for(G4int i=0;i<iterationNumber;i++)
{
x = (2*i + 1)*Step ;
mean += (fFunction(x+delta) + fFunction(x-delta)) ;
}
return mean*Step ;
G4int depth = 0;
G4double sum = 0.0;
AdaptGauss(xInitial, xFinal, sum, depth);
return sum;
}
G4double
G4SimpleIntegration::Simpson(G4double xInitial,
G4double xFinal,
G4int iterationNumber )
G4double G4SimpleIntegration::Gauss(G4double xInitial, G4double xFinal)
{
G4double Step = (xFinal - xInitial)/iterationNumber ;
G4double x = xInitial ;
G4double xPlus = xInitial + 0.5*Step ;
G4double mean = (fFunction(xInitial) + fFunction(xFinal))*0.5 ;
G4double sum = fFunction(xPlus) ;
for(G4int i=1;i<iterationNumber;i++)
{
x += Step ;
xPlus += Step ;
mean += fFunction(x) ;
sum += fFunction(xPlus) ;
}
mean += 2.0*sum ;
return mean*Step/3.0 ;
static const G4double root = 1.0 / std::sqrt(3.0);
G4double xMean = (xInitial + xFinal) / 2.0;
G4double Step = (xFinal - xInitial) / 2.0;
G4double delta = Step * root;
G4double sum = (fFunction(xMean + delta) + fFunction(xMean - delta));
return sum * Step;
}
// Adaptive Gauss integration
G4double
G4SimpleIntegration::AdaptGaussIntegration( G4double xInitial,
G4double xFinal )
void G4SimpleIntegration::AdaptGauss(G4double xInitial, G4double xFinal,
G4double& sum, G4int& depth)
{
G4int depth = 0 ;
G4double sum = 0.0 ;
AdaptGauss(xInitial,xFinal,sum,depth) ;
return sum ;
}
G4double
G4SimpleIntegration::Gauss( G4double xInitial,
G4double xFinal )
{
static const G4double root = 1.0/std::sqrt(3.0) ;
G4double xMean = (xInitial + xFinal)/2.0 ;
G4double Step = (xFinal - xInitial)/2.0 ;
G4double delta = Step*root ;
G4double sum = (fFunction(xMean + delta) + fFunction(xMean - delta)) ;
return sum*Step ;
}
void
G4SimpleIntegration::AdaptGauss( G4double xInitial,
G4double xFinal,
G4double& sum,
G4int& depth )
{
if(depth >fMaxDepth)
{
G4Exception("G4SimpleIntegration::AdaptGauss()", "Error",
FatalException, "Function varies too rapidly !") ;
}
G4double xMean = (xInitial + xFinal)/2.0 ;
G4double leftHalf = Gauss(xInitial,xMean) ;
G4double rightHalf = Gauss(xMean,xFinal) ;
G4double full = Gauss(xInitial,xFinal) ;
if(std::fabs(leftHalf+rightHalf-full) < fTolerance)
{
sum += full ;
}
else
{
depth++ ;
AdaptGauss(xInitial,xMean,sum,depth) ;
AdaptGauss(xMean,xFinal,sum,depth) ;
}
if(depth > fMaxDepth)
{
G4Exception("G4SimpleIntegration::AdaptGauss()", "Error", FatalException,
"Function varies too rapidly !");
}
G4double xMean = (xInitial + xFinal) / 2.0;
G4double leftHalf = Gauss(xInitial, xMean);
G4double rightHalf = Gauss(xMean, xFinal);
G4double full = Gauss(xInitial, xFinal);
if(std::fabs(leftHalf + rightHalf - full) < fTolerance)
{
sum += full;
}
else
{
++depth;
AdaptGauss(xInitial, xMean, sum, depth);
AdaptGauss(xMean, xFinal, sum, depth);
}
}
+47 -62
View File
@@ -23,28 +23,16 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4StatDouble class implementation
//
//
//
// ----------------------------------------------------------------------
// class G4StatDouble
//
// Implementation.
// Original Author: Giovanni Santin (ESA) - October 2005 in GRAS tool
// Adapted by: John Apostolakis - November 2011
// --------------------------------------------------------------------
#include "G4StatDouble.hh"
G4StatDouble::G4StatDouble()
{
reset();
}
G4StatDouble::G4StatDouble() { reset(); }
G4StatDouble::G4StatDouble(G4double x)
{
reset();
fill(x);
}
G4StatDouble::G4StatDouble(G4double x) { fill(x); }
void G4StatDouble::reset()
{
@@ -56,33 +44,31 @@ void G4StatDouble::reset()
m_scale = 1.;
}
G4StatDouble::~G4StatDouble()
{}
G4StatDouble::~G4StatDouble() {}
void G4StatDouble::fill(G4double value, G4double weight)
{
m_sum_wx += value * weight;
m_sum_wx += value * weight;
m_sum_wx2 += value * value * weight;
if(m_n < INT_MAX) { ++m_n; }
m_sum_w += weight;
m_sum_w2 += weight * weight;
if (weight <= 0.)
if(m_n < INT_MAX)
{
G4cout << "[G4StatDouble::fill] WARNING: weight<=0. "
<< weight << G4endl;
++m_n;
}
m_sum_w += weight;
m_sum_w2 += weight * weight;
if(weight <= 0.)
{
G4cout << "[G4StatDouble::fill] WARNING: weight<=0. " << weight << G4endl;
}
}
void G4StatDouble::scale(G4double value)
{
m_scale = m_scale * value;
}
void G4StatDouble::scale(G4double value) { m_scale = m_scale * value; }
G4double G4StatDouble::mean() const
{
G4double mean_val = 0.;
if (m_sum_w > 0.)
if(m_sum_w > 0.)
{
mean_val = m_sum_wx / m_sum_w;
}
@@ -92,52 +78,51 @@ G4double G4StatDouble::mean() const
G4double G4StatDouble::mean(G4double ext_sum_w) const
{
G4double factor = 0.;
// factor to rescale the Mean for the requested number
// of events (or sum of weights) ext_sum_w
// factor to rescale the Mean for the requested number
// of events (or sum of weights) ext_sum_w
if (ext_sum_w > 0)
if(ext_sum_w > 0)
{
factor = m_sum_w;
factor = m_sum_w;
factor /= ext_sum_w;
}
return mean() * factor;
}
G4double G4StatDouble::rms(G4double ssum_wx, G4double ssum_wx2,
G4double ssum_w, G4int nn)
G4double G4StatDouble::rms(G4double ssum_wx, G4double ssum_wx2, G4double ssum_w,
G4int nn)
{
G4double vrms = 0.0;
if (nn > 1)
if(nn > 1)
{
G4double vmean = ssum_wx / ssum_w;
G4double xn = nn;
G4double tmp =
G4double xn = nn;
G4double tmp =
// from GNU Scientific Library. This part is equivalent to N/(N-1)
// when w_i = w
// ((m_sum_w * m_sum_w) / (m_sum_w * m_sum_w - m_sum_w2))
// ((m_sum_w * m_sum_w) / (m_sum_w * m_sum_w - m_sum_w2))
// from NIST "DATAPLOT Reference manual", Page 2-66
// from NIST "DATAPLOT Reference manual", Page 2-66
// http://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weightsd.pdf
// rewritten based on: SUM[w(x-m)^2]/SUM[w] = SUM[wx^2]/SUM[w] - m^2
// and dividing it by sqrt[n] to go from rms of distribution to the
// rms of the mean value
(xn / (xn - 1))
* ((ssum_wx2 / ssum_w) - (vmean * vmean));
(xn / (xn - 1)) * ((ssum_wx2 / ssum_w) - (vmean * vmean));
tmp = std::max(tmp, 0.0); // this avoids observed computation problem
vrms = std::sqrt( tmp );
// G4cout << "[G4StatDoubleElement::rms] m_sum_wx: " << m_sum_wx
// << " m_sum_wx2: " << m_sum_wx2 << " m_sum_w: " << m_sum_w
// << " m_n: " << m_n << " tmp: " << tmp<< " rms: " << rms
// << G4endl;
// G4cout << "[G4StatDoubleElement::rms] (m_n / (m_n - 1)): " << (xn/(xn - 1))
// << " (m_sum_wx2 / m_sum_w): " << (m_sum_wx2 / m_sum_w)
// << " (mean * mean): " << (mean * mean)
// << " ((m_sum_wx2 / m_sum_w) - (mean * mean)): "
// << ((m_sum_wx2 / m_sum_w) - (mean * mean))
// << G4endl;
tmp = std::max(tmp, 0.0); // this avoids observed computation problem
vrms = std::sqrt(tmp);
// G4cout << "[G4StatDoubleElement::rms] m_sum_wx: " << m_sum_wx
// << " m_sum_wx2: " << m_sum_wx2 << " m_sum_w: " << m_sum_w
// << " m_n: " << m_n << " tmp: " << tmp<< " rms: " << rms
// << G4endl;
// G4cout << "[G4StatDoubleElement::rms] (m_n / (m_n - 1)): " << (xn/(xn -
// 1))
// << " (m_sum_wx2 / m_sum_w): " << (m_sum_wx2 / m_sum_w)
// << " (mean * mean): " << (mean * mean)
// << " ((m_sum_wx2 / m_sum_w) - (mean * mean)): "
// << ((m_sum_wx2 / m_sum_w) - (mean * mean))
// << G4endl;
}
return vrms * m_scale;
}
@@ -158,16 +143,16 @@ G4double G4StatDouble::rms(G4double ext_sum_w, G4int ext_n)
// it is useful when, given a number ext_n of events with sum of the weights
// ext_sum_w, only m_n (with sum of weights m_sum_w) are actually accumulated
// in the internal summation (e.g. for a dose variable in a volume, because
// only a few particles reach that volume)
// only a few particles reach that volume)
return rms(m_sum_wx, m_sum_wx2, ext_sum_w, ext_n);
}
void G4StatDouble::add(const G4StatDouble* ptr)
{
m_n += ptr->n();
m_sum_w += ptr->sum_w();
m_sum_w2 += ptr->sum_w2();
m_sum_wx += ptr->sum_wx();
m_n += ptr->n();
m_sum_w += ptr->sum_w();
m_sum_w2 += ptr->sum_w2();
m_sum_wx += ptr->sum_wx();
m_sum_wx2 += ptr->sum_wx2();
}
@@ -23,75 +23,68 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4VGaussianQuadrature class implementation
//
//
// Implementation file for G4VGaussianQuadrature virtual base class
//
// Author: V.Grichine, 18.04.1997
// --------------------------------------------------------------------
#include "G4VGaussianQuadrature.hh"
#include "G4ios.hh"
#include "globals.hh"
#include "G4VGaussianQuadrature.hh"
G4VGaussianQuadrature::G4VGaussianQuadrature( function pFunction )
: fFunction(pFunction), fAbscissa(0), fWeight(0), fNumber(0)
{
}
G4VGaussianQuadrature::G4VGaussianQuadrature(function pFunction)
: fFunction(pFunction)
{}
// -------------------------------------------------------------------
//
// Virtual destructor which deletes dynamically allocated memory
//
G4VGaussianQuadrature::~G4VGaussianQuadrature()
G4VGaussianQuadrature::~G4VGaussianQuadrature()
{
delete[] fAbscissa ;
delete[] fWeight ;
delete[] fAbscissa;
delete[] fWeight;
}
// -------------------------- Access functions ----------------------------------
// -------------------------- Access functions
// ----------------------------------
G4double
G4VGaussianQuadrature::GetAbscissa(G4int index) const
G4double G4VGaussianQuadrature::GetAbscissa(G4int index) const
{
return fAbscissa[index] ;
return fAbscissa[index];
}
G4double
G4VGaussianQuadrature::GetWeight(G4int index) const
G4double G4VGaussianQuadrature::GetWeight(G4int index) const
{
return fWeight[index] ;
return fWeight[index];
}
G4int G4VGaussianQuadrature::GetNumber() const
{
return fNumber ;
}
G4int G4VGaussianQuadrature::GetNumber() const { return fNumber; }
// ----------------------------------------------------------------------------
//
// Auxiliary function which returns the value of std::log(gamma-function(x))
//
G4double
G4VGaussianQuadrature::GammaLogarithm(G4double xx)
G4double G4VGaussianQuadrature::GammaLogarithm(G4double xx)
{
// Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for
// xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
// (Adapted from Numerical Recipes in C)
// Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for
// xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
// (Adapted from Numerical Recipes in C)
static const G4double cof[6] = { 76.18009172947146, -86.50532032941677,
24.01409824083091, -1.231739572450155,
24.01409824083091, -1.231739572450155,
0.1208650973866179e-2, -0.5395239384953e-5 };
G4double x = xx - 1.0;
G4double tmp = x + 5.5;
G4double x = xx - 1.0;
G4double tmp = x + 5.5;
tmp -= (x + 0.5) * std::log(tmp);
G4double ser = 1.000000000190015;
for ( size_t j = 0; j <= 5; j++ )
for(size_t j = 0; j <= 5; ++j)
{
x += 1.0;
ser += cof[j]/x;
ser += cof[j] / x;
}
return -tmp + std::log(2.5066282746310005*ser);
return -tmp + std::log(2.5066282746310005 * ser);
}