+++ /dev/null
- module random
-!-----------------------------------------------------------------------------
- use io_units
- use prng ! prng.f90 or prng_32.f90
- use math
- implicit none
-! public :: rndv
-!
-!-----------------------------------------------------------------------------
- contains
-!-----------------------------------------------------------------------------
-! gen_rand_conf.F
-!-----------------------------------------------------------------------------
- real(kind=8) function ran_number(x1,x2)
-! Calculate a random real number from the range (x1,x2).
-#ifdef MPI
- use MPI_data ! include 'COMMON.SETUP'
- include "mpif.h"
-#endif
-
-! implicit real*8 (a-h,o-z)
-! include 'DIMENSIONS'
- real(kind=8) :: x1,x2,fctor
-!el local variables
- integer :: ix(1) !el ix ---> ix(1)
- data fctor /2147483647.0D0/
-#ifdef MPI
- ran_number=x1+(x2-x1)*prng_next(me)
-#else
- call vrnd(ix(1),1)
- ran_number=x1+(x2-x1)*ix(1)/fctor
-#endif
- return
- end function ran_number
-!-----------------------------------------------------------------------------
- integer function iran_num(n1,n2)
-! Calculate a random integer number from the range (n1,n2).
-#ifdef MPI
- use MPI_data ! include 'COMMON.SETUP'
- include "mpif.h"
-#endif
-! implicit real*8 (a-h,o-z)
-! include 'DIMENSIONS'
- integer :: n1,n2,ix(1) !el ix ---> ix(1)
- real(kind=4) :: fctor=2147483647.0
-#ifdef MPI
- ix(1)=n1+(n2-n1+1)*prng_next(me)
- if (ix(1).lt.n1) ix(1)=n1
- if (ix(1).gt.n2) ix(1)=n2
- iran_num=ix(1)
-#else
- call vrnd(ix(1),1)
- ix(1)=n1+(n2-n1+1)*(ix(1)/fctor)
- if (ix(1).gt.n2) ix(1)=n2
- iran_num=ix(1)
-#endif
- return
- end function iran_num
-!-----------------------------------------------------------------------------
- real(kind=8) function binorm(x1,x2,sigma1,sigma2,ak)
-! implicit real*8 (a-h,o-z)
-!el local variables
- real(kind=8) :: x1,x2,sigma1,sigma2,ak,alowb,aupb,seg,alen
-! print '(a)','Enter BINORM.'
- alowb=dmin1(x1-3.0D0*sigma1,x2-3.0D0*sigma2)
- aupb=dmax1(x1+3.0D0*sigma1,x2+3.0D0*sigma2)
- seg=sigma1/(sigma1+ak*sigma2)
- alen=ran_number(0.0D0,1.0D0)
- if (alen.lt.seg) then
- binorm=anorm_distr(x1,sigma1,alowb,aupb)
- else
- binorm=anorm_distr(x2,sigma2,alowb,aupb)
- endif
-! print '(a)','Exiting BINORM.'
- return
- end function binorm
-!-----------------------------------------------------------------------------
- real(kind=8) function anorm_distr(x,sigma,alowb,aupb)
-! implicit real*8 (a-h,o-z)
-! to make a normally distributed deviate with zero mean and unit variance
-!
- integer :: iset
- real(kind=8) :: fac,gset,rsq,v1,v2,ran1
- real(kind=8) :: x,sigma,alowb,aupb,gaussdev
- save iset,gset
- data iset/0/
-!elwrite(iout,*) "anorm distr start",x,sigma,alowb,aupb
- if(iset.eq.0) then
- 1 v1=2.0d0*ran_number(0.0d0,1.0d0)-1.0d0
- v2=2.0d0*ran_number(0.0d0,1.0d0)-1.0d0
- rsq=v1**2+v2**2
- if(rsq.ge.1.d0.or.rsq.eq.0.0d0) goto 1
- fac=sqrt(-2.0d0*log(rsq)/rsq)
- gset=v1*fac
- gaussdev=v2*fac
- iset=1
- else
- gaussdev=gset
- iset=0
- endif
- anorm_distr=x+gaussdev*sigma
-!elwrite(iout,*) "anorm distr end",x,sigma,alowb,aupb,anorm_distr
- return
- end function anorm_distr
-!-----------------------------------------------------------------------------
- subroutine mult_norm(lda,n,a,x,fail)
-!
-! Generate the vector X whose elements obey the multiple-normal distribution
-! from exp(-0.5*X'AX). LDA is the leading dimension of the moment matrix A,
-! n is the dimension of the problem. FAIL is set at .TRUE., if the smallest
-! eigenvalue of the matrix A is close to 0.
-!
-! implicit double precision (a-h,o-z)
- integer :: lda,n,i,j
- real(kind=8),dimension(lda,n) :: a
- real(kind=8),dimension(n) :: x
- real(kind=8),dimension(100) :: eig,work
- real(kind=8),dimension(3,3) :: vec
- real(kind=8) :: eig_limit=1.0D-8
- logical :: fail
- real(kind=8) :: sigma,alim,xi
- fail=.false.
-! print '(a)','Enter MULT_NORM.'
-!
-! Find the smallest eigenvalue of the matrix A.
-!
-! do i=1,n
-! print '(8f10.5)',(a(i,j),j=1,n)
-! enddo
-#ifdef NAG
- call f02faf('V','U',2,a,lda,eig,work,100,ifail)
-#else
- call djacob(2,lda,10000,1.0d-10,a,vec,eig)
-#endif
-! print '(8f10.5)',(eig(i),i=1,n)
-! print '(a)'
-! do i=1,n
-! print '(8f10.5)',(a(i,j),j=1,n)
-! enddo
- if (eig(1).lt.eig_limit) then
- print *,'From Mult_Norm: Eigenvalues of A are too small.'
- fail=.true.
- return
- endif
-!
-! Generate points following the normal distributions along the principal
-! axes of the moment matrix. Store in WORK.
-!
- do i=1,n
- sigma=1.0D0/dsqrt(eig(i))
- alim=-3.0D0*sigma
- work(i)=anorm_distr(0.0D0,sigma,-alim,alim)
- enddo
-!
-! Transform the vector of normal variables back to the original basis.
-!
- do i=1,n
- xi=0.0D0
- do j=1,n
- xi=xi+a(i,j)*work(j)
- enddo
- x(i)=xi
- enddo
- return
- end subroutine mult_norm
-!-----------------------------------------------------------------------------
- subroutine mult_norm1(lda,n,a,z,box,x,fail)
-!
-! Generate the vector X whose elements obey the multi-gaussian multi-dimensional
-! distribution from sum_{i=1}^m W(i)exp[-0.5*X'(i)A(i)X(i)]. LDA is the
-! leading dimension of the moment matrix A, n is the dimension of the
-! distribution, nlob is the number of lobes. FAIL is set at .TRUE., if the
-! smallest eigenvalue of the matrix A is close to 0.
-!
-! implicit real*8 (a-h,o-z)
-! include 'DIMENSIONS'
-#ifdef MP
- use MPI_data !include 'COMMON.SETUP'
-#endif
-#ifdef MPI
- include 'mpif.h'
-#endif
- integer :: lda,n,i,j,istep
- real(kind=8),dimension(lda,n) :: a
- real(kind=8),dimension(n) :: z,x
- real(kind=8),dimension(n,n) :: box
- real(kind=8) :: etmp,ww,xi,dec
-! include 'COMMON.IOUNITS'
- logical :: fail
-!
-! Generate points following the normal distributions along the principal
-! axes of the moment matrix. Store in WORK.
-!
-!d print *,'CG Processor',me,' entered MultNorm1.'
-!d print '(2(1pe14.4),3x,1pe14.4)',((a(i,j),j=1,2),z(i),i=1,2)
-!d do i=1,n
-!d print *,i,box(1,i),box(2,i)
-!d enddo
- istep = 0
- 10 istep = istep + 1
- if (istep.gt.10000) then
-! write (iout,'(a,i4,2a)') 'CG Processor: ',me,': too many steps',
-! & ' in MultNorm1.'
-! write (*,'(a,i4,2a)') 'CG Processor: ',me,': too many steps',
-! & ' in MultNorm1.'
-! write (iout,*) 'box',box
-! write (iout,*) 'a',a
-! write (iout,*) 'z',z
- fail=.true.
- return
- endif
- do i=1,n
- x(i)=ran_number(box(1,i),box(2,i))
- enddo
- ww=0.0D0
- do i=1,n
- xi=pinorm(x(i)-z(i))
- ww=ww+0.5D0*a(i,i)*xi*xi
- do j=i+1,n
- ww=ww+a(i,j)*xi*pinorm(x(j)-z(j))
- enddo
- enddo
- dec=ran_number(0.0D0,1.0D0)
-! print *,(x(i),i=1,n),ww,dexp(-ww),dec
-!rc if (dec.gt.dexp(-ww)) goto 10
- if(-ww.lt.100) then
- etmp=dexp(-ww)
- else
- return
- endif
- if (dec.gt.etmp) goto 10
-!d print *,'CG Processor',me,' exitting MultNorm1.'
- return
- end subroutine mult_norm1
-!-----------------------------------------------------------------------------
-! ran.f
-!-----------------------------------------------------------------------------
- function ran0(idum)
- integer :: idum
- integer,parameter :: IA=16807,IM=2147483647,IQ=127773,IR=2836
- integer,parameter :: MASK=123459876
- real(kind=4) :: ran0
- real(kind=4),parameter :: AM=1./IM
- integer :: k
- idum=ieor(idum,MASK)
- k=idum/IQ
- idum=IA*(idum-k*IQ)-IR*k
- if (idum.lt.0) idum=idum+IM
- ran0=AM*idum
- idum=ieor(idum,MASK)
- return
- end function ran0
-! (C) Copr. 1986-92 Numerical Recipes Software *11915
-!-----------------------------------------------------------------------------
- function ran1(idum)
- integer :: idum
- integer,parameter :: IA=16807,IM=2147483647,IQ=127773,IR=2836
- integer,parameter :: NTAB=32,NDIV=1+(IM-1)/NTAB
- real(kind=4) :: ran1
- real(kind=4),parameter :: AM=1./IM,EPS=1.2e-7,RNMX=1.-EPS
- integer :: j,k,iy
- integer,dimension(NTAB) :: iv
- SAVE iv,iy
- DATA iv /NTAB*0/, iy /0/
- if (idum.le.0.or.iy.eq.0) then
- idum=max(-idum,1)
- do 11 j=NTAB+8,1,-1
- k=idum/IQ
- idum=IA*(idum-k*IQ)-IR*k
- if (idum.lt.0) idum=idum+IM
- if (j.le.NTAB) iv(j)=idum
-11 continue
- iy=iv(1)
- endif
- k=idum/IQ
- idum=IA*(idum-k*IQ)-IR*k
- if (idum.lt.0) idum=idum+IM
- j=1+iy/NDIV
- iy=iv(j)
- iv(j)=idum
- ran1=min(AM*iy,RNMX)
- return
- end function ran1
-! (C) Copr. 1986-92 Numerical Recipes Software *11915
-!-----------------------------------------------------------------------------
- function ran2(idum)
- integer :: idum
- integer,parameter :: IM1=2147483563,IM2=2147483399,IMM1=IM1-1,&
- IA1=40014,IA2=40692,IQ1=53668,IQ2=52774,IR1=12211,IR2=3791,&
- NTAB=32,NDIV=1+IMM1/NTAB
- real(kind=4) :: ran2
- real(kind=4),parameter :: AM=1./IM1,EPS=1.2e-7,RNMX=1.-EPS
- integer :: idum2,j,k,iy
- integer,dimension(NTAB) :: iv
- SAVE iv,iy,idum2
- DATA idum2/123456789/, iv/NTAB*0/, iy/0/
- if (idum.le.0) then
- idum=max(-idum,1)
- idum2=idum
- do 11 j=NTAB+8,1,-1
- k=idum/IQ1
- idum=IA1*(idum-k*IQ1)-k*IR1
- if (idum.lt.0) idum=idum+IM1
- if (j.le.NTAB) iv(j)=idum
-11 continue
- iy=iv(1)
- endif
- k=idum/IQ1
- idum=IA1*(idum-k*IQ1)-k*IR1
- if (idum.lt.0) idum=idum+IM1
- k=idum2/IQ2
- idum2=IA2*(idum2-k*IQ2)-k*IR2
- if (idum2.lt.0) idum2=idum2+IM2
- j=1+iy/NDIV
- iy=iv(j)-idum2
- iv(j)=idum
- if(iy.lt.1)iy=iy+IMM1
- ran2=min(AM*iy,RNMX)
- return
- end function ran2
-! (C) Copr. 1986-92 Numerical Recipes Software *11915
-!-----------------------------------------------------------------------------
- function ran3(idum)
- integer :: idum
- integer,parameter :: MBIG=1000000000,MSEED=161803398,MZ=0
-! REAL MBIG,MSEED,MZ
- real(kind=4) :: ran3
- real(kind=4),parameter :: FAC=1./MBIG
-! PARAMETER (MBIG=4000000.,MSEED=1618033.,MZ=0.,FAC=1./MBIG)
- integer :: i,iff,ii,inext,inextp,k
- integer :: mj,mk
- integer,dimension(55) :: ma
-! REAL mj,mk,ma(55)
- SAVE iff,inext,inextp,ma
- DATA iff /0/
- if(idum.lt.0.or.iff.eq.0)then
- iff=1
- mj=MSEED-iabs(idum)
- mj=mod(mj,MBIG)
- ma(55)=mj
- mk=1
- do 11 i=1,54
- ii=mod(21*i,55)
- ma(ii)=mk
- mk=mj-mk
- if(mk.lt.MZ)mk=mk+MBIG
- mj=ma(ii)
-11 continue
- do 13 k=1,4
- do 12 i=1,55
- ma(i)=ma(i)-ma(1+mod(i+30,55))
- if(ma(i).lt.MZ)ma(i)=ma(i)+MBIG
-12 continue
-13 continue
- inext=0
- inextp=31
- idum=1
- endif
- inext=inext+1
- if(inext.eq.56)inext=1
- inextp=inextp+1
- if(inextp.eq.56)inextp=1
- mj=ma(inext)-ma(inextp)
- if(mj.lt.MZ)mj=mj+MBIG
- ma(inext)=mj
- ran3=mj*FAC
- return
- end function ran3
-! (C) Copr. 1986-92 Numerical Recipes Software *11915
-!-----------------------------------------------------------------------------
-! randgens.f
-!-----------------------------------------------------------------------------
-! $Date: 1994/10/04 16:19:52 $
-! $Revision: 2.1 $
-!
-!
-! See help for RANDOMV on the PSFSHARE disk to understand these
-! subroutines. This is the VS Fortran version of this code.
-!
-!
- subroutine VRND(VEC,N)
-
- use comm_vrandd
-!el integer,dimension(250) :: A
- integer :: LOOP,N !el,I,I147
- integer,dimension(N) :: VEC
-!el COMMON /VRANDD/ A, I, I147
- DO 23000 LOOP=1,N
- I=I+1
- IF(.NOT.(I.GE.251))GOTO 23002
- I=1
-23002 CONTINUE
- I147=I147+1
- IF(.NOT.(I147.GE.251))GOTO 23004
- I147=1
-23004 CONTINUE
- A(I)=IEOR(A(I147),A(I))
- VEC(LOOP)=A(I)
-23000 CONTINUE
- return
- end subroutine VRND
-!-----------------------------------------------------------------------------
- real(kind=8) function RNDV(IDUM)
-
- real(kind=8) :: RM1,RM2,R(99)
- INTEGER :: IA1,IC1,M1, IA2,IC2,M2, IA3,IC3,M3, IDUM
- INTEGER :: IX1,IX2,IX3,J
- SAVE
- DATA IA1,IC1,M1/1279,351762,1664557/
- DATA IA2,IC2,M2/2011,221592,1048583/
- DATA IA3,IC3,M3/15551,6150,29101/
- IF(.NOT.(IDUM.LT.0))GOTO 23006
- IX1 = MOD(-IDUM,M1)
- IX1 = MOD(IA1*IX1+IC1,M1)
- IX2 = MOD(IX1,M2)
- IX1 = MOD(IA1*IX1+IC1,M1)
- IX3 = MOD(IX1,M3)
- RM1 = 1./DBLE(M1)
- RM2 = 1./DBLE(M2)
- DO 23008 J = 1,99
- IX1 = MOD(IA1*IX1+IC1,M1)
- IX2 = MOD(IA2*IX2+IC2,M2)
- R(J) = (DBLE(IX1)+DBLE(IX2)*RM2)*RM1
-23008 CONTINUE
-23006 CONTINUE
- IX1 = MOD(IA1*IX1+IC1,M1)
- IX2 = MOD(IA2*IX2+IC2,M2)
- IX3 = MOD(IA3*IX3+IC3,M3)
- J = 1+(99*IX3)/M3
- RNDV = R(J)
- R(J) = (DBLE(IX1)+DBLE(IX2)*RM2)*RM1
- IDUM = IX1
- return
- end function RNDV
-!-----------------------------------------------------------------------------
- subroutine VRNDST(SEED)
-
- use comm_vrandd
-!el INTEGER :: A(250)
- INTEGER :: LOOP,IDUM !el,I,I147
- INTEGER :: SEED
-!el real(kind=8) :: RNDV
-!el COMMON /VRANDD/ A, I, I147
- I=0
- I147=103
- IDUM=SEED
- DO 23010 LOOP=1,250
- A(LOOP)=INT(RNDV(IDUM)*2147483647)
-23010 CONTINUE
- return
- end subroutine VRNDST
-!-----------------------------------------------------------------------------
- subroutine VRNDIN(IODEV)
- use comm_vrandd
- INTEGER :: IODEV !el, A(250),I, I147
-!el COMMON/VRANDD/ A, I, I147
- READ(IODEV) A, I, I147
- return
- end subroutine VRNDIN
-!-----------------------------------------------------------------------------
- subroutine VRNDOU(IODEV)
-! This corresponds to VRNDOUT in the APFTN64 version
- use comm_vrandd
- INTEGER :: IODEV !el, A(250),I, I147
-!el COMMON/VRANDD/ A, I, I147
- WRITE(IODEV) A, I, I147
- return
- end subroutine VRNDOU
-!-----------------------------------------------------------------------------
- real(kind=8) function RNUNF(N)
- INTEGER :: IRAN1(2000),N
- real(kind=8) :: FCTOR
- DATA FCTOR /2147483647.0D0/
-! We get only one random number, here! DR 9/1/92
- CALL VRND(IRAN1,1)
- RNUNF= DBLE( IRAN1(1) ) / FCTOR
-!******************************
-! write(6,*) 'rnunf in rnunf = ',rnunf
- return
- end function RNUNF
-!-----------------------------------------------------------------------------
-! readrtns_CSA.F
-!-----------------------------------------------------------------------------
- subroutine random_init(seed)
-!
-! Initialize random number generator
-!
-! implicit real*8 (a-h,o-z)
-! include 'DIMENSIONS'
-#ifdef MPI
- use MPI_data
- include 'mpif.h'
- logical :: OKRandom !, prng_restart
- real(kind=8) :: r1
- integer :: iseed_array(4)
- integer(kind=8) :: iseed
-#else
- integer :: iseed
-#endif
- real(kind=8) :: seed
- integer :: ierr,error_msg
-! include 'COMMON.IOUNITS'
-! include 'COMMON.TIME1'
-! include 'COMMON.THREAD'
-! include 'COMMON.SBRIDGE'
-! include 'COMMON.CONTROL'
-! include 'COMMON.MCM'
-! include 'COMMON.MAP'
-! include 'COMMON.HEADER'
-! include 'COMMON.CSA'
-! include 'COMMON.CHAIN'
-! include 'COMMON.MUCA'
-! include 'COMMON.MD'
-! include 'COMMON.FFIELD'
-! include 'COMMON.SETUP'
- iseed=-dint(dabs(seed))
- if (iseed.eq.0) then
- write (iout,'(/80(1h*)/20x,a/80(1h*))') &
- 'Random seed undefined. The program will stop.'
- write (*,'(/80(1h*)/20x,a/80(1h*))') &
- 'Random seed undefined. The program will stop.'
-#ifdef MPI
- call mpi_finalize(mpi_comm_world,ierr)
-#endif
- stop 'Bad random seed.'
- endif
-#ifdef MPI
- if (fg_rank.eq.0) then
- seed=seed*(me+1)+1
-#ifdef AMD64
- if(me.eq.king) &
- write (iout,*) 'MPI: node= ', me, ' iseed= ',iseed
- OKRandom = prng_restart(me,iseed)
-#else
- do i=1,4
- tmp=65536.0d0**(4-i)
- iseed_array(i) = dint(seed/tmp)
- seed=seed-iseed_array(i)*tmp
- enddo
- if(me.eq.king) &
- write (iout,*) 'MPI: node= ', me, ' iseed(4)= ',&
- (iseed_array(i),i=1,4)
- write (*,*) 'MPI: node= ',me, ' iseed(4)= ',&
- (iseed_array(i),i=1,4)
- OKRandom = prng_restart(me,iseed_array)
-#endif
- if (OKRandom) then
-! r1 = prng_next(me)
- r1=ran_number(0.0D0,1.0D0)
- if(me.eq.king) &
- write (iout,*) 'ran_num',r1
- if (r1.lt.0.0d0) OKRandom=.false.
- endif
- if (.not.OKRandom) then
- write (iout,*) 'PRNG IS NOT WORKING!!!'
- print *,'PRNG IS NOT WORKING!!!'
- if (me.eq.0) then
- call flush(iout)
- call mpi_abort(mpi_comm_world,error_msg,ierr)
- stop
- else
- write (iout,*) 'too many processors for parallel prng'
- write (*,*) 'too many processors for parallel prng'
- call flush(iout)
- stop
- endif
- endif
- endif
-#else
- call vrndst(iseed)
- write (iout,*) 'ran_num',ran_number(0.0d0,1.0d0)
-#endif
- return
- end subroutine random_init
-!-----------------------------------------------------------------------------
-!-----------------------------------------------------------------------------
- end module random