korc_rnd_numbers.f90 Source File


This file depends on

sourcefile~~korc_rnd_numbers.f90~~EfferentGraph sourcefile~korc_rnd_numbers.f90 korc_rnd_numbers.f90 sourcefile~korc_random.f90 korc_random.f90 sourcefile~korc_rnd_numbers.f90->sourcefile~korc_random.f90 sourcefile~korc_types.f90 korc_types.f90 sourcefile~korc_rnd_numbers.f90->sourcefile~korc_types.f90 sourcefile~korc_random.f90->sourcefile~korc_types.f90

Files dependent on this one

sourcefile~~korc_rnd_numbers.f90~~AfferentGraph sourcefile~korc_rnd_numbers.f90 korc_rnd_numbers.f90 sourcefile~korc_velocity_distribution.f90 korc_velocity_distribution.f90 sourcefile~korc_velocity_distribution.f90->sourcefile~korc_rnd_numbers.f90 sourcefile~korc_experimental_pdf.f90 korc_experimental_pdf.f90 sourcefile~korc_velocity_distribution.f90->sourcefile~korc_experimental_pdf.f90 sourcefile~korc_fields.f90 korc_fields.f90 sourcefile~korc_velocity_distribution.f90->sourcefile~korc_fields.f90 sourcefile~korc_avalanche.f90 korc_avalanche.f90 sourcefile~korc_velocity_distribution.f90->sourcefile~korc_avalanche.f90 sourcefile~korc_experimental_pdf.f90->sourcefile~korc_rnd_numbers.f90 sourcefile~korc_interp.f90 korc_interp.f90 sourcefile~korc_experimental_pdf.f90->sourcefile~korc_interp.f90 sourcefile~korc_experimental_pdf.f90->sourcefile~korc_fields.f90 sourcefile~korc_initialize.f90 korc_initialize.f90 sourcefile~korc_initialize.f90->sourcefile~korc_rnd_numbers.f90 sourcefile~korc_initialize.f90->sourcefile~korc_velocity_distribution.f90 sourcefile~korc_spatial_distribution.f90 korc_spatial_distribution.f90 sourcefile~korc_initialize.f90->sourcefile~korc_spatial_distribution.f90 sourcefile~korc_initialize.f90->sourcefile~korc_fields.f90 sourcefile~korc_spatial_distribution.f90->sourcefile~korc_rnd_numbers.f90 sourcefile~korc_spatial_distribution.f90->sourcefile~korc_experimental_pdf.f90 sourcefile~korc_profiles.f90 korc_profiles.f90 sourcefile~korc_spatial_distribution.f90->sourcefile~korc_profiles.f90 sourcefile~korc_spatial_distribution.f90->sourcefile~korc_fields.f90 sourcefile~korc_spatial_distribution.f90->sourcefile~korc_avalanche.f90 sourcefile~korc_interp.f90->sourcefile~korc_rnd_numbers.f90 sourcefile~korc_profiles.f90->sourcefile~korc_interp.f90 sourcefile~korc_ppusher.f90 korc_ppusher.f90 sourcefile~korc_ppusher.f90->sourcefile~korc_interp.f90 sourcefile~korc_ppusher.f90->sourcefile~korc_profiles.f90 sourcefile~korc_collisions.f90 korc_collisions.f90 sourcefile~korc_ppusher.f90->sourcefile~korc_collisions.f90 sourcefile~korc_ppusher.f90->sourcefile~korc_fields.f90 sourcefile~korc_collisions.f90->sourcefile~korc_interp.f90 sourcefile~korc_collisions.f90->sourcefile~korc_profiles.f90 sourcefile~korc_collisions.f90->sourcefile~korc_fields.f90 sourcefile~main.f90 main.f90 sourcefile~main.f90->sourcefile~korc_initialize.f90 sourcefile~main.f90->sourcefile~korc_interp.f90 sourcefile~main.f90->sourcefile~korc_profiles.f90 sourcefile~main.f90->sourcefile~korc_ppusher.f90 sourcefile~main.f90->sourcefile~korc_collisions.f90 sourcefile~main.f90->sourcefile~korc_fields.f90 sourcefile~korc_finalize.f90 korc_finalize.f90 sourcefile~main.f90->sourcefile~korc_finalize.f90 sourcefile~korc_fields.f90->sourcefile~korc_interp.f90 sourcefile~korc_avalanche.f90->sourcefile~korc_profiles.f90 sourcefile~korc_avalanche.f90->sourcefile~korc_fields.f90 sourcefile~korc_finalize.f90->sourcefile~korc_profiles.f90 sourcefile~korc_finalize.f90->sourcefile~korc_fields.f90

Contents

Source Code


Source Code

module korc_rnd_numbers
  !! @note Module with subrotuines for generating integer 
  !! and real random numbers.@endnote
  !! This subroutines were taken from Numerical Recipes in Fortran 90, 
  !! and provide a way for generating random numbers of 'better quality' 
  !! in a faster way than build-in Fortran random generators (at least  
  !! better than those of Fortran 77). For more details we refer the user 
  !! to Numerical Recipes in Fortran 90.

#ifdef __INTEL_COMPILER
  use ifport
