source: trunk/source/processes/electromagnetic/lowenergy/src/G4PenelopeInterpolator.cc@ 1197

Last change on this file since 1197 was 819, checked in by garnier, 17 years ago

import all except CVS

File size: 7.0 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27//
28// Author: Luciano Pandola (Luciano.Pandola@cern.ch)
29//
30// History:
31// -----------
32// 17 Feb 2003 LP Created
33// 17 Dec 2003 LP Removed memory leak
34// 17 Mar 2004 LP Removed unnecessary calls to std::pow(a,b)
35//
36// -------------------------------------------------------------------
37
38#include "G4PenelopeInterpolator.hh"
39#include "G4DataVector.hh"
40
41G4PenelopeInterpolator::G4PenelopeInterpolator(G4double* pX,G4double* pY,G4int nOfData,G4double S1,G4double SN) :
42 a(0),b(0),c(0),d(0),x(0),y(0)
43{
44 // pX = X grid points (ascending order)
45 // pY = corresponding function values
46 // nOfData = number of points in the grid > 4
47 // S1 and S2 = second derivatives at X[0] and X[nOfData-1]
48 a = new G4DataVector;
49 b = new G4DataVector;
50 c = new G4DataVector;
51 d = new G4DataVector;
52
53 if (nOfData < 4 )
54 {
55 G4String excep = "Spline interpolation cannot be performed with less than 4 points";
56 G4Exception(excep);
57 }
58
59 G4int N1=nOfData-1;
60 G4int N2=nOfData-2;
61 G4int i;
62 G4int k=0;
63 G4DataVector A(N1),B(N2),D(nOfData);//auxiliary arrays
64 A.clear();
65 B.clear();
66 D.clear();
67 for (i=0;i<N1;i++){
68 if ((pX[i+1]-pX[i]) < 1.0e-13)
69 {
70 G4String excep = "Spline x values not in increasing order";
71 G4Exception(excep);
72 }
73 A.push_back(pX[i+1]-pX[i]);
74 D.push_back((pY[i+1]-pY[i])/A[i]);
75 }
76
77 //Symmetric coefficient matrix
78 for (i=0;i<N2;i++){
79 B.push_back(2.0*(A[i]+A[i+1]));
80 k=N1-i-1;
81 D[k]=6.0*(D[k]-D[k-1]);
82 }
83 D[1]=D[1]-A[0]*S1;
84 D[N1-1]=D[N1-1]-A[N1-1]*SN;
85
86 //Gauss solution of the tridiagonal system
87 for (i=1;i<N2;i++){
88 G4double R=A[i]/B[i-1];
89 B[i]=B[i]-R*A[i];
90 D[i+1]=D[i+1]-R*D[i];
91 }
92
93 //The sigma coefficients are stored in array D
94 D[N1-1]=D[N1-1]/B[N2-1];
95 for (i=1;i<N2;i++){
96 k=N1-i-1;
97 D[k]=(D[k]-A[k]*D[k+1])/B[k-1];
98 }
99 D.push_back(SN);
100
101 //Spline coefficients
102 G4double SI1=S1;
103 G4double SI=0,H=0,HI=0;
104 G4double store=0;
105 G4double help1=0;
106 G4double help2=0;
107
108 for (i=0;i<N1;i++){
109 SI=SI1;
110 SI1=D[i+1];
111 H=A[i];
112 HI=1.0/H;
113 help1 = pX[i+1]*pX[i+1]*pX[i+1];
114 help2 = pX[i]*pX[i]*pX[i];
115 store=HI*(SI*help1-SI1*help2)/6.0+HI*(pY[i]*pX[i+1]-pY[i+1]*pX[i])+
116 H*(SI1*pX[i]-SI*pX[i+1])/6.0;
117 a->push_back(store);
118 store=(HI/2.0)*(SI1*(pX[i]*pX[i])-SI*(pX[i+1]*pX[i+1]))+HI*(pY[i+1]-pY[i])+(H/6.0)*(SI-SI1);
119 b->push_back(store);
120 store=(HI/2.0)*(SI*pX[i+1]-SI1*pX[i]);
121 c->push_back(store);
122 store=(HI/6.0)*(SI1-SI);
123 d->push_back(store);
124 }
125 //Natural cubic spline for x > x[nOfData-1]
126 G4double FN=pY[nOfData-1];
127 store=(*b)[N1-1]+pX[nOfData-1]*(2.0*(*c)[N1-1]+pX[nOfData-1]*3.0*(*d)[N1-1]);
128 a->push_back(FN-pX[nOfData-1]*store);
129 b->push_back(store);
130 c->push_back(0.0);
131 d->push_back(0.0);
132
133 x = new G4DataVector;
134 y = new G4DataVector;
135
136 for (i=0;i<nOfData;i++){
137 x->push_back(pX[i]);
138 y->push_back(pY[i]);
139 }
140 return;
141}
142
143G4PenelopeInterpolator::~G4PenelopeInterpolator()
144{
145 delete a;
146 delete b;
147 delete c;
148 delete d;
149 delete x;
150 delete y;
151}
152
153G4double G4PenelopeInterpolator::CubicSplineInterpolation(G4double xx)
154{
155 G4double interp=0;
156 G4int index = FindBin(xx);
157 interp=(*a)[index]+xx*((*b)[index]+xx*((*c)[index]+xx*(*d)[index]));
158 return interp;
159}
160
161G4double G4PenelopeInterpolator::FirstDerivative(G4double xx)
162{
163 G4double interp=0;
164 G4int index = FindBin(xx);
165 interp=(*b)[index]+xx*((*c)[index]*2.0+xx*(*d)[index]*3.0);
166 return interp;
167}
168
169G4double G4PenelopeInterpolator::CalculateMomentum(G4double UpperLimit,
170 G4int MomentumOrder)
171{
172 G4int i;
173 G4int nOfData = (G4int) x->size();
174 const G4double eps=1.0e-35;
175 if (MomentumOrder < -1) G4Exception("Calculate Momentum: error 0");
176 if (nOfData < 2) G4Exception("Calculate Momentum: error 1");
177 if ((*x)[0]<0) G4Exception("Calculate Momentum: error 2");
178 for (i=1;i<nOfData;i++)
179 {
180 if ((*x)[i]<0) G4Exception("Calculate Momentum: error 3");
181 if ((*x)[i] < (*x)[i-1]) G4Exception ("Calculate Momentum: error 4");
182 }
183
184 G4double RMom=0.0;
185 if (UpperLimit < (*x)[0]) return RMom;
186 G4int iend=0;
187 G4double xt=std::min(UpperLimit,(*x)[nOfData-1]);
188 G4double x1,x2,y1,y2;
189 G4double xtc,dx,dy,a1,b1,ds;
190 for (i=0;i<(nOfData-1);i++){
191 x1=std::max((*x)[i],eps);
192 y1=(*y)[i];
193 x2=std::max((*x)[i+1],eps);
194 y2=(*y)[i+1];
195 if (xt < x2)
196 {
197 xtc=xt;
198 iend=1;
199 }
200 else
201 {
202 xtc=x2;
203 }
204 dx=x2-x1;
205 dy=y2-y1;
206 if (std::abs(dx) > (1e-14*std::abs(dy)))
207 {
208 b1=dy/dx;
209 a1=y1-b1*x1;
210 if (MomentumOrder == -1)
211 {
212 ds=a1*std::log(xtc/x1)+b1*(xtc-x1);
213 }
214 else
215 {
216 ds=a1*(std::pow(xtc,MomentumOrder+1)-std::pow(x1,MomentumOrder+1))/ ((G4double) (MomentumOrder+1))+
217 b1*(std::pow(xtc,MomentumOrder+2)-std::pow(x1,MomentumOrder+2))/((G4double) (MomentumOrder+2));
218 }
219 }
220 else
221 {
222 ds=0.5*(y1+y2)*std::pow((xtc-x1),MomentumOrder);
223 }
224 RMom += ds;
225 if (iend != 0) return RMom;
226 }
227 return RMom;
228}
229
230G4int G4PenelopeInterpolator::FindBin(G4double xx)
231{
232 //Finds the interval x[i],x[i+1] which contains the value xx
233
234 G4int nbOfPoints=x->size();
235
236 if (xx > (*x)[nbOfPoints-1])
237 {
238 return (nbOfPoints-1);
239 }
240 if (xx < (*x)[0])
241 {
242 return 0;
243 }
244 G4int i=0,i1=nbOfPoints-1;
245 do{
246 G4int it=(i+i1)/2;
247 if (xx > (*x)[it])
248 {
249 i=it;
250 }
251 else
252 {
253 i1=it;
254 }
255 } while((i1-i) > 1);
256 return i;
257}
258
259
260
261
Note: See TracBrowser for help on using the repository browser.