NLSL
ccrints.f90
Go to the documentation of this file.
1 c NLSL Version 1.5
2 c----------------------------------------------------------------------
3 c This file contains two copies of subroutine CCRINT named CCRIN1 and
4 c for use with double integration problems (e.g. integration over
5 c the polar angles in rigid limit EPR calculation programs)
6 c----------------------------------------------------------------------
7 c
8 c ======================
9 c subroutine CCRINT
10 c ======================
11 c
12 c Clenshaw-Curtis-Romberg integration method according to algorithm
13 c of O'Hara and Smith [Computer J. 12 (1969) 179-82]
14 c Adapted from G. Bruno thesis, Cornell Univ. (see p. 554 Bruno thesis)
15 c Code rearranged clarified, and re-commented by D. Budil, 1/16/90
16 c
17 c The function to be integrated is supplied as a double precision function
18 c whose name is passed to the program (external function f)
19 c
20 c Parameters:
21 c bndlow Lower bound of integration
22 c bndhi Upper bound of integration
23 c epsiln Tolerance (absolute) for convergence of integral
24 c Relative tolerance ratio is taken to be epsiln/100
25 c small Smallest permissible step, as fraction of (x range)/4
26 c
27 c Returns:
28 c neval Number of function evaluations
29 c id Error flag (1 for normal, -1 for stack overflow)
30 c----------------------------------------------------------------------
31  subroutine ccrint(bndlow,bndhi,epsiln,small,sum,neval,f,id)
32  external f
33 
34  integer id, neval, nstack
35  double precision b1(30), b2(30), b3(30), b4(30), p(30)
36  double precision bndlow, bndhi, acl7, ainsc, ccerr,
37  # cnc1, cnc2, cnc3, cnc4, c7l1, c7l2, c7l3, c7l4,
38  # c8r1, c8r2, c8r3, c8r4,
39  # cvgtol, err, diff, h, hmin, rombrg, rt3,
40  # sa, sc, sd, small, sum,
41  # t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, epsiln,
42  # x0, x1, x2, x3, x4, x5, x6, x7, x8, xx
43  double precision dabs, f
44 
45 c ======================================================================
46 c Coefficients for 2*(5 point Newton-Cotes) integration
47 c 14/45, 28/45, 24/45, 64/45
48 c ======================================================================
49 
50  data cnc1 /0.3111111111111111d0 /
51  # cnc2 /0.6222222222222222d0 /
52  # cnc3 /0.5333333333333333d0 /
53  # cnc4 /1.4222222222222222d0 /
54 
55 c ======================================================================
56 c Coefficients for 8 point Romberg formula
57 c 868/2835, 1744/2835, 1408/2835, 4096/2835
58 c ======================================================================
59 
60  data c8r1 /0.3061728395061728d0 /
61  # c8r2 /0.6151675485008818d0 /
62  # c8r3 /0.4966490299823633d0 /
63  # c8r4 /1.444797178130511d0 /
64 
65 c ======================================================================
66 c Coefficients for 7 point Clenshaw-Curtis formula
67 c 36/315, 656/315, 576/315, 320/315
68 c ======================================================================
69 
70  data c7l1 /0.1142857142857143d0 /
71  # c7l2 /2.082539682539683d0 /
72  # c7l3 /1.828571428571429d0 /
73  # c7l4 /1.015873015873016d0 /
74 
75  data rt3 /1.732050807568877d0 /
76 
77 c ======================================================================
78 c Set initial domain to be the entire domain from lower to upper bound
79 c ======================================================================
80 
81  id = 1
82  h = (bndhi-bndlow)*0.25d0
83  x0 = bndlow
84  x2 = x0+h
85  x4 = x2+h
86  x6 = x4+h
87  x8 = bndhi
88 
89  t0 = f(x0)
90  t2 = f(x2)
91  t4 = f(x4)
92  t6 = f(x6)
93  t8 = f(x8)
94  neval = 5
95 
96  err = epsiln
97  sum = 0.0d0
98  nstack = 0
99  hmin = small*h
100 
101 c ======================================================================
102 c Beginning of an iteration: divide step size in half.
103 c (assumed that current domain is only a small fraction of the total)
104 c Supplied with a (sub)domain defined by the x values x0,x2,x4,x6,x8,
105 c interpolate the points x1, x3, x5, x7 and calculate f at these points
106 c ======================================================================
107 
108 4 h = 0.5d0*h
109  if (dabs(h) .le. dabs(hmin)) go to 9
110 
111  x1 = x0+h
112  x3 = x2+h
113  x5 = x4+h
114  x7 = x6+h
115  t1 = f(x1)
116  t3 = f(x3)
117  t5 = f(x5)
118  t7 = f(x7)
119  neval=neval+4
120 
121  cvgtol = err*0.1d0
122  if (nstack.eq.0) cvgtol = err
123 
124 c ======================================================================
125 c First convergence test:
126 c Compare results of Newton-Cotes and Romberg quadratures.
127 c If absolute AND relative differences are too large, the current domain
128 c must be subdivided
129 c
130 c *** Modified 22-May-90: proceed if the integrated function is zero -DEB
131 c ======================================================================
132 
133  sa=t0+t8
134  sc=t2+t6
135  sd=t1+t3+t5+t7
136 
137  rombrg = (c8r1*sa + c8r2*t4 +c8r3*sc + c8r4*sd)*h
138  ainsc = (cnc1*sa + cnc2*t4 +cnc3*sc + cnc4*sd)*h
139  diff = dabs(rombrg-ainsc)
140 
141  if ( rombrg .ne. 0.0d0 .and. ainsc .ne. 0.0d0) then
142  if ( diff .gt. cvgtol
143  # .and. diff/dabs( 0.5d0*(rombrg+ainsc) ) .gt. cvgtol*1.0d-2 )
144  # go to 10
145  endif
146 
147 c ======================================================================
148 c Second convergence test:
149 c Compare 8 pt. Romberg with 7 pt. Clenshaw-Curtis quadratures.
150 c (Use error estimate for Clenshaw-Curtis quadrature if it is larger)
151 c If absolute AND relative differences are too large, the current domain
152 c needs to be subdivided
153 c
154 c *** Modified 22-May-90: proceed if the integrated function is zero -DEB
155 c ======================================================================
156 
157  xx = rt3*h
158  t9 = f(x2-xx) + f(x2+xx)
159  t10 = f(x6-xx) + f(x6+xx)
160  neval=neval+4
161  acl7 = 0.5d0*h*( c7l1*(sa+2.d0*t4) + c7l2*sc + c7l3*sd
162  # + c7l4*(t9+t10) )
163  diff = dabs( acl7-rombrg )
164  ccerr = ( dabs(0.5d0*(t0+t4)+t1+t3-t2-t9 )
165  # + dabs(0.5d0*(t4+t8)+t5+t7-t6-t10) )*h*64.d0/945.d0
166  if ( ccerr .gt. diff ) diff = ccerr
167 
168  if ( rombrg .ne. 0.0d0 .and. acl7 .ne. 0.0d0) then
169  if ( diff .gt. cvgtol
170  # .and.diff/dabs(0.5d0*(acl7+rombrg)) .gt. cvgtol/1.0d2) goto 10
171  endif
172 
173 c ======================================================================
174 c Convergence achieved for this subdomain: add integral into result
175 c Replace current subdomain with the top subdomain on the stack for next
176 c iteration (Integration is complete if the stack is empty)
177 c ======================================================================
178 
179  sum = sum + acl7
180 
181  if (diff .lt. cvgtol) err = err + diff
182 
183 9 continue
184 
185  if (nstack.le.0) return
186 
187  h = p(nstack)
188  t0 = t8
189  t2 = b1(nstack)
190  t4 = b2(nstack)
191  t6 = b3(nstack)
192  t8 = b4(nstack)
193  x0 = x8
194  x2 = x0+h
195  x4 = x2+h
196  x6 = x4+h
197  x8 = x6+h
198  nstack = nstack-1
199  go to 4
200 
201 c ======================================================================
202 c Push upper half of current subdomain (points x5, x6, x7, x8)
203 c and function values onto the stack (error return if stack overflows)
204 c Replace current subdomain (points x0, x2, x4, x6, x8) and function values
205 c with its lower half (points x0, x1, x2, x3, x4) for next iteration
206 c ======================================================================
207 
208  10 nstack=nstack+1
209  if(nstack.gt.30) then
210  id=-1
211  write(*,*)'CCRINT: more than 30 subdomain divisions'
212  return
213  endif
214 
215  b1(nstack) = t5
216  b2(nstack) = t6
217  b3(nstack) = t7
218  b4(nstack) = t8
219  p(nstack) = h
220 
221  t8 = t4
222  t6 = t3
223  t4 = t2
224  t2 = t1
225  x8 = x4
226  x6 = x3
227  x4 = x2
228  x2 = x1
229  go to 4
230  end
231 
232 c ======================================================================
233 c =========================
234 c Subroutine CCRIN1
235 c =========================
236 c Duplicate of subroutine ccrint used for two-dimensional integration.
237 c ======================================================================
238 
239  subroutine ccrin1(bndlow,bndhi,epsiln,small,sum,neval,f,id)
240  external f
241 
242  integer id, neval, nstack
243  double precision b1(30), b2(30), b3(30), b4(30), p(30)
244  double precision bndlow, bndhi, acl7, ainsc, ccerr,
245  # cnc1, cnc2, cnc3, cnc4, c7l1, c7l2, c7l3, c7l4,
246  # c8r1, c8r2, c8r3, c8r4,
247  # cvgtol, err, diff, h, hmin, rombrg, rt3,
248  # sa, sc, sd, small, sum,
249  # t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, epsiln,
250  # x0, x1, x2, x3, x4, x5, x6, x7, x8, xx
251  double precision dabs, f
252 
253 c ======================================================================
254 c Coefficients for 2*(5 point Newton-Cotes) integration
255 c 14/45, 28/45, 24/45, 64/45
256 c ======================================================================
257 
258  data cnc1 /0.3111111111111111d0 /
259  # cnc2 /0.6222222222222222d0 /
260  # cnc3 /0.5333333333333333d0 /
261  # cnc4 /1.4222222222222222d0 /
262 
263 c ======================================================================
264 c Coefficients for 8 point Romberg formula
265 c 868/2835, 1744/2835, 1408/2835, 4096/2835
266 c ======================================================================
267 
268  data c8r1 /0.3061728395061728d0 /
269  # c8r2 /0.6151675485008818d0 /
270  # c8r3 /0.4966490299823633d0 /
271  # c8r4 /1.444797178130511d0 /
272 
273 c ======================================================================
274 c Coefficients for 7 point Clenshaw-Curtis formula
275 c 36/315, 656/315, 576/315, 320/315
276 c ======================================================================
277 
278  data c7l1 /0.1142857142857143d0 /
279  # c7l2 /2.082539682539683d0 /
280  # c7l3 /1.828571428571429d0 /
281  # c7l4 /1.015873015873016d0 /
282 
283  data rt3 /1.732050807568877d0 /
284 
285 c ======================================================================
286 c Set initial domain to be the entire domain from lower to upper bound
287 c ======================================================================
288 
289  id = 1
290  h = (bndhi-bndlow)*0.25d0
291  x0 = bndlow
292  x2 = x0+h
293  x4 = x2+h
294  x6 = x4+h
295  x8 = bndhi
296 
297  t0 = f(x0)
298  t2 = f(x2)
299  t4 = f(x4)
300  t6 = f(x6)
301  t8 = f(x8)
302  neval = 5
303 
304  err = epsiln
305  sum = 0.0d0
306  nstack = 0
307  hmin = small*h
308 
309 c ======================================================================
310 c Beginning of an iteration: divide step size in half.
311 c Skip integration formulae if the step size h is too small.
312 c (assumed that current domain is only a small fraction of the total)
313 c Supplied with a (sub)domain defined by the x values x0,x2,x4,x6,x8,
314 c interpolate the points x1, x3, x5, x7 and calculate f at these points
315 c ======================================================================
316 
317 4 h = 0.5d0*h
318  if (dabs(h) .le. dabs(hmin)) go to 9
319 
320  x1 = x0+h
321  x3 = x2+h
322  x5 = x4+h
323  x7 = x6+h
324  t1 = f(x1)
325  t3 = f(x3)
326  t5 = f(x5)
327  t7 = f(x7)
328  neval=neval+4
329 
330  cvgtol = err*0.1d0
331  if (nstack.eq.0) cvgtol = err
332 
333 c ======================================================================
334 c First convergence test:
335 c Compare results of Newton-Cotes and Romberg quadratures.
336 c If absolute AND relative differences are too large, the current domain
337 c must be subdivided
338 c
339 c *** Modified 22-May-90: proceed if the integrated function is zero -DEB
340 c ======================================================================
341 
342  sa=t0+t8
343  sc=t2+t6
344  sd=t1+t3+t5+t7
345 
346  rombrg = (c8r1*sa + c8r2*t4 +c8r3*sc + c8r4*sd)*h
347  ainsc = (cnc1*sa + cnc2*t4 +cnc3*sc + cnc4*sd)*h
348  diff = dabs(rombrg-ainsc)
349 
350  if ( rombrg .ne. 0.0d0 .and. ainsc .ne. 0.0d0) then
351  if ( diff .gt. cvgtol
352  # .and. diff/dabs( 0.5d0*(rombrg+ainsc) ) .gt. cvgtol*1.0d-2 )
353  # go to 10
354  endif
355 
356 c ======================================================================
357 c Second convergence test:
358 c Compare 8 pt. Romberg with 7 pt. Clenshaw-Curtis quadratures.
359 c (Use error estimate for Clenshaw-Curtis quadrature if it is larger)
360 c If absolute AND relative differences are too large, the current domain
361 c needs to be subdivided
362 c
363 c *** Modified 22-May-90: proceed if the integrated function is zero -DEB
364 c ======================================================================
365 
366  xx = rt3*h
367  t9 = f(x2-xx) + f(x2+xx)
368  t10 = f(x6-xx) + f(x6+xx)
369  neval=neval+4
370  acl7 = 0.5d0*h*( c7l1*(sa+2.d0*t4) + c7l2*sc + c7l3*sd
371  # + c7l4*(t9+t10) )
372  diff = dabs( acl7-rombrg )
373  ccerr = ( dabs(0.5d0*(t0+t4)+t1+t3-t2-t9 )
374  # + dabs(0.5d0*(t4+t8)+t5+t7-t6-t10) )*h*64.d0/945.d0
375  if ( ccerr .gt. diff ) diff = ccerr
376 
377  if ( rombrg .ne. 0.0d0 .and. acl7 .ne. 0.0d0) then
378  if ( diff .gt. cvgtol
379  # .and.diff/dabs(0.5d0*(acl7+rombrg)) .gt. cvgtol/1.0d2) goto 10
380  endif
381 
382 c ======================================================================
383 c Convergence achieved for this subdomain: add integral into result
384 c Replace current subdomain with the top subdomain on the stack for next
385 c iteration (Integration is complete if the stack is empty)
386 c ======================================================================
387 
388  sum = sum + acl7
389 
390  if (diff .lt. cvgtol) err = err + diff
391 
392 9 continue
393 
394  if (nstack.le.0) return
395 
396  h = p(nstack)
397  t0 = t8
398  t2 = b1(nstack)
399  t4 = b2(nstack)
400  t6 = b3(nstack)
401  t8 = b4(nstack)
402  x0 = x8
403  x2 = x0+h
404  x4 = x2+h
405  x6 = x4+h
406  x8 = x6+h
407  nstack = nstack-1
408  go to 4
409 
410 c ======================================================================
411 c Push upper half of current subdomain (points x5, x6, x7, x8)
412 c and function values onto the stack (error return if stack overflows)
413 c Replace current subdomain (points x0, x2, x4, x6, x8) and function values
414 c with its lower half (points x0, x1, x2, x3, x4) for next iteration
415 c ======================================================================
416 
417  10 nstack=nstack+1
418  if(nstack.gt.30) then
419  id=-1
420  write(*,*)'CCRIN1: more than 30 subdomain divisions'
421  return
422  endif
423 
424  b1(nstack) = t5
425  b2(nstack) = t6
426  b3(nstack) = t7
427  b4(nstack) = t8
428  p(nstack) = h
429 
430  t8 = t4
431  t6 = t3
432  t4 = t2
433  t2 = t1
434  x8 = x4
435  x6 = x3
436  x4 = x2
437  x2 = x1
438  go to 4
439  end
subroutine ccrin1(bndlow, bndhi, epsiln, small, sum, neval, f, id)
Definition: ccrints.f90:240
subroutine ccrint(bndlow, bndhi, epsiln, small, sum, neval, f, id)
Definition: ccrints.f90:32