| 1 |
module sprng_mod |
| 2 |
use definitions, ONLY : DP |
| 3 |
use parameter, ONLY : iseed |
| 4 |
#ifdef MPI |
| 5 |
use mpi_module |
| 6 |
#endif |
| 7 |
implicit none |
| 8 |
PRIVATE |
| 9 |
|
| 10 |
#ifdef MPI |
| 11 |
#define USE_MPI |
| 12 |
#endif |
| 13 |
#define CHECK_POINTERS |
| 14 |
|
| 15 |
|
| 16 |
#include "headers/sprng_f.h" |
| 17 |
|
| 18 |
|
| 19 |
public :: random_gauss |
| 20 |
public :: init_gauss_stream |
| 21 |
public :: gran |
| 22 |
public :: init_random_stream |
| 23 |
public :: get_random_sprng |
| 24 |
|
| 25 |
integer, parameter :: gtype = 3 ! sprng random generator type |
| 26 |
! Combined Multiple Recursive generator |
| 27 |
logical :: is_init_gauss = .false. |
| 28 |
logical :: is_init_ran = .false. |
| 29 |
#ifdef mpi |
| 30 |
integer, parameter :: gauss_stream_number = node + nprocs |
| 31 |
integer, parameter :: ran_stream_number = node |
| 32 |
integer, parameter :: n_streams = 2*nprocs |
| 33 |
#else |
| 34 |
integer, parameter :: gauss_stream_number = 1 |
| 35 |
integer, parameter :: ran_stream_number = 0 |
| 36 |
integer, parameter :: n_streams = 2 |
| 37 |
#endif |
| 38 |
|
| 39 |
|
| 40 |
SPRNG_POINTER gauss_stream |
| 41 |
SPRNG_POINTER ran_stream |
| 42 |
contains |
| 43 |
|
| 44 |
subroutine init_random_stream () |
| 45 |
integer :: junk |
| 46 |
if (is_init_ran) return |
| 47 |
ran_stream = init_sprng(gtype,ran_stream_number, & |
| 48 |
n_streams,iseed,SPRNG_DEFAULT) |
| 49 |
is_init_ran = .true. |
| 50 |
! junk = print_sprng(ran_stream) |
| 51 |
end subroutine init_random_stream |
| 52 |
|
| 53 |
subroutine init_gauss_stream () |
| 54 |
integer :: junk |
| 55 |
! . if stream is already initialized then return |
| 56 |
if (is_init_gauss) return |
| 57 |
|
| 58 |
gauss_stream = init_sprng(gtype,gauss_stream_number, & |
| 59 |
n_streams,iseed,SPRNG_DEFAULT) |
| 60 |
is_init_gauss = .true. |
| 61 |
|
| 62 |
! junk = print_sprng(gauss_stream) |
| 63 |
end subroutine init_gauss_stream |
| 64 |
|
| 65 |
function get_random_sprng () result(ran_n) |
| 66 |
real( kind = DP ) :: ran_n |
| 67 |
if(.not. is_init_ran) then |
| 68 |
call init_random_stream() |
| 69 |
endif |
| 70 |
|
| 71 |
ran_n = sprng(ran_stream) |
| 72 |
return |
| 73 |
end function get_random_sprng |
| 74 |
|
| 75 |
function random_gauss () result(X) |
| 76 |
use constants, ONLY : twopi |
| 77 |
real( kind = dp ) :: X,Y |
| 78 |
real( kind = dp ) :: R1,R2 |
| 79 |
real( kind = dp ) :: rn1,rn2 |
| 80 |
! . if the gauss stream has not been initialized then init |
| 81 |
if(.not. is_init_gauss) then |
| 82 |
call init_gauss_stream() |
| 83 |
endif |
| 84 |
|
| 85 |
|
| 86 |
rn1 = sprng(gauss_stream) |
| 87 |
rn2 = sprng(gauss_stream) |
| 88 |
|
| 89 |
|
| 90 |
R1 = sqrt(-2.0_DP * log(rn1)) |
| 91 |
R2 = twopi * rn2 |
| 92 |
|
| 93 |
X = R1*cos(R2) |
| 94 |
|
| 95 |
end function random_gauss |
| 96 |
|
| 97 |
!*********************************************************************** |
| 98 |
! qran is a (quick) normal, linear congruential random number |
| 99 |
! generator with "well-chosen" constants taken from Numerical |
| 100 |
! Recipes. Call it with a positive integer seed, it'll change that |
| 101 |
! seed and return a number in [0,1]...sjs 3/18/92 |
| 102 |
!*********************************************************************** |
| 103 |
! Note: Numerical Recipes doesn't SAVE the variables, which it |
| 104 |
! should. |
| 105 |
!*********************************************************************** |
| 106 |
function qran(iseed) result(random) |
| 107 |
! |
| 108 |
integer, parameter :: imod = 134456 |
| 109 |
integer, parameter :: imult = 3887 |
| 110 |
integer, parameter :: iadd = 29573 |
| 111 |
integer :: iseed |
| 112 |
|
| 113 |
real( kind = DP ) :: random |
| 114 |
! |
| 115 |
save |
| 116 |
! |
| 117 |
iseed = mod(imult * iseed + iadd, imod) |
| 118 |
random = dble(iseed) / dble(imod) |
| 119 |
return |
| 120 |
end function qran |
| 121 |
!*********************************************************************** |
| 122 |
! gran is a (good) more reliable random number generator based on 3 |
| 123 |
! linear congruential cycles, with shuffling. It was taken straight |
| 124 |
! from Numerical Recipes....sjs 3/18/92 |
| 125 |
!*********************************************************************** |
| 126 |
! Note: Numerical Recipes doesn't SAVE the variables, which it |
| 127 |
! should. |
| 128 |
!*********************************************************************** |
| 129 |
function gran(iseed) result(random) |
| 130 |
|
| 131 |
logical init |
| 132 |
integer isize, imod1, imult1, iadd1 |
| 133 |
integer imod2, imult2, iadd2 |
| 134 |
integer imod3, imult3, iadd3 |
| 135 |
integer iseed, iseed1, iseed2, iseed3, islot |
| 136 |
real( kind = DP ) :: div1, div2 |
| 137 |
real( kind = DP ) :: random |
| 138 |
! |
| 139 |
parameter (isize = 97) |
| 140 |
parameter (imod1 = 259200, imult1 = 7141, iadd1 = 54773, & |
| 141 |
div1 = 1.E0_DP / imod1) |
| 142 |
parameter (imod2 = 134456, imult2 = 8121, iadd2 = 28411, & |
| 143 |
div2 = 1.E0_DP / imod2) |
| 144 |
parameter (imod3 = 243000, imult3 = 4561, iadd3 = 51349) |
| 145 |
! |
| 146 |
save |
| 147 |
! |
| 148 |
real( kind = DP ) :: store(isize) |
| 149 |
! |
| 150 |
data init/.true./ |
| 151 |
! |
| 152 |
if (iseed .lt. 0 .or. init) then |
| 153 |
init = .false. |
| 154 |
iseed1 = mod(iadd1 - iseed, imod1) |
| 155 |
iseed1 = mod(imult1 * iseed1 + iadd1, imod1) |
| 156 |
iseed2 = mod(iseed1, imod2) |
| 157 |
iseed1 = mod(imult1 * iseed1 + iadd1, imod1) |
| 158 |
iseed3 = mod(iseed1, imod3) |
| 159 |
do islot = 1, isize |
| 160 |
iseed1 = mod(imult1 * iseed1 + iadd1, imod1) |
| 161 |
iseed2 = mod(imult2 * iseed2 + iadd2, imod2) |
| 162 |
store(islot) = (dble(iseed1) + dble(iseed2) * div2) * div1 |
| 163 |
end do |
| 164 |
! iseed = 1 |
| 165 |
end if |
| 166 |
iseed1 = mod(imult1 * iseed1 + iadd1, imod1) |
| 167 |
iseed2 = mod(imult2 * iseed2 + iadd2, imod2) |
| 168 |
iseed3 = mod(imult3 * iseed3 + iadd3, imod3) |
| 169 |
islot = 1 + (isize * iseed3) / imod3 |
| 170 |
random = store(islot) |
| 171 |
store(islot) = (dble(iseed1) + dble(iseed2) * div2) * div1 |
| 172 |
return |
| 173 |
end function gran |
| 174 |
|
| 175 |
|
| 176 |
|
| 177 |
end module sprng_mod |