#endif
  use korc_types

  IMPLICIT NONE

  ! Parameters and variables used in generator of uniform random numbers
  INTEGER(8), PARAMETER  :: iv = 4101842887655102017_8
  INTEGER(8), PARAMETER  :: iw = 1_8
  INTEGER(8), PARAMETER  :: a = 4294957665_8
  INTEGER(8), PARAMETER  :: b = 4294967295_8
  INTEGER(8), PARAMETER  :: d = 2862933555777941757_8
  INTEGER(8), PARAMETER  :: e = 7046029254386353087_8
  REAL(rp), PARAMETER    :: rcoeff = 5.42101086242752217E-20_rp


  TYPE, PRIVATE :: URAND
     INTEGER(8) :: u
     INTEGER(8) :: v
     INTEGER(8) :: w
  END TYPE URAND


  TYPE(URAND), PRIVATE :: urand_vars
  ! Parameters and variables used in generator of uniform random numbers


  INTERFACE u_random
     module procedure rand_int64,rand_int32,rand_real,rand_real_array
  END INTERFACE u_random


  PUBLIC :: init_u_random, u_random
  PRIVATE :: rand_int64,rand_int32,rand_real

CONTAINS

subroutine init_u_random(seed)
	INTEGER(8), INTENT(IN) :: seed
	INTEGER(8)             :: dummy_int64

	urand_vars%u = seed**urand_vars%v
	call rand_int64()
	urand_vars%v = urand_vars%u
	call rand_int64()
	urand_vars%w = urand_vars%v
	call rand_int64()
end subroutine init_u_random


subroutine rand_int64(irand)
	INTEGER(8), OPTIONAL, INTENT(OUT)  :: irand
	INTEGER(8)                         :: x


	urand_vars%u = urand_vars%u*d + e !u=u* 2862933555777941757LL + 7046029254386353087LL;

	urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,-17)) ! v^=v>>17;
	urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,31)) ! v^=v<<31;
	urand_vars%v = IEOR(urand_vars%v,ISHFT(urand_vars%v,-8)) ! v^=v>>8;

	urand_vars%w = a*IAND(urand_vars%w,b) + ISHFT(urand_vars%w,-32) ! w = 4294957665U*(w & 0xffffffff) + (w >> 32);

	x = IEOR(urand_vars%u,ISHFT(urand_vars%u,21)) ! Ullong x=u^(u<< 21);
	x = IEOR(x,ISHFT(x,-35)) ! x ^= x >> 35;
	x = IEOR(x,ISHFT(x,4)) ! x ^= x << 4;

	if (PRESENT(irand)) then
		irand = IEOR(x + urand_vars%v,urand_vars%w)
	end if
end subroutine rand_int64


subroutine rand_int32(irand32)
	INTEGER(4), INTENT(OUT)    :: irand32
	INTEGER(8)                 :: irand64

	call rand_int64(irand64)

	irand32 = INT(irand64,4)
end subroutine rand_int32


subroutine rand_real_array(rrand)
	REAL(rp), DIMENSION(:), INTENT(INOUT)  :: rrand
	INTEGER(8)                             :: irand64
    INTEGER                                :: ii ! Iterator

    do ii=1_idef,SIZE(rrand)
        	call rand_int64(irand64)
        rrand(ii) = rcoeff*REAL(irand64,rp) + 0.5_rp
    end do
end subroutine rand_real_array


subroutine rand_real(rrand)
	REAL(rp), INTENT(OUT)  :: rrand
	INTEGER(8)             :: irand64

 	call rand_int64(irand64)
    rrand = rcoeff*REAL(irand64,rp) + 0.5_rp
end subroutine rand_real


subroutine init_random_seed()
#ifdef PARALLEL_RANDOM
  use korc_random
#endif
  INTEGER, allocatable       :: seed(:)
  INTEGER(8), DIMENSION(8)   :: dt
  INTEGER(8)                 :: i
  INTEGER(8)                 :: istat
  INTEGER(8)                 :: pid
  INTEGER(4)                 :: n
  INTEGER(8)                 :: t

  call random_seed(size = n)
  allocate(seed(n))
  ! First try if the OS provides a random number generator
  open(default_unit_open, file="/dev/urandom", access="stream", &
       form="unformatted", action="read", status="old", iostat=istat)
  if (istat == 0) then
     read(default_unit_open) seed
     close(default_unit_open)
     
  else
     ! Fallback to XOR:ing the current time and pid. The PID is
     ! useful in case one launches multiple instances of the same
     ! program in parallel.
     call system_clock(t)
     if (t == 0) then
        call date_and_time(values=dt)
        t = (dt(1) - 1970_8) * 365_8 * 24_8 * 60_8 * 60_8 * 1000_8 &
             + dt(2) * 31_8 * 24_8 * 60_8 * 60_8 * 1000_8 &
             + dt(3) * 24_8 * 60_8 * 60_8 * 1000_8 &
             + dt(5) * 60_8 * 60_8 * 1000_8 &
             + dt(6) * 60_8 * 1000_8 &
             + dt(7) * 1000_8 &
             + dt(8)
     end if
     pid = getpid()
     write(output_unit_write,'("PID: ",I15)') pid
     t = ieor(t, int(pid, kind(t)))
     do i = 1, n
        seed(i) = lcg(t)
     end do
  end if
#ifdef PARALLEL_RANDOM
  call initialize_random(seed(1))
  call initialize_random_U(seed(1))
  call initialize_random_N(seed(1))

!  call initialize_random_mkl(seed(1))
#else
  call random_seed(put=seed)
#endif
contains

  ! This simple PRNG might not be good enough for real work, but is
  ! sufficient for seeding a better PRNG.
  function lcg(s)
    INTEGER :: lcg
    INTEGER(8) :: s
    if (s == 0) then
       s = 104729_8
    else
       s = mod(s, 4294967296_8)
    end if
    s = mod(s * 279470273_8, 4294967291_8)
    lcg = int(mod(s, int(huge(0), 8)), kind(0))
  end function lcg
end subroutine init_random_seed

end module korc_rnd_numbers