COSMOS v7.655  COSMOSv7655
(AirShowerMC)
kdexpIntFb.f
Go to the documentation of this file.
1 !c
2 !c Takahashi-Mori's double exponential integration quadrature
3 !c
4 ! This is completely the same as kdexpIntF except for
5 ! the name; this can be used if two are used for double
6 ! integral to avoid recursive call.
7 !
8 ! *******************************************************
9  subroutine kdexpintfb(func, a, b, eps, ans, error, icon)
10 ! *******************************************************
11  implicit none
12 !
13 ! Numerical integration in a finite range by Takahashi-Mori's
14 ! double exponential integraton method.
15 ! The method gives accurate result even if there are singularities
16 ! at the integration limits. If there is a very sharp peak in the
17 ! midst of the integration region, the method will not give
18 ! a good result.
19 !
20 !
21  real*8 func ! input. integrand function name with 1 argument
22  ! you have to declare 'external'
23  ! Argument is real*8 xx(2).
24  ! xx(1) is x,
25  ! Let aa=min(a, b), bb=max(a,b)
26  ! xx(2) = aa - x if aa<= x < (aa+bb)/2
27  ! = bb - x if bb> x >= (aa+bb)/2
28  ! So you should use xx(2) if at aa and/or bb
29  ! func is singular;
30  ! x(2) < 0 ==> f(aa-x(2))
31  ! x(2) >=0 ==> f(bb-x(2))
32 
33  real*8 a ! input. lower limit of the integration region
34  real*8 b ! input. upper //
35  ! b may be <=a.
36  real*8 eps ! input. relative or absolute error of the
37  ! intetegration you want to get.
38  ! if |ans| is > 1, used for relative error
39  ! else used for absolute error.
40  ! eps ~> 1.d-9 may be a good choice.
41  real*8 ans ! output. approximate integration value.
42  real*8 error ! output. estimated error (relative or absolute)
43  ! depending on |ans|.
44  integer icon ! output. 0 --> ans is reliable.
45  ! 1 --> ans may have a larger error than
46  ! your request.
47  ! 2 --> input error so that ans is undef.
48 !
49 !
50 !
51 
52  integer halveNtime ! if the integration accuracy is not enough
53  ! halve the equi-step of trapezoidal rule.
54  ! halving is tried upto halveNtime times.
55  integer pointsInUnit ! see graph below
56  integer blocks ! we take 10 blocks
57  integer totalpoints ! (max number of points)-1 where function
58  ! is evaluated.
59 !
60 ! integration bin; unit is
61 !
62 ! 1 2 3 .. 2**halveNtime = pointsInUnit
63 ! | | | ... |
64 ! blocks of units are max number of points where the function is
65 ! evaluated.
66 !
67 ! 0 1 2 3 .. pointsInUnit (note 0 at the top)
68 ! | | | | ... | | ..... | | | | .. | | | | | | | ...|
69 ! 1 2.... pointsInUnit
70 !
71 !
72 ! 1 2 3 bloks units
73 !
74 ! for the first integration use points marked O as below (bloks points)
75 ! O O O O c
76 ! That is, if pointsInUnit = 32, in each block O is used
77 !
78 !
79 ! 0 1 2 16 32
80 ! | | | | | | | | | | | | | |... | | | | | | ... | | | | | |
81 ! O O
82 ! halving this
83 !
84 ! 0 1 2 16 32
85 ! | | | | | | | | | | | | | | | | | | | | ... | | | | | | | | | | |
86 ! O x O
87 ! halving this
88 !
89 !
90 ! 0 1 2 3 4 5 6 7 8 9 10 12 13 14 16 18 20 22 24 26 28 30 32
91 ! | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
92 ! O + x + O
93 ! halving this
94 !
95 ! 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 32
96 ! | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
97 ! O # + # x # + # O
98 !
99 ! halving this
100 ! 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 32
101 ! | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
102 ! O $ # $ + $ # $ x $ # $ + $ # $ O
103 !
104 ! halving this is the final step
105 !
106  parameter(halventime = 5, pointsinunit = 32)
107 ! must be 2**halveNtime
108  parameter( blocks = 10,
109  * totalpoints = blocks * pointsinunit + 1 )
110 !
111 ! mapping: y(0), y(1), y(32), y(33), ... corresponds to the
112 ! above nodal points. y(0) is very close to -1 and y(totalpoints)
113 ! is very close to 1. (actually, they are -1, and 1 due to
114 ! finite accuracy of double precision. so 1+y and 1-y is
115 ! tabulated specially.
116 !
117 
118  real*8 y(0:totalpoints), w(0:totalpoints)
119  real*8 opy(0:totalpoints),omy(0:totalpoints)
120  real*8 f(0:totalpoints)
121  real*8 machmin, machmax ! machine min, and max values
122  real*8 halfpi
123  real*8 tmax ! max |t| where transformation
124  ! y = tanh(pi/2 *sinh(t)) has no over/under flow.
125  ! |y| < 1
126  real*8 h ! minimum step of trapezoidal rule.
127  real*8 t, c1, ans1, ans2, step, f2, ytox, ytoxn, ytoxp
128  real*8 temp, xa(2), expm, expp
129  integer i, j, jstep, k
130 
131  logical first /.true./
132 
133  save first, y, w, halfpi, tmax, h, opy, omy, temp
134 
135  ytox(k) = c1*(y(k) + 1) + a
136  ytoxn(k) = -c1*opy(k) ! -c1(1+y)
137  ytoxp(k) = c1*omy(k) ! c1(1-y)
138 
139  if( first ) then
140 ! approx machine min, max
141  call kdmachmnmx(machmin, machmax)
142  halfpi = asin(1.d0) ! pi/2
143 
144 ! tmax = log(log(machmax/1.d5)/halfpi )
145 !
146 ! The next choice is rather from trial and error
147 ! log(log(1.d-75 ~ 1.d150).. ) is o.k
148 !
149  tmax = log(log(sqrt(machmin)/2)/(-2))
150 
151  h = 2*tmax/totalpoints ! width of (-tmax, tmax) is devided
152  ! by totalpoints
153 !
154 ! compute nodal points and weight there.
155 !
156  do i = 0, totalpoints
157  t = -tmax + i * h
158  temp = halfpi * sinh(t)
159  expm = exp(-temp)
160  expp = exp( temp)
161 
162  y(i) = tanh( temp )
163 
164  opy(i) = 2*expp/(expp + expm) ! 1+y
165  omy(i) = 2*expm/(expp + expm) ! 1-y
166 
167  w(i) = cosh(t) / cosh( halfpi*sinh(t) )**2
168 
169  enddo
170  first = .false.
171  endif
172 
173  if(a .eq. b) then
174  ans = 0.d0
175  icon = 0.
176  else
177  c1 = (b-a)/2.0d0
178  ans1 = 0.
179 
180  jstep = pointsinunit
181  do i = 1, halventime
182  step = jstep*h
183  ans2 = 0.
184  do j = 0, totalpoints, jstep
185  if( i.gt. 1 .and.
186  * mod( mod(j, pointsinunit), jstep*2) .eq. 0) then
187  f2 = f(j)
188  else
189  xa(1) = ytox(j)
190  if(y(j) .lt. 0. ) then
191  xa(2) = ytoxn(j)
192  else
193  xa(2) = ytoxp(j)
194  endif
195  f2 = func( xa ) * w(j)
196  f(j) = f2
197  endif
198  ans2 = ans2 + f2
199  enddo
200  ans2 = ans2 * step
201  if(i .gt. 1) then
202  if(abs(ans2) .gt. 1.d0) then
203  error =abs( abs(ans1/ans2)-1.d0 )
204  if(error .le. eps) then
205  icon = 0
206  goto 1000
207  endif
208  else
209  error = abs(ans2-ans1)
210  if(error .le. eps) then
211  icon = 0
212  goto 1000
213  endif
214  endif
215  endif
216  ans1 = ans2
217  jstep = jstep/2
218  enddo
219  icon = 1
220  1000 continue
221  ans = ans2 * halfpi *c1
222  endif
223  end
integer npitbl real *nx parameter(n=101, npitbl=46, nx=n-1) real *8 uconst
subroutine kdmachmnmx(xmin, xmax)
Definition: kdmachmnmx.f:8
block data cblkEvhnp ! currently usable models data RegMdls ad *special data *Cekaon d0
Definition: cblkEvhnp.h:5
subroutine kdexpintfb(func, a, b, eps, ans, error, icon)
Definition: kdexpIntFb.f:10
block data cblkElemag data *AnihiE ! Eposi< 1 TeV, anihilation considered *X0/365.667/, ! radiation length of air in kg/m2 *Ecrit/81.e-3/, ! critical energy of air in GeV *MaxComptonE/1./, ! compton is considered below 1 GeV *MaxPhotoE/1.e-3/, ! above this, PhotoElectric effect neg. *MinPhotoProdE/153.e-3/, ! below 153 MeV, no gp --> hadrons ! scattering const not MeV *Knockon ! knockon is considered Obsolete *PhotoProd false
Definition: cblkElemag.h:7