source: ZHANGProjects/ICOSIM/CPP/trunk/source/crystalprotonfuns.f @ 17

Last change on this file since 17 was 17, checked in by zhangj, 10 years ago

Added comments...

File size: 27.6 KB
Line 
1CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
2C  Math functions used in crystal_dan_FINAL_VERSION_CHvsCV.f
3C      From track_dan_new.f
4C
5C
6C
7C
8CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
9
10
11
12      double precision function RAN_GAUSS(cut)
13!*********************************************************************
14!
15! RAN_GAUSS - will generate a normal distribution from a uniform
16!   distribution between [0,1].
17!   See "Communications of the ACM", V. 15 (1972), p. 873.
18!
19! cut - double precision - cut for distribution in units of sigma
20!                the cut must be greater than 0.5
21!
22!*********************************************************************
23      implicit none
24 
25      logical flag
26      real rndm4
27      double precision x, u1, u2, twopi, r,cut
28      save
29 
30c      write(*,*) "In RAN_GAUSS: "
31c      write(*,*) "flag = ",flag
32c      write(*,*) "U1 = ", U1,"U2 = ", U2
33            twopi=8d0*atan(1d0)
34    1       if (flag) then
35              r = dble(rndm4( ))
36              r = max(r, 0.5d0**32)
37              r = min(r, 1d0-0.5d0**32)
38              u1 = sqrt(-2d0*log( r ))
39              u2 = dble(rndm4( ))
40              x = u1 * cos(twopi*u2)
41            else
42              x = u1 * sin(twopi*u2)
43            endif
44 
45c            write(*,*) "flag = ",flag
46c            write(*,*) "U1 = ", U1,"U2 = ", U2, "x = ", x
47
48          flag = .not. flag
49 
50!  cut the distribution if cut > 0.5
51          if (cut .gt. 0.5d0 .and. abs(x) .gt. cut) goto 1
52 
53          RAN_GAUSS = x
54
55c          write(*,*) "ran_gauss = ", RAN_GAUSS
56
57        return
58      end
59
60!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
61!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
62      function rndm4()
63      implicit none
64      integer len, in
65      real rndm4, a
66      save
67      parameter ( len =  30000 )
68      dimension a(len)
69      data in/1/
70!
71      if ( in.eq.1 ) then
72         call ranlux(a,len)
73         rndm4=a(1)
74         in=2
75!        write(6,'('' LEN: '',i5)')LEN
76      else
77         rndm4=a(in)
78         in=in+1
79         if(in.eq.len+1)in=1
80      endif
81      return
82      end
83
84
85
86      subroutine ranlux(rvec,lenv)
87!         Subtract-and-borrow random number generator proposed by
88!         Marsaglia and Zaman, implemented by F. James with the name
89!         RCARRY in 1991, and later improved by Martin Luescher
90!         in 1993 to produce "Luxury Pseudorandom Numbers".
91!     Fortran 77 coded by F. James, 1993
92!
93!   LUXURY LEVELS.
94!   ------ ------      The available luxury levels are:
95!
96!  level 0  (p=24): equivalent to the original RCARRY of Marsaglia
97!           and Zaman, very long period, but fails many tests.
98!  level 1  (p=48): considerable improvement in quality over level 0,
99!           now passes the gap test, but still fails spectral test.
100!  level 2  (p=97): passes all known tests, but theoretically still
101!           defective.
102!  level 3  (p=223): DEFAULT VALUE.  Any theoretically possible
103!           correlations have very small chance of being observed.
104!  level 4  (p=389): highest possible luxury, all 24 bits chaotic.
105!
106!!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
107!!!  Calling sequences for RANLUX:                                  ++
108!!!      CALL RANLUX (RVEC, LEN)   returns a vector RVEC of LEN     ++
109!!!                   32-bit random floating point numbers between  ++
110!!!                   zero (not included) and one (also not incl.). ++
111!!!      CALL RLUXGO(LUX,INT,K1,K2) initializes the generator from  ++
112!!!               one 32-bit integer INT and sets Luxury Level LUX  ++
113!!!               which is integer between zero and MAXLEV, or if   ++
114!!!               LUX .GT. 24, it sets p=LUX directly.  K1 and K2   ++
115!!!               should be set to zero unless restarting at a break++
116!!!               point given by output of RLUXAT (see RLUXAT).     ++
117!!!      CALL RLUXAT(LUX,INT,K1,K2) gets the values of four integers++
118!!!               which can be used to restart the RANLUX generator ++
119!!!               at the current point by calling RLUXGO.  K1 and K2++
120!!!               specify how many numbers were generated since the ++
121!!!               initialization with LUX and INT.  The restarting  ++
122!!!               skips over  K1+K2*E9   numbers, so it can be long.++
123!!!   A more efficient but less convenient way of restarting is by: ++
124!!!      CALL RLUXIN(ISVEC)    restarts the generator from vector   ++
125!!!                   ISVEC of 25 32-bit integers (see RLUXUT)      ++
126!!!      CALL RLUXUT(ISVEC)    outputs the current values of the 25 ++
127!!!                 32-bit integer seeds, to be used for restarting ++
128!!!      ISVEC must be dimensioned 25 in the calling program        ++
129!!! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
130      implicit none
131      integer lenv,isdext,iseeds,maxlev,ndskip,itwo24,next,j24,i24,     &
132     &inseed,mkount,kount,in24,nskip,lxdflt,jsdflt,jseed,lp,i,k,icons,  &
133     &inner,izip,izip2,ivec,isk,igiga,isd,k2,k1,inout,lout,ins,lux,ilx, &
134     &iouter
135      real rvec,seeds,twop12,twom12,twom24,carry,uni
136      dimension rvec(lenv)
137      dimension seeds(24), iseeds(24), isdext(25)
138      parameter (maxlev=4, lxdflt=3)
139      dimension ndskip(0:maxlev)
140      dimension next(24)
141      parameter (twop12=4096., igiga=1000000000,jsdflt=314159265)
142      parameter (itwo24=2**24, icons=2147483563)
143      save notyet, i24, j24, carry, seeds, twom24, twom12, luxlev
144      save nskip, ndskip, in24, next, kount, mkount, inseed
145      integer luxlev
146      logical notyet
147      data notyet, luxlev, in24, kount, mkount /.true., lxdflt, 0,0,0/
148      data i24,j24,carry/24,10,0./
149!                               default
150!  Luxury Level   0     1     2   *3*    4
151      data ndskip/0,   24,   73,  199,  365 /
152!Corresponds to p=24    48    97   223   389
153!     time factor 1     2     3     6    10   on slow workstation
154!                 1    1.5    2     3     5   on fast mainframe
155!
156!  NOTYET is .TRUE. if no initialization has been performed yet.
157!              Default Initialization by Multiplicative Congruential
158      if (notyet) then
159         notyet = .false.
160         jseed = jsdflt
161         inseed = jseed
162         write(*,'(A,I12)') ' RANLUX DEFAULT INITIALIZATION: ',jseed
163         luxlev = lxdflt
164         nskip = ndskip(luxlev)
165         lp = nskip + 24
166         in24 = 0
167         kount = 0
168         mkount = 0
169!         WRITE(6,'(A,I2,A,I4)')  ' RANLUX DEFAULT LUXURY LEVEL =  ',
170!     &        LUXLEV,'      p =',LP
171            twom24 = 1.
172         do 25 i= 1, 24
173            twom24 = twom24 * 0.5
174         k = jseed/53668
175         jseed = 40014*(jseed-k*53668) -k*12211
176         if (jseed .lt. 0)  jseed = jseed+icons
177         iseeds(i) = mod(jseed,itwo24)
178   25    continue
179         twom12 = twom24 * 4096.
180         do 50 i= 1,24
181         seeds(i) = real(iseeds(i))*twom24
182         next(i) = i-1
183   50    continue
184         next(1) = 24
185         i24 = 24
186         j24 = 10
187         carry = 0.
188         if (seeds(24) .eq. 0.) carry = twom24
189      endif
190!
191!          The Generator proper: "Subtract-with-borrow",
192!          as proposed by Marsaglia and Zaman,
193!          Florida State University, March, 1989
194!
195      do 100 ivec= 1, lenv
196      uni = seeds(j24) - seeds(i24) - carry
197      if (uni .lt. 0.)  then
198         uni = uni + 1.
199         carry = twom24
200      else
201         carry = 0.
202      endif
203      seeds(i24) = uni
204      i24 = next(i24)
205      j24 = next(j24)
206      rvec(ivec) = uni
207!  small numbers (with less than 12 "significant" bits) are "padded".
208      if (uni .lt. twom12)  then
209         rvec(ivec) = rvec(ivec) + twom24*seeds(j24)
210!        and zero is forbidden in case someone takes a logarithm
211         if (rvec(ivec) .eq. 0.)  rvec(ivec) = twom24*twom24
212      endif
213!        Skipping to luxury.  As proposed by Martin Luscher.
214      in24 = in24 + 1
215      if (in24 .eq. 24)  then
216         in24 = 0
217         kount = kount + nskip
218         do 90 isk= 1, nskip
219         uni = seeds(j24) - seeds(i24) - carry
220         if (uni .lt. 0.)  then
221            uni = uni + 1.
222            carry = twom24
223         else
224            carry = 0.
225         endif
226         seeds(i24) = uni
227         i24 = next(i24)
228         j24 = next(j24)
229   90    continue
230      endif
231  100 continue
232      kount = kount + lenv
233      if (kount .ge. igiga)  then
234         mkount = mkount + 1
235         kount = kount - igiga
236      endif
237      return
238!
239!           Entry to input and float integer seeds from previous run
240      entry rluxin(isdext)
241         notyet = .false.
242         twom24 = 1.
243         do 195 i= 1, 24
244         next(i) = i-1
245  195    twom24 = twom24 * 0.5
246         next(1) = 24
247         twom12 = twom24 * 4096.
248      write(*,*) ' FULL INITIALIZATION OF RANLUX WITH 25 INTEGERS:'
249      write(*,'(5X,5I12)') isdext
250      do 200 i= 1, 24
251      seeds(i) = real(isdext(i))*twom24
252  200 continue
253      carry = 0.
254      if (isdext(25) .lt. 0)  carry = twom24
255      isd = iabs(isdext(25))
256      i24 = mod(isd,100)
257      isd = isd/100
258      j24 = mod(isd,100)
259      isd = isd/100
260      in24 = mod(isd,100)
261      isd = isd/100
262      luxlev = isd
263        if (luxlev .le. maxlev) then
264          nskip = ndskip(luxlev)
265          write(*,'(A,I2)') ' RANLUX LUXURY LEVEL SET BY RLUXIN TO: ',  &
266     &luxlev
267        else  if (luxlev .ge. 24) then
268          nskip = luxlev - 24
269          write(*,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXIN TO:',luxlev
270        else
271          nskip = ndskip(maxlev)
272          write(*,'(A,I5)') ' RANLUX ILLEGAL LUXURY RLUXIN: ',luxlev
273          luxlev = maxlev
274        endif
275      inseed = -1
276      return
277!
278!                    Entry to ouput seeds as integers
279      entry rluxut(isdext)
280      do 300 i= 1, 24
281         isdext(i) = int(seeds(i)*twop12*twop12)
282  300 continue
283      isdext(25) = i24 + 100*j24 + 10000*in24 + 1000000*luxlev
284      if (carry .gt. 0.)  isdext(25) = -isdext(25)
285      return
286!
287!                    Entry to output the "convenient" restart point
288      entry rluxat(lout,inout,k1,k2)
289      lout = luxlev
290      inout = inseed
291      k1 = kount
292      k2 = mkount
293      return
294!
295!                    Entry to initialize from one or three integers
296      entry rluxgo(lux,ins,k1,k2)
297         if (lux .lt. 0) then
298            luxlev = lxdflt
299         else if (lux .le. maxlev) then
300            luxlev = lux
301         else if (lux .lt. 24 .or. lux .gt. 2000) then
302            luxlev = maxlev
303            write(*,'(A,I7)') ' RANLUX ILLEGAL LUXURY RLUXGO: ',lux
304         else
305            luxlev = lux
306            do 310 ilx= 0, maxlev
307              if (lux .eq. ndskip(ilx)+24)  luxlev = ilx
308  310       continue
309         endif
310      if (luxlev .le. maxlev)  then
311         nskip = ndskip(luxlev)
312         write(*,'(A,I2,A,I4)') ' RANLUX LUXURY LEVEL SET BY RLUXGO :', &
313     &luxlev,'     P=', nskip+24
314      else
315          nskip = luxlev - 24
316          write(*,'(A,I5)') ' RANLUX P-VALUE SET BY RLUXGO TO:',luxlev
317      endif
318      in24 = 0
319      if (ins .lt. 0)  write(*,*)                                       &
320     &' Illegal initialization by RLUXGO, negative input seed'
321      if (ins .gt. 0)  then
322        jseed = ins
323        write(*,'(A,3I12)') ' RANLUX INITIALIZED BY RLUXGO FROM SEEDS', &
324     &jseed, k1,k2
325      else
326        jseed = jsdflt
327        write(*,*)' RANLUX INITIALIZED BY RLUXGO FROM DEFAULT SEED'
328      endif
329      inseed = jseed
330      notyet = .false.
331      twom24 = 1.
332         do 325 i= 1, 24
333           twom24 = twom24 * 0.5
334         k = jseed/53668
335         jseed = 40014*(jseed-k*53668) -k*12211
336         if (jseed .lt. 0)  jseed = jseed+icons
337         iseeds(i) = mod(jseed,itwo24)
338  325    continue
339      twom12 = twom24 * 4096.
340         do 350 i= 1,24
341         seeds(i) = real(iseeds(i))*twom24
342         next(i) = i-1
343  350    continue
344      next(1) = 24
345      i24 = 24
346      j24 = 10
347      carry = 0.
348      if (seeds(24) .eq. 0.) carry = twom24
349!        If restarting at a break point, skip K1 + IGIGA*K2
350!        Note that this is the number of numbers delivered to
351!        the user PLUS the number skipped (if luxury .GT. 0).
352      kount = k1
353      mkount = k2
354      if (k1+k2 .ne. 0)  then
355        do 500 iouter= 1, k2+1
356          inner = igiga
357          if (iouter .eq. k2+1)  inner = k1
358          do 450 isk= 1, inner
359            uni = seeds(j24) - seeds(i24) - carry
360            if (uni .lt. 0.)  then
361               uni = uni + 1.
362               carry = twom24
363            else
364               carry = 0.
365            endif
366            seeds(i24) = uni
367            i24 = next(i24)
368            j24 = next(j24)
369  450     continue
370  500   continue
371!         Get the right value of IN24 by direct calculation
372        in24 = mod(kount, nskip+24)
373        if (mkount .gt. 0)  then
374           izip = mod(igiga, nskip+24)
375           izip2 = mkount*izip + in24
376           in24 = mod(izip2, nskip+24)
377        endif
378!       Now IN24 had better be between zero and 23 inclusive
379        if (in24 .gt. 23) then
380           write(*,'(A/A,3I11,A,I5)')                                   &
381     &'  Error in RESTARTING with RLUXGO:','  The values', ins,         &
382     &k1, k2, ' cannot occur at luxury level', luxlev
383           in24 = 0
384        endif
385      endif
386      return
387      end
388 
389!cccccccccccccccccccccccccccccccccccccccccccccccccc
390      subroutine funlxp (func,xfcum,x2low,x2high)
391!         F. JAMES,   Sept, 1994
392!
393!         Prepares the user function FUNC for FUNLUX
394!         Inspired by and mostly copied from FUNPRE and FUNRAN
395!         except that
396!    1. FUNLUX uses RANLUX underneath,
397!    2. FUNLXP expands the first and last bins to cater for
398!              functions with long tails on left and/or right,
399!    3. FUNLXP calls FUNPCT to do the actual finding of percentiles.
400!    4. both FUNLXP and FUNPCT use RADAPT for Gaussian integration.
401!
402      implicit none
403      external func
404      integer ifunc,ierr
405      real x2high,x2low,xfcum,rteps,xhigh,xlow,xrange,uncert,x2,tftot1, &
406     &x3,tftot2,func
407      real tftot
408      common/funint/tftot
409      dimension xfcum(200)
410      parameter (rteps=0.0002)
411      save ifunc
412      data ifunc/0/
413      ifunc = ifunc + 1
414!         FIND RANGE WHERE FUNCTION IS NON-ZERO.
415      call funlz(func,x2low,x2high,xlow,xhigh)
416      xrange = xhigh-xlow
417      if(xrange .le. 0.)  then
418        write(*,'(A,2G15.5)') ' FUNLXP finds function range .LE.0',     &
419     &xlow,xhigh
420        go to 900
421      endif
422      call radapt(func,xlow,xhigh,1,rteps,0.,tftot ,uncert)
423!      WRITE(6,1003) IFUNC,XLOW,XHIGH,TFTOT
424 1003 format(' FUNLXP: integral of USER FUNCTION',                      &
425     &i3,' from ',e12.5,' to ',e12.5,' is ',e14.6)
426!
427!      WRITE (6,'(A,A)') ' FUNLXP preparing ',
428!     + 'first the whole range, then left tail, then right tail.'
429      call funpct(func,ifunc,xlow,xhigh,xfcum,1,99,tftot,ierr)
430      if (ierr .gt. 0)  go to 900
431      x2 = xfcum(3)
432      call radapt(func,xlow,x2,1,rteps,0.,tftot1 ,uncert)
433      call funpct(func,ifunc,xlow,x2 ,xfcum,101,49,tftot1,ierr)
434      if (ierr .gt. 0)  go to 900
435      x3 = xfcum(98)
436      call radapt(func,x3,xhigh,1,rteps,0.,tftot2 ,uncert)
437      call funpct(func,ifunc,x3,xhigh,xfcum,151,49,tftot2,ierr)
438      if (ierr .gt. 0)  go to 900
439!      WRITE(6,1001) IFUNC,XLOW,XHIGH
440 1001 format(' FUNLXP has prepared USER FUNCTION',i3,                   &
441     &' between',g12.3,' and',g12.3,' for FUNLUX')
442      return
443  900 continue
444      write(*,*) ' Fatal error in FUNLXP. FUNLUX will not work.'
445      end
446!
447
448
449      subroutine funlux(array,xran,len)
450!         Generation of LEN random numbers in any given distribution,
451!         by 4-point interpolation in the inverse cumulative distr.
452!         which was previously generated by FUNLXP
453      implicit none
454      real tftot
455      common/funint/tftot
456      integer len,ibuf,j,j1
457      real array,xran,gap,gapinv,tleft,bright,gaps,gapins,x,p,a,b
458      dimension array(200)
459      dimension xran(len)
460!  Bin width for main sequence, and its inverse
461      parameter (gap= 1./99.,  gapinv=99.)
462!  Top of left tail, bottom of right tail (each tail replaces 2 bins)
463      parameter (tleft= 2./99.,bright=97./99.)
464!  Bin width for minor sequences (tails), and its inverse
465      parameter (gaps=tleft/49.,  gapins=1./gaps)
466!
467!   The array ARRAY is assumed to have the following structure:
468!        ARRAY(1-100) contains the 99 bins of the inverse cumulative
469!                     distribution of the entire function.
470!        ARRAY(101-150) contains the 49-bin blowup of main bins
471!                       1 and 2 (left tail of distribution)
472!        ARRAY(151-200) contains the 49-bin blowup of main bins
473!                       98 and 99 (right tail of distribution)
474!
475      call ranlux(xran,len)
476 
477      do 500 ibuf= 1, len
478      x = xran(ibuf)
479      j = int(  x    *gapinv) + 1
480      if (j .lt. 3)  then
481         j1 = int( x *gapins)
482             j = j1 + 101
483             j = max(j,102)
484             j = min(j,148)
485         p = (   x -gaps*(j1-1)) * gapins
486         a = (p+1.0) * array(j+2) - (p-2.0)*array(j-1)
487         b = (p-1.0) * array(j) - p * array(j+1)
488         xran(ibuf) = a*p*(p-1.0)*0.16666667 + b*(p+1.)*(p-2.)*0.5
489      else if (j .gt. 97)  then
490         j1 = int((x-bright)*gapins)
491             j = j1 + 151
492             j = max(j,152)
493             j = min(j,198)
494         p = (x -bright -gaps*(j1-1)) * gapins
495         a = (p+1.0) * array(j+2) - (p-2.0)*array(j-1)
496         b = (p-1.0) * array(j) - p * array(j+1)
497         xran(ibuf) = a*p*(p-1.0)*0.16666667 + b*(p+1.)*(p-2.)*0.5
498      else
499!      J = MAX(J,2)
500!      J = MIN(J,98)
501         p = (   x -gap*(j-1)) * gapinv
502         a = (p+1.) * array(j+2) - (p-2.)*array(j-1)
503         b = (p-1.) * array(j) - p * array(j+1)
504         xran(ibuf) = a*p*(p-1.)*0.16666667 + b*(p+1.)*(p-2.)*0.5
505      endif
506  500 continue
507      tftot = x
508      return
509      end
510
511
512CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
513C
514CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
515      subroutine funlz(func,x2low,x2high,xlow,xhigh)
516!         FIND RANGE WHERE FUNC IS NON-ZERO.
517!         WRITTEN 1980, F. JAMES
518!         MODIFIED, NOV. 1985, TO FIX BUG AND GENERALIZE
519!         TO FIND SIMPLY-CONNECTED NON-ZERO REGION (XLOW,XHIGH)
520!         ANYWHERE WITHIN THE GIVEN REGION (X2LOW,H2HIGH).
521!            WHERE 'ANYWHERE' MEANS EITHER AT THE LOWER OR UPPER
522!            EDGE OF THE GIVEN REGION, OR, IF IN THE MIDDLE,
523!            COVERING AT LEAST 1% OF THE GIVEN REGION.
524!         OTHERWISE IT IS NOT GUARANTEED TO FIND THE NON-ZERO REGION.
525!         IF FUNCTION EVERYWHERE ZERO, FUNLZ SETS XLOW=XHIGH=0.
526      implicit none
527      external func
528      integer logn,nslice,i,k
529      real xhigh,xlow,x2high,x2low,func,xmid,xh,xl,xnew
530      xlow = x2low
531      xhigh = x2high
532!         FIND OUT IF FUNCTION IS ZERO AT ONE END OR BOTH
533      xmid = xlow
534      if (func(xlow) .gt. 0.) go to 120
535      xmid = xhigh
536      if (func(xhigh) .gt. 0.)  go to 50
537!         FUNCTION IS ZERO AT BOTH ENDS,
538!         LOOK FOR PLACE WHERE IT IS NON-ZERO.
539      do 30 logn= 1, 7
540      nslice = 2**logn
541      do 20 i= 1, nslice, 2
542      xmid = xlow + i * (xhigh-xlow) / nslice
543      if (func(xmid) .gt. 0.)  go to 50
544   20 continue
545   30 continue
546!         FALLING THROUGH LOOP MEANS CANNOT FIND NON-ZERO VALUE
547      write(*,554)
548      write(*,555) xlow, xhigh
549      xlow = 0.
550      xhigh = 0.
551      go to 220
552!
553   50 continue
554!         DELETE 'LEADING' ZERO RANGE
555      xh = xmid
556      xl = xlow
557      do 70 k= 1, 20
558      xnew = 0.5*(xh+xl)
559      if (func(xnew) .eq. 0.) go to 68
560      xh = xnew
561      go to 70
562   68 xl = xnew
563   70 continue
564      xlow = xl
565      write(*,555) x2low,xlow
566  120 continue
567      if (func(xhigh) .gt. 0.) go to 220
568!         DELETE 'TRAILING' RANGE OF ZEROES
569      xl = xmid
570      xh = xhigh
571      do 170 k= 1, 20
572      xnew = 0.5*(xh+xl)
573      if (func(xnew) .eq. 0.) go to 168
574      xl = xnew
575      go to 170
576  168 xh = xnew
577  170 continue
578      xhigh = xh
579      write(*,555) xhigh, x2high
580!
581  220 continue
582      return
583  554 format('0CANNOT FIND NON-ZERO FUNCTION VALUE')
584  555 format(' FUNCTION IS ZERO FROM X=',e12.5,' TO ',e12.5)
585      end
586
587
588!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
589!
590! $Id: radapt.F,v 1.1.1.1 1996/04/01 15:02:13 mclareni Exp $
591!
592! $Log: radapt.F,v $
593! Revision 1.1.1.1  1996/04/01 15:02:13  mclareni
594! Mathlib gen
595!
596!
597      subroutine radapt(f,a,b,nseg,reltol,abstol,res,err)
598 
599!     RES = Estimated Integral of F from A to B,
600!     ERR = Estimated absolute error on RES.
601!     NSEG  specifies how the adaptation is to be done:
602!        =0   means use previous binning,
603!        =1   means fully automatic, adapt until tolerance attained.
604!        =n>1 means first split interval into n equal segments,
605!             then adapt as necessary to attain tolerance.
606!     The specified tolerances are:
607!            relative: RELTOL ;  absolute: ABSTOL.
608!        It stop s when one OR the other is satisfied, or number of
609!        segments exceeds NDIM.  Either TOLA or TOLR (but not both!)
610!        can be set to zero, in which case only the other is used.
611 
612      implicit none
613      external f
614      integer nseg,ndim,nter,nsegd,i,iter,ibig
615      real err,res,abstol,reltol,b,a,xlo,xhi,tval,ters,te,root,xhib,    &
616     &bin,xlob,bige,hf,xnew,r1,f
617      double precision tvals,terss
618 
619      parameter (ndim=100)
620      parameter (r1 = 1., hf = r1/2.)
621 
622      dimension xlo(ndim),xhi(ndim),tval(ndim),ters(ndim)
623      save xlo,xhi,tval,ters,nter
624      data nter /0/
625 
626      if(nseg .le. 0)  then
627       if(nter .eq. 0) then
628        nsegd=1
629        go to 2
630       endif
631       tvals=0d0
632       terss=0d0
633       do 1 i = 1,nter
634       call rgs56p(f,xlo(i),xhi(i),tval(i),te)
635       ters(i)=te**2
636       tvals=tvals+tval(i)
637       terss=terss+ters(i)
638    1  continue
639       root= sqrt(2.*terss)
640       go to 9
641      endif
642      nsegd=min(nseg,ndim)
643    2 xhib=a
644      bin=(b-a)/nsegd
645      do 3 i = 1,nsegd
646      xlo(i)=xhib
647      xlob=xlo(i)
648      xhi(i)=xhib+bin
649      if(i .eq. nsegd) xhi(i)=b
650      xhib=xhi(i)
651      call rgs56p(f,xlob,xhib,tval(i),te)
652      ters(i)=te**2
653    3 continue
654      nter=nsegd
655      do 4 iter = 1,ndim
656      tvals=tval(1)
657      terss=ters(1)
658      do 5 i = 2,nter
659      tvals=tvals+tval(i)
660      terss=terss+ters(i)
661    5 continue
662      root= sqrt(2.*terss)
663      if(root .le. abstol .or. root .le. reltol*abs(tvals)) go to 9
664      if(nter .eq. ndim) go to 9
665      bige=ters(1)
666      ibig=1
667      do 6 i = 2,nter
668      if(ters(i) .gt. bige) then
669       bige=ters(i)
670       ibig=i
671      endif
672    6 continue
673      nter=nter+1
674      xhi(nter)=xhi(ibig)
675      xnew=hf*(xlo(ibig)+xhi(ibig))
676      xhi(ibig)=xnew
677      xlo(nter)=xnew
678      call rgs56p(f,xlo(ibig),xhi(ibig),tval(ibig),te)
679      ters(ibig)=te**2
680      call rgs56p(f,xlo(nter),xhi(nter),tval(nter),te)
681      ters(nter)=te**2
682    4 continue
683    9 res=tvals
684      err=root
685      return
686      end
687
688
689!cccccccccccccccccccccccccccccccccccccccccccccccccccccc
690 
691!
692! $Id: rgs56p.F,v 1.1.1.1 1996/04/01 15:02:14 mclareni Exp $
693!
694! $Log: rgs56p.F,v $
695! Revision 1.1.1.1  1996/04/01 15:02:14  mclareni
696! Mathlib gen
697!
698!
699      subroutine rgs56p(f,a,b,res,err)
700      implicit none
701      integer i
702      real err,res,b,a,f,w6,x6,w5,x5,rang,r1,hf
703      double precision e5,e6
704 
705      parameter (r1 = 1., hf = r1/2.)
706      dimension x5(5),w5(5),x6(6),w6(6)
707 
708      data (x5(i),w5(i),i=1,5)                                          &
709     &/4.6910077030668004e-02, 1.1846344252809454e-01,                  &
710     &2.3076534494715846e-01, 2.3931433524968324e-01,                   &
711     &5.0000000000000000e-01, 2.8444444444444444e-01,                   &
712     &7.6923465505284154e-01, 2.3931433524968324e-01,                   &
713     &9.5308992296933200e-01, 1.1846344252809454e-01/
714 
715      data (x6(i),w6(i),i=1,6)                                          &
716     &/3.3765242898423989e-02, 8.5662246189585178e-02,                  &
717     &1.6939530676686775e-01, 1.8038078652406930e-01,                   &
718     &3.8069040695840155e-01, 2.3395696728634552e-01,                   &
719     &6.1930959304159845e-01, 2.3395696728634552e-01,                   &
720     &8.3060469323313225e-01, 1.8038078652406930e-01,                   &
721     &9.6623475710157601e-01, 8.5662246189585178e-02/
722 
723      rang=b-a
724      e5=0d0
725      e6=0d0
726      do 1 i = 1,5
727      e5=e5+w5(i)*f(a+rang*x5(i))
728      e6=e6+w6(i)*f(a+rang*x6(i))
729    1 continue
730      e6=e6+w6(6)*f(a+rang*x6(6))
731      res=hf*(e6+e5)*rang
732      err=abs((e6-e5)*rang)
733      return
734      end
735!GRD
736
737
738!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
739!C
740!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
741      subroutine funpct(func,ifunc,xlow,xhigh,xfcum,nlo,nbins,tftot,    &
742     &ierr)
743!        Array XFCUM is filled from NLO to NLO+NBINS, which makes
744!        the number of values NBINS+1, or the number of bins NBINS
745      implicit none
746      external func
747      integer ierr,nbins,nlo,ifunc,nz,ibin,maxz,iz,nitmax,ihome
748      real tftot,xhigh,xlow,func,xfcum,rteps,tpctil,tz,tzmax,x,f,tcum,  &
749     &x1,f1,dxmax,fmin,fminz,xincr,tincr,xbest,dtbest,tpart,x2,precis,  &
750     &refx,uncert,tpart2,dtpar2,dtabs,aberr
751      dimension xfcum(*)
752      parameter (rteps=0.005, nz=10, maxz=20, nitmax=6,precis=1e-6)
753!      DOUBLE PRECISION TPCTIL, TZ, TCUM, XINCR, DTABS,
754!     &  TINCR, TZMAX, XBEST, DTBEST, DTPAR2
755!
756      ierr = 0
757      if (tftot .le. 0.) go to 900
758      tpctil = tftot/nbins
759      tz = tpctil/nz
760      tzmax = tz * 2.
761      xfcum(nlo) = xlow
762      xfcum(nlo+nbins) = xhigh
763      x = xlow
764      f = func(x)
765      if (f .lt. 0.) go to 900
766!         Loop over percentile bins
767      do 600 ibin = nlo, nlo+nbins-2
768      tcum = 0.
769      x1 = x
770      f1 = f
771      dxmax = (xhigh -x) / nz
772      fmin = tz/dxmax
773      fminz = fmin
774!         Loop over trapezoids within a supposed percentil
775      do 500 iz= 1, maxz
776      xincr = tz/max(f1,fmin,fminz)
777  350 x = x1 + xincr
778      f = func(x)
779      if (f .lt. 0.) go to 900
780      tincr = (x-x1) * 0.5 * (f+f1)
781      if (tincr .lt. tzmax) go to 370
782      xincr = xincr * 0.5
783      go to 350
784  370 continue
785      tcum = tcum + tincr
786      if (tcum .ge. tpctil*0.99) go to 520
787      fminz = tz*f/ (tpctil-tcum)
788      f1 = f
789      x1 = x
790  500 continue
791      write(*,*) ' FUNLUX:  WARNING. FUNPCT fails trapezoid.'
792!         END OF TRAPEZOID LOOP
793!         Adjust interval using Gaussian integration with
794!             Newton corrections since F is the derivative
795  520 continue
796      x1 = xfcum(ibin)
797      xbest = x
798      dtbest = tpctil
799      tpart = tpctil
800!         Allow for maximum NITMAX more iterations on RADAPT
801      do 550 ihome= 1, nitmax
802  535 xincr = (tpctil-tpart) / max(f,fmin)
803      x = xbest + xincr
804      x2 = x
805        if (ihome .gt. 1 .and. x2 .eq. xbest) then
806        write(*,'(A,G12.3)')                                            &
807     &' FUNLUX: WARNING from FUNPCT: insufficient precision at X=',x
808        go to 580
809        endif
810      refx = abs(x)+precis
811      call radapt(func,x1,x2,1,rteps,0.,tpart2,uncert)
812      dtpar2 = tpart2-tpctil
813      dtabs = abs(dtpar2)
814      if(abs(xincr)/refx .lt. precis) goto 545
815      if(dtabs .lt. dtbest) goto 545
816      xincr = xincr * 0.5
817      goto 535
818  545 dtbest = dtabs
819      xbest = x
820      tpart = tpart2
821      f = func(x)
822      if(f .lt. 0.) goto 900
823      if(dtabs .lt. rteps*tpctil) goto 580
824  550 continue
825      write(*,'(A,I4)')                                                 &
826     &' FUNLUX: WARNING from FUNPCT: cannot converge, bin',ibin
827!
828  580 continue
829      xincr = (tpctil-tpart) / max(f,fmin)
830      x = xbest + xincr
831      xfcum(ibin+1) = x
832      f = func(x)
833      if(f .lt. 0.) goto 900
834  600 continue
835!         END OF LOOP OVER BINS
836      x1 = xfcum(nlo+nbins-1)
837      x2 = xhigh
838      call radapt(func,x1,x2,1,rteps,0.,tpart ,uncert)
839      aberr = abs(tpart-tpctil)/tftot
840!      WRITE(6,1001) IFUNC,XLOW,XHIGH
841      if(aberr .gt. rteps)  write(*,1002) aberr
842      return
843  900 write(*,1000) x,f
844      ierr = 1
845      return
846 1000 format(/' FUNLUX fatal error in FUNPCT: function negative:'/      &
847     &,' at X=',e15.6,', F=',e15.6/)
848! 1001 FORMAT(' FUNPCT has prepared USER FUNCTION',I3,
849!     + ' between',G12.3,' and',G12.3,' for FUNLUX.')
850 1002 format(' WARNING: Relative error in cumulative distribution',     &
851     &' may be as big as',f10.7)
852      end
853 
854
Note: See TracBrowser for help on using the repository browser.